Feat: lab 3 w/o adv 2
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
|||||||
**.elf
|
**.elf
|
||||||
**.cpio
|
**.cpio
|
||||||
.gdb_history
|
.gdb_history
|
||||||
|
userprog/userprog
|
||||||
|
|||||||
9
Makefile
9
Makefile
@@ -10,6 +10,7 @@ QEMUFLAGS += -M raspi3b -display none -serial null
|
|||||||
|
|
||||||
CC := $(GNU)-gcc
|
CC := $(GNU)-gcc
|
||||||
CCFLAGS += -Wall -Wextra -O0 \
|
CCFLAGS += -Wall -Wextra -O0 \
|
||||||
|
-mcpu=cortex-a53+nofp+nosimd \
|
||||||
-nostdinc -nostdlib -nostartfiles -nodefaultlibs \
|
-nostdinc -nostdlib -nostartfiles -nodefaultlibs \
|
||||||
-Wno-unused-parameter -Wno-unused-value -Wno-main -g
|
-Wno-unused-parameter -Wno-unused-value -Wno-main -g
|
||||||
LD := $(GNU)-ld
|
LD := $(GNU)-ld
|
||||||
@@ -55,7 +56,7 @@ all: $(CPIO)
|
|||||||
build: $(IMG)
|
build: $(IMG)
|
||||||
|
|
||||||
$(CPIO): $(shell find $(ROOTFS_DIR)) userprog
|
$(CPIO): $(shell find $(ROOTFS_DIR)) userprog
|
||||||
cp userprog.img $(ROOTFS_DIR)/userprog
|
cp userprog/userprog $(ROOTFS_DIR)/userprog
|
||||||
cd $(ROOTFS_DIR) && find . | cpio -o -H newc > ../$@
|
cd $(ROOTFS_DIR) && find . | cpio -o -H newc > ../$@
|
||||||
|
|
||||||
$(IMG): $(ELF)
|
$(IMG): $(ELF)
|
||||||
@@ -74,9 +75,9 @@ $(ELF): $(LD_SCRIPT) $(TARGET_OBJS) $(OBJS)
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm $(OBJS) $(CPIO) $(ROOTFS_DIR)/userprog
|
-rm $(OBJS) $(CPIO) $(ROOTFS_DIR)/userprog
|
||||||
|
$(MAKE) $(MAKEFLAGS) -C userprog clean
|
||||||
$(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=kernel TARGET=kernel8
|
$(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=kernel TARGET=kernel8
|
||||||
$(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=bootloader TARGET=bootloader
|
$(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=bootloader TARGET=bootloader
|
||||||
$(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=userprog TARGET=userprog
|
|
||||||
|
|
||||||
clean_target:
|
clean_target:
|
||||||
-rm $(TARGET_OBJS) $(ELF) $(IMG)
|
-rm $(TARGET_OBJS) $(ELF) $(IMG)
|
||||||
@@ -90,10 +91,10 @@ kernel: $(CPIO)
|
|||||||
|
|
||||||
bootloader: $(CPIO)
|
bootloader: $(CPIO)
|
||||||
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=bootloader TARGET=bootloader
|
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=bootloader TARGET=bootloader
|
||||||
$(QEMU) -kernel bootloader.img $(QEMUFLAGS)
|
$(QEMU) -kernel bootloader.img $(QEMUFLAGS) -serial stdio
|
||||||
|
|
||||||
userprog:
|
userprog:
|
||||||
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=userprog TARGET=userprog
|
$(MAKE) $(MAKEFLAGS) -C userprog
|
||||||
|
|
||||||
debug: $(CPIO)
|
debug: $(CPIO)
|
||||||
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8
|
$(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
void uart_init();
|
void uart_init();
|
||||||
void uart_send(unsigned int c);
|
void uart_send(uint32_t c);
|
||||||
uint8_t uart_getb();
|
uint8_t uart_getb();
|
||||||
char uart_getc();
|
char uart_getc();
|
||||||
void uart_puts(const char *s);
|
void uart_puts(const char *s);
|
||||||
void uart_hex(uint64_t d);
|
void uart_hex(uint64_t d);
|
||||||
|
|
||||||
extern int is_uart_init;
|
extern int is_uart_inited;
|
||||||
@@ -16,9 +16,7 @@
|
|||||||
#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE + 0x00215064))
|
#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE + 0x00215064))
|
||||||
#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE + 0x00215068))
|
#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE + 0x00215068))
|
||||||
|
|
||||||
#define ARMINT_En_IRQs1 ((volatile unsigned int*)(MMIO_BASE + 0x0000b210))
|
int is_uart_inited = 0;
|
||||||
|
|
||||||
int is_uart_init = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set baud rate and characteristics (115200 8N1) and map to GPIO
|
* Set baud rate and characteristics (115200 8N1) and map to GPIO
|
||||||
@@ -29,7 +27,6 @@ void uart_init()
|
|||||||
|
|
||||||
/* initialize UART */
|
/* initialize UART */
|
||||||
*AUX_ENABLE |= 1; // enable UART1, AUX mini uart
|
*AUX_ENABLE |= 1; // enable UART1, AUX mini uart
|
||||||
*AUX_MU_IER = 1;
|
|
||||||
*AUX_MU_CNTL = 0;
|
*AUX_MU_CNTL = 0;
|
||||||
*AUX_MU_LCR = 3; // 8 bits
|
*AUX_MU_LCR = 3; // 8 bits
|
||||||
*AUX_MU_MCR = 0;
|
*AUX_MU_MCR = 0;
|
||||||
@@ -48,9 +45,7 @@ void uart_init()
|
|||||||
*GPPUDCLK0 = 0; // flush GPIO setup
|
*GPPUDCLK0 = 0; // flush GPIO setup
|
||||||
*AUX_MU_CNTL = 3; // enable Tx, Rx
|
*AUX_MU_CNTL = 3; // enable Tx, Rx
|
||||||
|
|
||||||
*ARMINT_En_IRQs1 |= (1 << 29);
|
is_uart_inited = 1;
|
||||||
|
|
||||||
is_uart_init = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define NO_ERROR 0x00000000
|
||||||
#define ERR_NO_MEM 0x00000001
|
#define ERR_NO_MEM 0x00000001
|
||||||
#define ERR_UNREACHABLE 0x00000002
|
#define ERR_UNREACHABLE 0x00000002
|
||||||
#define ERR_CONVERSION 0x00000003
|
#define ERR_CONVERSION 0x00000003
|
||||||
@@ -7,4 +8,5 @@
|
|||||||
#define ERR_INVALID_OP 0x00000005
|
#define ERR_INVALID_OP 0x00000005
|
||||||
#define ERR_INVALID_MEM 0x00000006
|
#define ERR_INVALID_MEM 0x00000006
|
||||||
#define ERR_NOT_EXIST 0x00000007
|
#define ERR_NOT_EXIST 0x00000007
|
||||||
|
#define ERR_IO_FAILED 0x00000008
|
||||||
#define ERR_ADMINKILL 0x00114514
|
#define ERR_ADMINKILL 0x00114514
|
||||||
|
|||||||
@@ -34,6 +34,13 @@ static inline char *_logger_pointer(char *dest, void *x)
|
|||||||
return _logger_hex(dest, (uint64_t)x);
|
return _logger_hex(dest, (uint64_t)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _uart_puts_sync(const char *s)
|
||||||
|
{
|
||||||
|
while (*s != '\0')
|
||||||
|
uart_putb_sync((const uint8_t *)s++, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#define _I_HATE_C_LANG(msg) \
|
#define _I_HATE_C_LANG(msg) \
|
||||||
logger_cur = _Generic((msg), \
|
logger_cur = _Generic((msg), \
|
||||||
char * : _do_nothing, \
|
char * : _do_nothing, \
|
||||||
@@ -54,9 +61,9 @@ logger_cur = _Generic((msg), \
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define FLUSH(prefix) { \
|
#define FLUSH(prefix) { \
|
||||||
uart_puts(prefix); \
|
_uart_puts_sync(prefix); \
|
||||||
uart_puts(logger_buf); \
|
_uart_puts_sync(logger_buf); \
|
||||||
uart_puts(ENDL); \
|
_uart_puts_sync(ENDL); \
|
||||||
logger_cur = logger_buf; \
|
logger_cur = logger_buf; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define true 1
|
#define true 0x1
|
||||||
#define false 0
|
#define false 0x0
|
||||||
|
|
||||||
#define ENDL "\r\n"
|
#define ENDL "\r\n"
|
||||||
|
|
||||||
#define NAME_MAX 255
|
#define NAME_MAX 255
|
||||||
#define PATH_MAX 4096
|
#define PATH_MAX 4096
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
int strcmp(const char *lhs, const char *rhs);
|
int strcmp(const char *lhs, const char *rhs);
|
||||||
char *strcpy(char *destination, const char *source);
|
char *strcpy(char *destination, const char *source);
|
||||||
size_t strlen(const char *str);
|
size_t strlen(const char *str);
|
||||||
|
char *strtok_r(char *str, const char *delimiters, char **saveptr);
|
||||||
|
|
||||||
void *memcpy(void *dest, const void *src, size_t count);
|
void *memcpy(void *dest, const void *src, size_t count);
|
||||||
void *memzero(void *start, void *end);
|
void *memzero(void *start, void *end);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ _start:
|
|||||||
mrs x1, mpidr_el1
|
mrs x1, mpidr_el1
|
||||||
and x1, x1, #3
|
and x1, x1, #3
|
||||||
cbz x1, run
|
cbz x1, run
|
||||||
// cpu id > 0, stop
|
// cpu id > 0, fallback to wait
|
||||||
wait:
|
wait:
|
||||||
wfe
|
wfe
|
||||||
b wait
|
b wait
|
||||||
|
|||||||
@@ -2,16 +2,5 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
|
|
||||||
#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060)
|
|
||||||
|
|
||||||
enum :uint32_t {
|
|
||||||
CNTPNSIRQ_INT = ((uint32_t)1 << 1),
|
|
||||||
GPU_INT = ((uint32_t)1 << 8)
|
|
||||||
};
|
|
||||||
|
|
||||||
void init_interrupt(void);
|
void init_interrupt(void);
|
||||||
void irq_handler(void);
|
void irq_handler(void);
|
||||||
|
|
||||||
void enable_interrupt(void);
|
|
||||||
void disable_interrupt(void);
|
|
||||||
|
|||||||
14
kernel/include/ringbuffer.h
Normal file
14
kernel/include/ringbuffer.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t size;
|
||||||
|
size_t cap;
|
||||||
|
uint8_t *data;
|
||||||
|
uint8_t *read, *write;
|
||||||
|
} ringbuffer_t;
|
||||||
|
|
||||||
|
ringbuffer_t *make_ringbuffer(size_t size);
|
||||||
|
int ringbuffer_push(ringbuffer_t *buf, uint8_t val);
|
||||||
|
uint8_t ringbuffer_bump(ringbuffer_t *buf);
|
||||||
27
kernel/include/timer.h
Normal file
27
kernel/include/timer.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef void (*task_callback_func_t)(uint64_t);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t firing_tick;
|
||||||
|
uint64_t interval;
|
||||||
|
uint64_t repeat;
|
||||||
|
|
||||||
|
task_callback_func_t func;
|
||||||
|
uint64_t param;
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
typedef struct timer {
|
||||||
|
struct timer *_l, *_r;
|
||||||
|
uint32_t _d;
|
||||||
|
|
||||||
|
task_t data;
|
||||||
|
} timer_t;
|
||||||
|
|
||||||
|
void add_task(task_t task);
|
||||||
|
|
||||||
|
void timer_irq_handler(void);
|
||||||
|
|
||||||
|
extern timer_t *global_timer;
|
||||||
25
kernel/include/uart.h
Normal file
25
kernel/include/uart.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <ringbuffer.h>
|
||||||
|
|
||||||
|
#define UART_BUFLEN 0x800
|
||||||
|
|
||||||
|
void uart_init(void);
|
||||||
|
char uart_getc(void);
|
||||||
|
void uart_puts(const char *s);
|
||||||
|
void uart_hex(uint64_t d);
|
||||||
|
|
||||||
|
void uart_irq_handler(void);
|
||||||
|
|
||||||
|
size_t uart_putb_sync(const uint8_t *bytes, size_t len);
|
||||||
|
size_t uart_getb_sync(uint8_t *bytes, size_t len);
|
||||||
|
|
||||||
|
size_t uart_putb_async(const uint8_t *bytes, size_t len);
|
||||||
|
size_t uart_getb_async(uint8_t *bytes, size_t len);
|
||||||
|
|
||||||
|
extern size_t (*uart_putb)(const uint8_t *bytes, size_t len);
|
||||||
|
extern size_t (*uart_getb)(uint8_t *bytes, size_t len);
|
||||||
|
extern int is_uart_inited;
|
||||||
|
|
||||||
|
extern ringbuffer_t *uart_readbuf;
|
||||||
@@ -45,8 +45,16 @@ void exit(int);
|
|||||||
|
|
||||||
#define W_SYSREG(reg, val) \
|
#define W_SYSREG(reg, val) \
|
||||||
asm volatile( \
|
asm volatile( \
|
||||||
"msr " #reg ", %[a]" \
|
"mov x0, %[a]" ENDL \
|
||||||
|
"msr " #reg ", x0" ENDL \
|
||||||
:: [a] "r" (val) \
|
:: [a] "r" (val) \
|
||||||
|
: "x0" \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define W_SYSREG_IMM(reg, val) \
|
||||||
|
asm volatile( \
|
||||||
|
"msr " #reg ", %[a]" \
|
||||||
|
:: [a] "i" (val) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define R_REG(ret, reg) \
|
#define R_REG(ret, reg) \
|
||||||
@@ -54,3 +62,17 @@ void exit(int);
|
|||||||
"mov %[a], " #reg \
|
"mov %[a], " #reg \
|
||||||
: [a] "=r" (ret) \
|
: [a] "=r" (ret) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#define W_REG(reg, val) \
|
||||||
|
asm volatile( \
|
||||||
|
"mov " #reg ", %[a]" \
|
||||||
|
:: [a] "r" (val) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define MMIO_W_HELPER(name, reg, mask, offset) \
|
||||||
|
static inline void name(uint64_t state) \
|
||||||
|
{ *reg = (*reg & ~((mask) << (offset))) | ((state & (mask)) << (offset)); }
|
||||||
|
|
||||||
|
#define MMIO_R_HELPER(name, reg, mask, offset) \
|
||||||
|
static inline uint64_t name(void) \
|
||||||
|
{ return (*reg >> (offset)) & (mask); }
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ void not_implemented_handler()
|
|||||||
|
|
||||||
void synchronous_handler()
|
void synchronous_handler()
|
||||||
{
|
{
|
||||||
static int count = 0;
|
static int poop = 0;
|
||||||
if (count++ > 5)
|
if (poop++ > 5)
|
||||||
exit(ERR_ADMINKILL);
|
exit(ERR_ADMINKILL);
|
||||||
DEBUG_EXCEP("synchronous caught");
|
DEBUG_EXCEP("synchronous caught");
|
||||||
uint64_t x0 = 0x0;
|
uint64_t x0 = 0x0;
|
||||||
|
|||||||
@@ -1,58 +1,45 @@
|
|||||||
#include <interrupt.h>
|
#include <interrupt.h>
|
||||||
|
#include <uart.h>
|
||||||
|
#include <timer.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
#include <logger.h>
|
#include <logger.h>
|
||||||
#include <errcode.h>
|
#include <errcode.h>
|
||||||
|
|
||||||
|
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
|
||||||
|
#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060)
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _enable_interrupt(void)
|
||||||
|
{ W_SYSREG_IMM(DAIFClr, 0xf); }
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _disable_interrupt(void)
|
||||||
|
{ W_SYSREG_IMM(DAIFSet, 0xf); }
|
||||||
|
|
||||||
|
MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
|
||||||
|
|
||||||
|
MMIO_R_HELPER(_irq_source_timer, CORE0_IRQ_SOURCE, 0x1, 1);
|
||||||
|
MMIO_R_HELPER(_irq_source_uart, CORE0_IRQ_SOURCE, 0x1, 8);
|
||||||
|
|
||||||
void init_interrupt(void)
|
void init_interrupt(void)
|
||||||
{
|
{
|
||||||
uint64_t cntfrq_el0;
|
uint64_t cntfrq_el0;
|
||||||
|
W_SYSREG(cntp_ctl_el0, 1);
|
||||||
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||||
W_SYSREG(cntp_tval_el0, cntfrq_el0);
|
W_SYSREG(cntp_tval_el0, cntfrq_el0);
|
||||||
|
|
||||||
*CORE0_TIMER_IRQ_CTRL = 0x2;
|
_enable_timer_irq(true);
|
||||||
}
|
_enable_interrupt();
|
||||||
|
|
||||||
static inline
|
|
||||||
void _uart_irq_handler(void)
|
|
||||||
{
|
|
||||||
DEBUG_EXCEP("uart irq");
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
void _timer_irq_handler(void)
|
|
||||||
{
|
|
||||||
LOG("timer irq");
|
|
||||||
|
|
||||||
uint64_t cntpct_el0;
|
|
||||||
R_SYSREG(cntpct_el0, cntpct_el0);
|
|
||||||
DEBUG_EXCEP(cntpct_el0);
|
|
||||||
|
|
||||||
uint64_t cntfrq_el0;
|
|
||||||
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
|
||||||
W_SYSREG(cntp_tval_el0, cntfrq_el0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_handler(void)
|
void irq_handler(void)
|
||||||
{
|
{
|
||||||
LOG("irq caught");
|
// uint64_t core0_irq_source = *CORE0_IRQ_SOURCE;
|
||||||
uint64_t irq_source = *CORE0_IRQ_SOURCE;
|
// DEBUG_EXCEP(core0_irq_source);
|
||||||
DEBUG_EXCEP(irq_source);
|
|
||||||
|
|
||||||
*CORE0_TIMER_IRQ_CTRL = 0x0;
|
if (_irq_source_timer())
|
||||||
if (irq_source & GPU_INT)
|
timer_irq_handler();
|
||||||
_uart_irq_handler();
|
|
||||||
if (irq_source & CNTPNSIRQ_INT)
|
|
||||||
_timer_irq_handler();
|
|
||||||
|
|
||||||
*CORE0_TIMER_IRQ_CTRL = 0x2;
|
if (_irq_source_uart())
|
||||||
}
|
uart_irq_handler();
|
||||||
|
|
||||||
void enable_interrupt(void)
|
|
||||||
{
|
|
||||||
asm volatile("msr DAIFClr, 0xf");
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable_interrupt(void)
|
|
||||||
{
|
|
||||||
asm volatile("msr DAIFSet, 0xf");
|
|
||||||
}
|
}
|
||||||
|
|||||||
47
kernel/lib/ringbuffer.c
Normal file
47
kernel/lib/ringbuffer.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include <ringbuffer.h>
|
||||||
|
#include <utils.h>
|
||||||
|
#include <errcode.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <kmalloc.h>
|
||||||
|
|
||||||
|
ringbuffer_t *make_ringbuffer(size_t size)
|
||||||
|
{
|
||||||
|
ringbuffer_t *ret = kmalloc(sizeof(ringbuffer_t));
|
||||||
|
uint8_t *data = kmalloc(size * sizeof(uint8_t));
|
||||||
|
*ret = (ringbuffer_t){
|
||||||
|
.size = 0,
|
||||||
|
.cap = size,
|
||||||
|
.data = data,
|
||||||
|
.read = data,
|
||||||
|
.write = data,
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ringbuffer_push(ringbuffer_t *buf, uint8_t val)
|
||||||
|
{
|
||||||
|
if (buf->size == buf->cap)
|
||||||
|
return ERR_OUT_OF_BOUND;
|
||||||
|
|
||||||
|
*buf->write++ = val;
|
||||||
|
++buf->size;
|
||||||
|
|
||||||
|
if (buf->write == buf->data + buf->cap)
|
||||||
|
buf->write = buf->data;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ringbuffer_bump(ringbuffer_t *buf)
|
||||||
|
{
|
||||||
|
if (buf->size == 0)
|
||||||
|
exit(ERR_INVALID_OP);
|
||||||
|
|
||||||
|
uint8_t ret = *buf->read++;
|
||||||
|
--buf->size;
|
||||||
|
|
||||||
|
if (buf->read == buf->data + buf->cap)
|
||||||
|
buf->read = buf->data;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <logger.h>
|
||||||
|
#include <timer.h>
|
||||||
#include <errcode.h>
|
#include <errcode.h>
|
||||||
#include <kmalloc.h>
|
#include <kmalloc.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
@@ -109,6 +111,35 @@ void _exec(file_node_t *root, const char *filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _settimeout_cb_func(uint64_t args)
|
||||||
|
{
|
||||||
|
vector_t *v = (void *)args;
|
||||||
|
for (int i = 2; i < (int)v->size; ++i) {
|
||||||
|
uart_puts(VEC_AT(char, v, i));
|
||||||
|
uart_puts(" ");
|
||||||
|
}
|
||||||
|
uart_puts(ENDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _settimeout(int32_t sec, vector_t *args)
|
||||||
|
{
|
||||||
|
uint64_t cntpct_el0, cntfrq_el0;
|
||||||
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||||
|
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||||
|
|
||||||
|
task_t task = (task_t){
|
||||||
|
.firing_tick = cntpct_el0 + sec * cntfrq_el0,
|
||||||
|
.interval = sec * cntfrq_el0,
|
||||||
|
.repeat = 1,
|
||||||
|
|
||||||
|
.func = _settimeout_cb_func,
|
||||||
|
.param = (uint64_t)args,
|
||||||
|
};
|
||||||
|
add_task(task);
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void _set(long addr, unsigned int value) {
|
void _set(long addr, unsigned int value) {
|
||||||
volatile unsigned int* point = (unsigned int*)addr;
|
volatile unsigned int* point = (unsigned int*)addr;
|
||||||
@@ -130,45 +161,47 @@ void _reboot(void)
|
|||||||
int shell(file_node_t *initrd_root)
|
int shell(file_node_t *initrd_root)
|
||||||
{
|
{
|
||||||
uart_puts("# ");
|
uart_puts("# ");
|
||||||
|
char *buf = kmalloc(INPUT_BUFLEN * sizeof(char)), ch;
|
||||||
char buf[INPUT_BUFLEN], ch;
|
|
||||||
int sz = 0;
|
int sz = 0;
|
||||||
while ((ch = uart_getc()) != '\n') {
|
while ((ch = uart_getc()) != '\n') {
|
||||||
buf[sz++] = ch;
|
buf[sz++] = ch;
|
||||||
uart_send(ch);
|
uart_putb((const uint8_t *)&ch, 1);
|
||||||
}
|
}
|
||||||
uart_puts(ENDL);
|
uart_puts(ENDL);
|
||||||
buf[sz] = '\0';
|
buf[sz] = ' ';
|
||||||
|
|
||||||
const char *i = buf;
|
vector_t *args = make_vector(0);
|
||||||
|
for (char *saveptr = 0x0, *tok = strtok_r(buf, " ", &saveptr);
|
||||||
|
tok; tok = strtok_r((char *)0x0, " ", &saveptr)) {
|
||||||
|
VEC_PUSH(args, tok);
|
||||||
|
LOG(tok);
|
||||||
|
}
|
||||||
|
|
||||||
char bin[INPUT_BUFLEN], *j;
|
// DEBUG("ENDL");
|
||||||
for (j = bin; *i != '\0' && !isspace(*i); ++i, ++j)
|
CLEAN;
|
||||||
*j = *i;
|
|
||||||
*j = '\0';
|
|
||||||
|
|
||||||
for (; *i != '\0' && isspace(*i); ++i);
|
char *cmd = args->size ? VEC_AT(char, args, 0) : (char *)0x0;
|
||||||
|
if (!strcmp(cmd, "help")) {
|
||||||
char param[INPUT_BUFLEN];
|
|
||||||
for (j = param; *i != '\0' && !isspace(*i); ++i, ++j)
|
|
||||||
*j = *i;
|
|
||||||
*j = '\0';
|
|
||||||
|
|
||||||
if (!strcmp(bin, "help")) {
|
|
||||||
_help();
|
_help();
|
||||||
} else if (!strcmp(bin, "hello")) {
|
} else if (!strcmp(cmd, "hello")) {
|
||||||
_hello();
|
_hello();
|
||||||
} else if (!strcmp(bin, "hwinfo")) {
|
} else if (!strcmp(cmd, "hwinfo")) {
|
||||||
_hwinfo();
|
_hwinfo();
|
||||||
} else if (!strcmp(bin, "memalloc")){
|
} else if (!strcmp(cmd, "memalloc") && args->size >= 2){
|
||||||
_memalloc((size_t)atoi32(param));
|
char *p1 = VEC_AT(char, args, 1);
|
||||||
} else if (!strcmp(bin, "ls")) {
|
_memalloc((size_t)atoi32(p1));
|
||||||
|
} else if (!strcmp(cmd, "ls")) {
|
||||||
_ls(initrd_root);
|
_ls(initrd_root);
|
||||||
} else if (!strcmp(bin, "cat")) {
|
} else if (!strcmp(cmd, "cat") && args->size >= 2) {
|
||||||
_cat(initrd_root, param);
|
char *p1 = VEC_AT(char, args, 1);
|
||||||
} else if (!strcmp(bin, "exec")) {
|
_cat(initrd_root, p1);
|
||||||
_exec(initrd_root, param);
|
} else if (!strcmp(cmd, "exec") && args->size >= 2) {
|
||||||
} else if (!strcmp(bin, "reboot")) {
|
char *p1 = VEC_AT(char, args, 1);
|
||||||
|
_exec(initrd_root, p1);
|
||||||
|
} else if (!strcmp(cmd, "settimeout") && args->size >= 2) {
|
||||||
|
char *p1 = VEC_AT(char, args, 1);
|
||||||
|
_settimeout(atoi32(p1), args);
|
||||||
|
} else if (!strcmp(cmd, "reboot")) {
|
||||||
_reboot();
|
_reboot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
95
kernel/lib/timer.c
Normal file
95
kernel/lib/timer.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include <timer.h>
|
||||||
|
#include <logger.h>
|
||||||
|
#include <utils.h>
|
||||||
|
#include <kmalloc.h>
|
||||||
|
|
||||||
|
#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040)
|
||||||
|
|
||||||
|
timer_t *global_timer = (timer_t *)0x0;
|
||||||
|
|
||||||
|
MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1);
|
||||||
|
|
||||||
|
static inline
|
||||||
|
uint32_t _d(timer_t *t)
|
||||||
|
{ return t ? t->_d : 0; }
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _swap(timer_t *a, timer_t *b)
|
||||||
|
{
|
||||||
|
timer_t *tmp = a;
|
||||||
|
a = b, b = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
timer_t *_merge(timer_t *a, timer_t *b)
|
||||||
|
{
|
||||||
|
if (!a || !b)
|
||||||
|
return a ?: b;
|
||||||
|
|
||||||
|
if (a->data.firing_tick > b->data.firing_tick)
|
||||||
|
_swap(a, b);
|
||||||
|
a->_r = _merge(a->_r, b);
|
||||||
|
|
||||||
|
if (_d(a->_l) < _d(a->_r))
|
||||||
|
_swap(a->_l, a->_r);
|
||||||
|
|
||||||
|
a->_d = _d(a->_r) + 1;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
timer_t *_pop(timer_t *t)
|
||||||
|
{
|
||||||
|
if (!t || (!t->_l && !t->_r))
|
||||||
|
return (timer_t *)0x0;
|
||||||
|
return _merge(t->_l, t->_r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _set_timer_interrrupt()
|
||||||
|
{
|
||||||
|
if (global_timer) {
|
||||||
|
uint64_t cntpct_el0;
|
||||||
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||||
|
DEBUG_EXCEP(cntpct_el0);
|
||||||
|
|
||||||
|
uint64_t firing_tick = MAX(global_timer->data.firing_tick, cntpct_el0);
|
||||||
|
W_SYSREG(cntp_cval_el0, firing_tick);
|
||||||
|
|
||||||
|
_enable_timer_irq(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_task(task_t task)
|
||||||
|
{
|
||||||
|
DEBUG_EXCEP("add task");
|
||||||
|
timer_t *newtimer = kmalloc(sizeof(timer_t));
|
||||||
|
*newtimer = (timer_t){
|
||||||
|
._l = (timer_t *)0x0,
|
||||||
|
._r = (timer_t *)0x0,
|
||||||
|
._d = 0,
|
||||||
|
|
||||||
|
.data = task,
|
||||||
|
};
|
||||||
|
|
||||||
|
global_timer = _merge(global_timer, newtimer);
|
||||||
|
_set_timer_interrrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_irq_handler(void)
|
||||||
|
{
|
||||||
|
_enable_timer_irq(false);
|
||||||
|
|
||||||
|
LOG("timer irq");
|
||||||
|
|
||||||
|
uint64_t cntpct_el0;
|
||||||
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||||
|
DEBUG_EXCEP(cntpct_el0);
|
||||||
|
|
||||||
|
if (global_timer) {
|
||||||
|
global_timer->data.func(global_timer->data.param);
|
||||||
|
global_timer = _pop(global_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_set_timer_interrrupt();
|
||||||
|
}
|
||||||
188
kernel/lib/uart.c
Normal file
188
kernel/lib/uart.c
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
#include <uart.h>
|
||||||
|
#include <logger.h>
|
||||||
|
#include <errcode.h>
|
||||||
|
#include <utils.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <gpio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <ringbuffer.h>
|
||||||
|
|
||||||
|
/* Auxilary mini UART registers */
|
||||||
|
#define AUX_ENABLE ((volatile uint32_t*)(MMIO_BASE + 0x00215004))
|
||||||
|
#define AUX_MU_IO ((volatile uint32_t*)(MMIO_BASE + 0x00215040))
|
||||||
|
#define AUX_MU_IER ((volatile uint32_t*)(MMIO_BASE + 0x00215044))
|
||||||
|
#define AUX_MU_IIR ((volatile uint32_t*)(MMIO_BASE + 0x00215048))
|
||||||
|
#define AUX_MU_LCR ((volatile uint32_t*)(MMIO_BASE + 0x0021504C))
|
||||||
|
#define AUX_MU_MCR ((volatile uint32_t*)(MMIO_BASE + 0x00215050))
|
||||||
|
#define AUX_MU_LSR ((volatile uint32_t*)(MMIO_BASE + 0x00215054))
|
||||||
|
#define AUX_MU_MSR ((volatile uint32_t*)(MMIO_BASE + 0x00215058))
|
||||||
|
#define AUX_MU_SCRATCH ((volatile uint32_t*)(MMIO_BASE + 0x0021505C))
|
||||||
|
#define AUX_MU_CNTL ((volatile uint32_t*)(MMIO_BASE + 0x00215060))
|
||||||
|
#define AUX_MU_STAT ((volatile uint32_t*)(MMIO_BASE + 0x00215064))
|
||||||
|
#define AUX_MU_BAUD ((volatile uint32_t*)(MMIO_BASE + 0x00215068))
|
||||||
|
|
||||||
|
#define ARMINT_En_IRQs1 ((volatile uint32_t*)(MMIO_BASE + 0x0000b210))
|
||||||
|
|
||||||
|
size_t (*uart_putb)(const uint8_t *bytes, size_t len) = uart_putb_sync;
|
||||||
|
size_t (*uart_getb)(uint8_t *bytes, size_t len) = uart_getb_sync;
|
||||||
|
int is_uart_inited = false;
|
||||||
|
|
||||||
|
ringbuffer_t *uart_readbuf;
|
||||||
|
ringbuffer_t *uart_writebuf;
|
||||||
|
|
||||||
|
MMIO_W_HELPER(_uart_enable_receive_interrupt, AUX_MU_IER, 0x1, 0);
|
||||||
|
MMIO_W_HELPER(_uart_enable_transmit_interrupt, AUX_MU_IER, 0x1, 1);
|
||||||
|
MMIO_W_HELPER(_uart_clear_receive_fifo, AUX_MU_IIR, 0x1, 1);
|
||||||
|
MMIO_W_HELPER(_uart_clear_transmit_fifo, AUX_MU_IIR, 0x1, 2);
|
||||||
|
MMIO_W_HELPER(_uart_write_data, AUX_MU_IO, 0xff, 0);
|
||||||
|
MMIO_W_HELPER(_uart_interrupt_controller, ARMINT_En_IRQs1, 0x1, 29);
|
||||||
|
|
||||||
|
MMIO_R_HELPER(_uart_interrupt_pending, AUX_MU_IIR, 0x1, 0);
|
||||||
|
MMIO_R_HELPER(_uart_transmit_interrupt, AUX_MU_IIR, 0x1, 1);
|
||||||
|
MMIO_R_HELPER(_uart_receive_interrupt, AUX_MU_IIR, 0x1, 2);
|
||||||
|
MMIO_R_HELPER(_uart_transmitter_idle, AUX_MU_LSR, 0x1, 5);
|
||||||
|
MMIO_R_HELPER(_uart_data_ready, AUX_MU_LSR, 0x1, 0);
|
||||||
|
MMIO_R_HELPER(_uart_read_data, AUX_MU_IO, 0xff, 0);
|
||||||
|
|
||||||
|
void uart_init(void)
|
||||||
|
{
|
||||||
|
register uint32_t r;
|
||||||
|
|
||||||
|
/* initialize UART */
|
||||||
|
*AUX_ENABLE |= 1; // enable UART1, AUX mini uart
|
||||||
|
*AUX_MU_CNTL = 0; // disable Tx, Rx
|
||||||
|
*AUX_MU_LCR = 3; // set 8 bits
|
||||||
|
*AUX_MU_MCR = 0;
|
||||||
|
*AUX_MU_IER = 0; // disable interrupt by default
|
||||||
|
*AUX_MU_IIR = 0x6; // clear tx, rx FIFO
|
||||||
|
*AUX_MU_BAUD = 270; // 115200 baud
|
||||||
|
/* map UART1 to GPIO pins */
|
||||||
|
r = *GPFSEL1;
|
||||||
|
r &= ~((7 << 12) | (7 << 15)); // gpio14, gpio15
|
||||||
|
r |= (2 << 12) | (2 << 15); // alt5
|
||||||
|
*GPFSEL1 = r;
|
||||||
|
*GPPUD = 0; // enable pins 14 and 15
|
||||||
|
r = 150; while (r--) { asm volatile("nop"); }
|
||||||
|
*GPPUDCLK0 = (1 << 14) | (1 << 15);
|
||||||
|
r = 150; while (r--) { asm volatile("nop"); }
|
||||||
|
*GPPUDCLK0 = 0; // flush GPIO setup
|
||||||
|
*AUX_MU_CNTL = 3; // enable Tx, Rx
|
||||||
|
_uart_interrupt_controller(true);
|
||||||
|
|
||||||
|
uart_readbuf = make_ringbuffer(UART_BUFLEN);
|
||||||
|
uart_writebuf = make_ringbuffer(UART_BUFLEN);
|
||||||
|
|
||||||
|
_uart_enable_receive_interrupt(true);
|
||||||
|
//uint64_t ier = *AUX_MU_IER;
|
||||||
|
|
||||||
|
uart_getb = uart_getb_async;
|
||||||
|
uart_putb = uart_putb_async;
|
||||||
|
|
||||||
|
is_uart_inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_transmit_interrupt_handler()
|
||||||
|
{
|
||||||
|
if (uart_writebuf->size > 0)
|
||||||
|
_uart_write_data(ringbuffer_bump(uart_writebuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_receive_interrupt_handler()
|
||||||
|
{
|
||||||
|
if (uart_readbuf->size < uart_readbuf->cap) {
|
||||||
|
uint8_t b = _uart_read_data();
|
||||||
|
ringbuffer_push(uart_readbuf, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_irq_handler(void)
|
||||||
|
{
|
||||||
|
_uart_enable_receive_interrupt(false);
|
||||||
|
_uart_enable_transmit_interrupt(false);
|
||||||
|
if (_uart_receive_interrupt())
|
||||||
|
uart_receive_interrupt_handler();
|
||||||
|
if (_uart_transmit_interrupt())
|
||||||
|
uart_transmit_interrupt_handler();
|
||||||
|
|
||||||
|
_uart_enable_receive_interrupt(true);
|
||||||
|
if (uart_writebuf->size > 0)
|
||||||
|
_uart_enable_transmit_interrupt(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uart_putb_async(const uint8_t *bytes, size_t len)
|
||||||
|
{
|
||||||
|
size_t sentlen = 0;
|
||||||
|
for (; sentlen < len; ++bytes, ++sentlen)
|
||||||
|
ringbuffer_push(uart_writebuf, *bytes);
|
||||||
|
|
||||||
|
if (uart_writebuf->size > 0)
|
||||||
|
_uart_enable_transmit_interrupt(true);
|
||||||
|
|
||||||
|
return sentlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uart_putb_sync(const uint8_t *bytes, size_t len)
|
||||||
|
{
|
||||||
|
size_t sentlen = 0;
|
||||||
|
for (; sentlen < len; ++bytes, ++sentlen) {
|
||||||
|
do asm volatile("nop"); // busy waiting
|
||||||
|
while (!_uart_transmitter_idle());
|
||||||
|
|
||||||
|
_uart_write_data(*bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sentlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uart_getb_async(uint8_t *bytes, size_t len)
|
||||||
|
{
|
||||||
|
size_t recvlen = 0;
|
||||||
|
for (; recvlen < len; ++bytes, ++recvlen) {
|
||||||
|
while (!uart_readbuf->size)
|
||||||
|
asm volatile("wfe"); // wait for interrupt
|
||||||
|
*bytes = ringbuffer_bump(uart_readbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return recvlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t uart_getb_sync(uint8_t *bytes, size_t len)
|
||||||
|
{
|
||||||
|
size_t recvlen = 0;
|
||||||
|
for (; recvlen < len; ++bytes, ++recvlen) {
|
||||||
|
do asm volatile("nop");
|
||||||
|
while (!_uart_data_ready());
|
||||||
|
|
||||||
|
*bytes = _uart_read_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
return recvlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
char uart_getc(void)
|
||||||
|
{
|
||||||
|
char r;
|
||||||
|
uart_getb((uint8_t *)&r, 1);
|
||||||
|
return r == '\r' ? '\n' : r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_puts(const char *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
size_t ret = uart_putb((const uint8_t *)s, len);
|
||||||
|
if (ret != len)
|
||||||
|
exit(ERR_IO_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart_hex(uint64_t d)
|
||||||
|
{
|
||||||
|
char buf[0x11], *p = buf;
|
||||||
|
uint64_t n;
|
||||||
|
for (int c = 28; c >= 0; c -= 4) {
|
||||||
|
n = (d >> c) & 0xf;
|
||||||
|
n += n > 9 ? (char)'A' : (char)'0';
|
||||||
|
*p++ = n;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
uart_puts(buf);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <logger.h>
|
#include <logger.h>
|
||||||
|
#include <timer.h>
|
||||||
#include <kmalloc.h>
|
#include <kmalloc.h>
|
||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
#include <dtb.h>
|
#include <dtb.h>
|
||||||
@@ -35,11 +36,38 @@ void init(void *dtb, file_node_t **initrd_root)
|
|||||||
mman_init();
|
mman_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _print_time(uint64_t)
|
||||||
|
{
|
||||||
|
uint64_t cntpct_el0, cntfrq_el0;
|
||||||
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||||
|
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||||
|
DEBUG_EXCEP(cntpct_el0 / cntpct_el0);
|
||||||
|
}
|
||||||
|
|
||||||
void main(void *dtb)
|
void main(void *dtb)
|
||||||
{
|
{
|
||||||
file_node_t *initrd_root = 0x0;
|
file_node_t *initrd_root = 0x0;
|
||||||
init(dtb, &initrd_root);
|
init(dtb, &initrd_root);
|
||||||
|
|
||||||
|
LOG("system booting in");
|
||||||
|
_print_time(0x0);
|
||||||
|
|
||||||
|
uint64_t cntpct_el0, cntfrq_el0;
|
||||||
|
R_SYSREG(cntpct_el0, cntpct_el0);
|
||||||
|
R_SYSREG(cntfrq_el0, cntfrq_el0);
|
||||||
|
|
||||||
|
task_t task = {
|
||||||
|
.firing_tick = cntpct_el0 + 2 * cntfrq_el0,
|
||||||
|
.interval = 2 * cntfrq_el0,
|
||||||
|
.repeat = 1,
|
||||||
|
|
||||||
|
.func = _print_time,
|
||||||
|
.param = 0x0,
|
||||||
|
};
|
||||||
|
|
||||||
|
add_task(task);
|
||||||
|
|
||||||
uint64_t el;
|
uint64_t el;
|
||||||
R_SYSREG(el, CurrentEL);
|
R_SYSREG(el, CurrentEL);
|
||||||
INFOR(el);
|
INFOR(el);
|
||||||
|
|||||||
15
lib/string.c
15
lib/string.c
@@ -35,6 +35,21 @@ size_t strlen(const char *str)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *strtok_r(char *restrict str, const char *restrict delimiters,
|
||||||
|
char **restrict saveptr)
|
||||||
|
{
|
||||||
|
if (str)
|
||||||
|
*saveptr = str;
|
||||||
|
for (char *ret = *saveptr; **saveptr != '\0'; ++(*saveptr)) {
|
||||||
|
for (int i = 0; delimiters[i] != '\0'; i++)
|
||||||
|
if (**saveptr == delimiters[i]) {
|
||||||
|
*(*saveptr)++ = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
void *memcpy(void *dest, const void *src, size_t count)
|
void *memcpy(void *dest, const void *src, size_t count)
|
||||||
{
|
{
|
||||||
void *ret = dest;
|
void *ret = dest;
|
||||||
|
|||||||
BIN
rootfs/userprog
BIN
rootfs/userprog
Binary file not shown.
13
test.py
13
test.py
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env -S python3
|
|
||||||
from pwn import *
|
|
||||||
from struct import pack
|
|
||||||
|
|
||||||
print(sys.argv)
|
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print("no args for serial device")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
tube = serialtube(sys.argv[1], convert_newlines=False)
|
|
||||||
|
|
||||||
tube.interactive()
|
|
||||||
39
userprog/Makefile
Normal file
39
userprog/Makefile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
MAKE := make
|
||||||
|
MAKEFLAGS += -j 8
|
||||||
|
|
||||||
|
ARCH := aarch64
|
||||||
|
GNU := $(ARCH)-linux-gnu
|
||||||
|
|
||||||
|
CC := $(GNU)-gcc
|
||||||
|
CCFLAGS += -Wall -Wextra -O0 \
|
||||||
|
-nostdinc -nostdlib -nostartfiles -nodefaultlibs \
|
||||||
|
-Wno-unused-parameter -Wno-unused-value -Wno-main -g
|
||||||
|
|
||||||
|
LD := $(GNU)-ld
|
||||||
|
LDFLAGS += -g -nostdlib -no-pie
|
||||||
|
OBJCOPY := $(GNU)-objcopy
|
||||||
|
|
||||||
|
LD_SCRIPT := linker.ld
|
||||||
|
SRCS := $(shell find . -name '*.[cS]')
|
||||||
|
OBJS := $(SRCS:%=%.o)
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
all: userprog
|
||||||
|
|
||||||
|
userprog: userprog.elf
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
userprog.elf: $(LD_SCRIPT) $(OBJS)
|
||||||
|
$(LD) -o $@ -T $(LD_SCRIPT) $(OBJS) $(LDFLAGS)
|
||||||
|
|
||||||
|
%.S.o: %.S
|
||||||
|
mkdir -p $(dir $@)
|
||||||
|
$(CC) -c $< -o $@ $(CCFLAGS)
|
||||||
|
|
||||||
|
%.c.o: %.c
|
||||||
|
mkdir -p $(dir $@)
|
||||||
|
$(CC) -c $< -o $@ $(CCFLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm $(OBJS) userprog userprog.elf
|
||||||
Reference in New Issue
Block a user