hw2 done
This commit is contained in:
21
Makefile
21
Makefile
@@ -2,6 +2,7 @@ MAKE := make
|
||||
|
||||
ARCH := aarch64
|
||||
GNU := $(ARCH)-linux-gnu
|
||||
GDB := $(GNU)-gdb
|
||||
|
||||
QEMU := qemu-system-$(ARCH)
|
||||
QEMUFLAGS += -M raspi3b -display none -serial null -serial pty
|
||||
@@ -9,9 +10,9 @@ QEMUFLAGS += -M raspi3b -display none -serial null -serial pty
|
||||
CC := $(GNU)-gcc
|
||||
CCFLAGS += -Wall -Wextra -O0 \
|
||||
-nostdinc -nostdlib -nostartfiles -nodefaultlibs \
|
||||
-Wno-unused-parameter -Wno-main -g
|
||||
-Wno-unused-parameter -Wno-unused-value -Wno-main -g
|
||||
LD := $(GNU)-ld
|
||||
LDFLAGS += -g -nostdlib
|
||||
LDFLAGS += -g -nostdlib -no-pie
|
||||
OBJCOPY := $(GNU)-objcopy
|
||||
|
||||
#TARGET := kernel8
|
||||
@@ -23,7 +24,7 @@ LD_SCRIPT := $(TARGET_DIR)/linker.ld
|
||||
INCLUDE += -Iinclude
|
||||
LIB_DIR := ./lib
|
||||
MISC_DIR := ./misc
|
||||
#QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb
|
||||
QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb
|
||||
|
||||
BOOTLOADER_DIR := ./bootloader
|
||||
ROOTFS_DIR := ./rootfs
|
||||
@@ -35,7 +36,7 @@ SRCS := $(shell find $(TARGET_DIR) -name '*.[cS]') \
|
||||
$(shell find $(LIB_DIR) -name '*.c')
|
||||
OBJS := $(SRCS:%=%.o)
|
||||
|
||||
.PHONY: all build clean clean_target run
|
||||
.PHONY: all build clean clean_target run kernel debug gdb
|
||||
|
||||
all:
|
||||
$(MAKE) build TARGET_DIR=./kernel TARGET=kernel8
|
||||
@@ -69,4 +70,14 @@ clean_target:
|
||||
|
||||
run: all $(CPIO)
|
||||
$(QEMU) -kernel bootloader.img $(QEMUFLAGS)
|
||||
#$(QEMU) -kernel kernel8.img $(QEMUFLAGS)
|
||||
|
||||
kernel: all $(CPIO)
|
||||
-killall screen
|
||||
$(QEMU) -kernel kernel8.img $(QEMUFLAGS)
|
||||
|
||||
debug: all $(CPIO)
|
||||
-killall screen
|
||||
$(QEMU) -kernel kernel8.img $(QEMUFLAGS) -S -s
|
||||
|
||||
gdb:
|
||||
$(GDB)
|
||||
|
||||
@@ -12,8 +12,9 @@ wait:
|
||||
b wait
|
||||
|
||||
run:
|
||||
// move dtb to x20
|
||||
mov x20, x0
|
||||
adr x0, _start
|
||||
adrp x0, __stack_end
|
||||
mov sp, x0
|
||||
|
||||
adr x0, __text_start
|
||||
@@ -25,6 +26,7 @@ run:
|
||||
adr x1, __bss_end
|
||||
bl memzero
|
||||
|
||||
// move dtb back to x0
|
||||
mov x0, x20
|
||||
bl main
|
||||
b wait
|
||||
@@ -36,7 +38,8 @@ relocate:
|
||||
adr x2, __text_end
|
||||
sub x2, x2, x1
|
||||
bl memcpy
|
||||
mov x19, x0
|
||||
|
||||
mov x19, x0 // save return pointer
|
||||
|
||||
// move rodata section
|
||||
ldr x0, =__new_ro_start
|
||||
@@ -52,5 +55,6 @@ relocate:
|
||||
sub x2, x2, x1
|
||||
bl memcpy
|
||||
|
||||
mov x0, x20
|
||||
br x19
|
||||
b wait
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
ENTRY(_start)
|
||||
MEMORY
|
||||
{
|
||||
NEWTEXT (rx) : ORIGIN = 0x10000, LENGTH = 128K
|
||||
NEWRO (r) : ORIGIN = 0x30000, LENGTH = 128K
|
||||
NEWDATA (rw) : ORIGIN = 0x50000, LENGTH = 64K
|
||||
NEWBSS (rw) : ORIGIN = 0x60000, LENGTH = 64K
|
||||
NEWTEXT (rx) : ORIGIN = 0x10000, LENGTH = 64K
|
||||
NEWRO (r) : ORIGIN = 0x20000, LENGTH = 16K
|
||||
NEWDATA (rw) : ORIGIN = 0x24000, LENGTH = 16K
|
||||
NEWBSS (rw) : ORIGIN = 0x28000, LENGTH = 16K
|
||||
|
||||
TEXT (rx) : ORIGIN = 0x80000, LENGTH = 128K
|
||||
RO (r) : ORIGIN = 0xa0000, LENGTH = 128K
|
||||
DATA (rw) : ORIGIN = 0xc0000, LENGTH = 64K
|
||||
BSS (rw) : ORIGIN = 0xd0000, LENGTH = 64K
|
||||
RAM (rw) : ORIGIN = 0xf0000, LENGTH = 8M
|
||||
TEXT (rx) : ORIGIN = 0x80000, LENGTH = 64K
|
||||
RO (r) : ORIGIN = 0x90000, LENGTH = 16K
|
||||
DATA (rw) : ORIGIN = 0x94000, LENGTH = 16K
|
||||
BSS (rw) : ORIGIN = 0x98000, LENGTH = 16K
|
||||
RAM (rw) : ORIGIN = 0x9c000, LENGTH = 4M
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -36,6 +36,7 @@ SECTIONS
|
||||
*(.bss)
|
||||
__bss_end = .;
|
||||
} >BSS
|
||||
|
||||
__stack_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
__new_text_start = ORIGIN(NEWTEXT);
|
||||
@@ -44,7 +45,6 @@ SECTIONS
|
||||
__new_bss_start = ORIGIN(NEWBSS);
|
||||
}
|
||||
|
||||
__kernel = 0x80000;
|
||||
__heap_start = ORIGIN(RAM);
|
||||
__heap_end = ORIGIN(RAM) + LENGTH(RAM) - 2M;
|
||||
__bss_size = (__bss_end - __bss_start)>>3;
|
||||
|
||||
@@ -2,20 +2,44 @@
|
||||
#include <shell.h>
|
||||
#include <uart.h>
|
||||
|
||||
extern byte_t __kernel[];
|
||||
byte_t *kernel = __kernel;
|
||||
// extern uint64_t __kernel;
|
||||
uint64_t __kernel = 0x80000;
|
||||
|
||||
void main()
|
||||
typedef void (*main_func_t)(void *);
|
||||
|
||||
void main(void *dtb)
|
||||
{
|
||||
uart_init();
|
||||
|
||||
uart_getc();
|
||||
uart_puts("waiting for kernel to be sent ..." ENDL);
|
||||
|
||||
union {
|
||||
int size;
|
||||
uint8_t buf[4];
|
||||
} kernel_header;
|
||||
kernel_header.size = 0;
|
||||
for (int i = 0; i < (int)sizeof(kernel_header); ++i)
|
||||
kernel_header.buf[i] = uart_getb();
|
||||
|
||||
uart_puts("received kernel size: ");
|
||||
uart_int(kernel_header.size);
|
||||
uart_puts(ENDL);
|
||||
|
||||
uart_puts("loaded addr: ");
|
||||
uart_hex((unsigned int)(unsigned long)main);
|
||||
uart_puts(ENDL);
|
||||
|
||||
int shell_cont = 1;
|
||||
while (shell_cont) {
|
||||
shell_cont = shell();
|
||||
}
|
||||
uart_puts("dtb addr: ");
|
||||
uart_hex((unsigned int)(unsigned long)dtb);
|
||||
uart_puts(ENDL);
|
||||
|
||||
uint8_t *kernel = (void *)__kernel;
|
||||
uart_puts("kernel addr: ");
|
||||
uart_hex((unsigned int)(unsigned long)kernel);
|
||||
uart_puts("$" ENDL);
|
||||
|
||||
for (int i = 0; i < kernel_header.size; ++i)
|
||||
kernel[i] = uart_getb();
|
||||
|
||||
((main_func_t)kernel)(dtb);
|
||||
}
|
||||
|
||||
52
include/dtb.h
Normal file
52
include/dtb.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <vector.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t totalsize;
|
||||
uint32_t off_dt_struct;
|
||||
uint32_t off_dt_strings;
|
||||
uint32_t off_mem_rsvmap;
|
||||
uint32_t version;
|
||||
uint32_t last_comp_version;
|
||||
uint32_t boot_cpuid_phys;
|
||||
uint32_t size_dt_strings;
|
||||
uint32_t size_dt_struct;
|
||||
}__attribute__((packed)) fdt_header_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t address;
|
||||
uint64_t size;
|
||||
}__attribute__((packed)) fdt_reserve_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t len;
|
||||
uint32_t nameoff;
|
||||
}__attribute__((packed)) fdt_prop_header_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t len;
|
||||
const char *name;
|
||||
void *value;
|
||||
} fdt_prop_t;
|
||||
|
||||
#define FDT_BEGIN_NODE 0x00000001
|
||||
#define FDT_END_NODE 0x00000002
|
||||
#define FDT_PROP 0x00000003
|
||||
#define FDT_NOP 0x00000004
|
||||
#define FDT_END 0x00000009
|
||||
|
||||
#define FDT_PATH_BUFFER_LEN 0x10
|
||||
|
||||
typedef void (*fdt_callback_func_t)(const vector_t *props);
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const fdt_callback_func_t func;
|
||||
} fdt_callback_t;
|
||||
|
||||
void fdt_callback(const char *path, const vector_t *cbs, const vector_t *props);
|
||||
void fdt_traverse(const vector_t *cbs);
|
||||
|
||||
extern void *dtb_addr;
|
||||
6
include/errcode.h
Normal file
6
include/errcode.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define ERR_NO_MEM 0x00000001
|
||||
#define ERR_UNREACHABLE 0x00000002
|
||||
#define ERR_CONVERSION 0x00000003
|
||||
#define ERR_VECTOR_OOR 0x00000101
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <dtb.h>
|
||||
#include <vector.h>
|
||||
|
||||
typedef struct {
|
||||
char c_magic[6];
|
||||
@@ -38,9 +40,16 @@ typedef struct file_node {
|
||||
int namesize;
|
||||
|
||||
char *filename;
|
||||
byte_t *filecontent;
|
||||
uint8_t *filecontent;
|
||||
} file_node_t;
|
||||
|
||||
typedef void (*initrd_callback_func_t)(file_node_t *);
|
||||
|
||||
file_node_t *initrd_init(void);
|
||||
int initrd_ls(void);
|
||||
void initrd_fdt_callback(const vector_t *props);
|
||||
file_node_t *initrd_get(file_node_t *root, const char *filename);
|
||||
void initrd_traverse(file_node_t *tr, initrd_callback_func_t func);
|
||||
|
||||
extern fdt_callback_t initrd_dtb_cb;
|
||||
extern void *initrd_start;
|
||||
extern void *initrd_end;
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <initrd.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void help(void);
|
||||
void hello(void);
|
||||
void hwinfo(void);
|
||||
void ls(file_node_t *root);
|
||||
void cat(file_node_t *root, const char *filename);
|
||||
void reboot(void);
|
||||
|
||||
int // is continue
|
||||
shell(void);
|
||||
shell(file_node_t *);
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define ENDL "\r\n"
|
||||
#define NAME_MAX 255
|
||||
#define PATH_MAX 4096
|
||||
|
||||
typedef long unsigned int size_t;
|
||||
typedef unsigned char byte_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef long long int int64_t;
|
||||
typedef unsigned long long int uint64_t;
|
||||
|
||||
@@ -3,5 +3,8 @@
|
||||
#include <stddef.h>
|
||||
|
||||
int strcmp(const char *lhs, const char *rhs);
|
||||
char *strcpy(char *destination, const char *source);
|
||||
size_t strlen(const char *str);
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t count);
|
||||
void *memzero(void *start, void *end);
|
||||
|
||||
@@ -2,9 +2,24 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define DEBUG(x) { \
|
||||
uart_puts(#x " = "); \
|
||||
uart_hex((unsigned int)(unsigned long)x); \
|
||||
uart_puts(ENDL); \
|
||||
}
|
||||
|
||||
#define DEBUG_s(x) { \
|
||||
uart_puts(#x " = "); \
|
||||
uart_puts(x); \
|
||||
uart_puts(ENDL); \
|
||||
}
|
||||
|
||||
void uart_init();
|
||||
void uart_send(unsigned int c);
|
||||
byte_t uart_getb();
|
||||
uint8_t uart_getb();
|
||||
char uart_getc();
|
||||
void uart_puts(char *s);
|
||||
void uart_puts(const char *s);
|
||||
void uart_hex(unsigned int d);
|
||||
void uart_int(int d);
|
||||
|
||||
extern int is_uart_init;
|
||||
|
||||
31
include/utils.h
Normal file
31
include/utils.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <uart.h>
|
||||
|
||||
uint32_t msb32(uint32_t);
|
||||
|
||||
uint32_t hton32(const uint32_t);
|
||||
uint32_t ntoh32(const uint32_t);
|
||||
|
||||
uint64_t hton64(const uint64_t);
|
||||
uint64_t ntoh64(const uint64_t);
|
||||
|
||||
int isdigit(int);
|
||||
int isxdigit(int);
|
||||
int isupper(int);
|
||||
int isspace(int);
|
||||
|
||||
int32_t atoi32(const char *);
|
||||
uint32_t atoh32(const char *);
|
||||
|
||||
void exit(int);
|
||||
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define MAX(x, y) (((x) < (y)) ? (y) : (x))
|
||||
#define ALIGN4(ptr) (void *)(((((uint64_t)(ptr) - 1) >> 2) + 1) << 2)
|
||||
#define ALIGN8(ptr) (void *)(((((uint64_t)(ptr) - 1) >> 3) + 1) << 3)
|
||||
#define BUMP(orig_type, bump_type, ptr) ( \
|
||||
(ptr = (orig_type *)((bump_type *)ptr + 1)), \
|
||||
((bump_type *)ptr - 1) \
|
||||
)
|
||||
18
include/vector.h
Normal file
18
include/vector.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
size_t cap;
|
||||
|
||||
uint64_t *data;
|
||||
} vector_t;
|
||||
|
||||
vector_t *make_vector(size_t size);
|
||||
|
||||
uint64_t vec_at(const vector_t *vec, size_t idx);
|
||||
vector_t *vec_push(vector_t *vec, uint64_t val);
|
||||
|
||||
#define VEC_AT(type, vec, idx) ((type *)vec_at((vec), (idx)))
|
||||
#define VEC_PUSH(vec, val) vec = vec_push(vec, (uint64_t)val)
|
||||
@@ -6,23 +6,22 @@ _start:
|
||||
// read cpu id, stop slave cores
|
||||
mrs x1, mpidr_el1
|
||||
and x1, x1, #3
|
||||
cbz x1, 2f
|
||||
cbz x1, run
|
||||
// cpu id > 0, stop
|
||||
1:
|
||||
wait:
|
||||
wfe
|
||||
b 1b
|
||||
2:// cpu id == 0
|
||||
// set top of stack just before our code (stack grows to a lower address per AAPCS64)
|
||||
ldr x1, =_start
|
||||
mov sp, x1
|
||||
b wait
|
||||
|
||||
run: // cpu id == 0
|
||||
mov x20, x0
|
||||
adrp x0, __stack_end
|
||||
mov sp, x0
|
||||
|
||||
// clear bss
|
||||
adr x0, __bss_start
|
||||
adr x1, __bss_end
|
||||
bl memzero
|
||||
|
||||
4:
|
||||
// jump to C code, should not return
|
||||
mov x0, x20
|
||||
bl main
|
||||
// for failsafe, halt this core too
|
||||
b 1b
|
||||
b wait
|
||||
|
||||
@@ -4,7 +4,7 @@ MEMORY
|
||||
TEXT (rx) : ORIGIN = 0x80000, LENGTH = 128K
|
||||
RO (r) : ORIGIN = 0xa0000, LENGTH = 128K
|
||||
DATA (rw) : ORIGIN = 0x100000, LENGTH = 512K
|
||||
RAM (rw) : ORIGIN = 0x180000, LENGTH = 8M
|
||||
RAM (rw) : ORIGIN = 0x180000, LENGTH = 64M
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -24,10 +24,10 @@ SECTIONS
|
||||
*(.bss)
|
||||
__bss_end = .;
|
||||
} >DATA
|
||||
|
||||
__stack_end = ORIGIN(RAM) + LENGTH(RAM);
|
||||
}
|
||||
|
||||
__kernel = 0x80000;
|
||||
__heap_start = ORIGIN(RAM);
|
||||
__heap_end = ORIGIN(RAM) + LENGTH(RAM) - 2M;
|
||||
__heap_end = ORIGIN(RAM) + 32M;
|
||||
__bss_size = (__bss_end - __bss_start)>>3;
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
#include <uart.h>
|
||||
#include <dtb.h>
|
||||
#include <initrd.h>
|
||||
#include <shell.h>
|
||||
#include <vector.h>
|
||||
|
||||
void main()
|
||||
void main(void *dtb)
|
||||
{
|
||||
uart_init();
|
||||
uart_getc();
|
||||
|
||||
DEBUG(dtb);
|
||||
|
||||
dtb_addr = dtb;
|
||||
vector_t *dtb_cbs = make_vector(0);
|
||||
VEC_PUSH(dtb_cbs, &initrd_dtb_cb);
|
||||
fdt_traverse(dtb_cbs);
|
||||
|
||||
DEBUG(initrd_start);
|
||||
DEBUG(initrd_end);
|
||||
|
||||
file_node_t *initrd_root = initrd_init();
|
||||
|
||||
int shell_cont = 1;
|
||||
while (shell_cont) {
|
||||
shell_cont = shell();
|
||||
shell_cont = shell(initrd_root);
|
||||
}
|
||||
}
|
||||
|
||||
81
lib/dtb.c
Normal file
81
lib/dtb.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <errcode.h>
|
||||
#include <dtb.h>
|
||||
#include <utils.h>
|
||||
#include <string.h>
|
||||
#include <uart.h>
|
||||
#include <kmalloc.h>
|
||||
#include <vector.h>
|
||||
|
||||
void *dtb_addr;
|
||||
|
||||
void fdt_callback(const char *path, const vector_t *cbs, const vector_t *props)
|
||||
{
|
||||
for (int i = 0; i < (int)cbs->size; ++i)
|
||||
if (!strcmp(path, VEC_AT(fdt_callback_t, cbs, i)->name))
|
||||
VEC_AT(fdt_callback_t, cbs, i)->func(props);
|
||||
}
|
||||
|
||||
uint32_t *fdt_struct_cur;
|
||||
|
||||
#define nextnode(ptr) (void *)((((uint64_t)(ptr) >> 2) + 1) << 2)
|
||||
void traverse(const char *path, const vector_t *cbs)
|
||||
{
|
||||
vector_t *props = make_vector(0);
|
||||
|
||||
fdt_prop_t *prop;
|
||||
const fdt_prop_header_t *prop_header;
|
||||
const char *fdt_node_path = 0x0;
|
||||
|
||||
for (;;) {
|
||||
fdt_struct_cur = ALIGN4(fdt_struct_cur);
|
||||
|
||||
switch (ntoh32(*fdt_struct_cur)) {
|
||||
case FDT_BEGIN_NODE:
|
||||
BUMP(uint32_t, uint32_t, fdt_struct_cur);
|
||||
fdt_node_path = (void *)fdt_struct_cur;
|
||||
do {
|
||||
BUMP(uint32_t, char, fdt_struct_cur);
|
||||
} while (*(char *)fdt_struct_cur != '\0');
|
||||
BUMP(uint32_t, char, fdt_struct_cur); // '\0'
|
||||
|
||||
fdt_struct_cur = ALIGN4(fdt_struct_cur);
|
||||
traverse(fdt_node_path, cbs);
|
||||
break;
|
||||
case FDT_END_NODE:
|
||||
fdt_struct_cur = nextnode(fdt_struct_cur);
|
||||
goto traverse_callback;
|
||||
case FDT_PROP:
|
||||
BUMP(uint32_t, uint32_t, fdt_struct_cur);
|
||||
prop_header = BUMP(uint32_t, fdt_prop_header_t, fdt_struct_cur);
|
||||
|
||||
prop = kmalloc(sizeof(fdt_prop_t));
|
||||
prop->len = ntoh32(prop_header->len);
|
||||
prop->name = dtb_addr +
|
||||
ntoh32(((fdt_header_t *)dtb_addr)->off_dt_strings) +
|
||||
ntoh32(prop_header->nameoff);
|
||||
prop->value = (void *)fdt_struct_cur;
|
||||
VEC_PUSH(props, prop);
|
||||
|
||||
fdt_struct_cur = (void *)((uint64_t)fdt_struct_cur +
|
||||
ntoh32(prop_header->len));
|
||||
fdt_struct_cur = ALIGN4(fdt_struct_cur);
|
||||
break;
|
||||
case FDT_NOP:
|
||||
fdt_struct_cur = nextnode(fdt_struct_cur);
|
||||
break;
|
||||
case FDT_END:
|
||||
return;
|
||||
default:
|
||||
exit(ERR_UNREACHABLE);
|
||||
}
|
||||
}
|
||||
traverse_callback:
|
||||
fdt_callback(path, cbs, props);
|
||||
}
|
||||
|
||||
void fdt_traverse(const vector_t *cbs)
|
||||
{
|
||||
fdt_struct_cur = dtb_addr + ntoh32(((fdt_header_t *)dtb_addr)->off_dt_struct);
|
||||
|
||||
traverse("", cbs);
|
||||
}
|
||||
88
lib/initrd.c
88
lib/initrd.c
@@ -1,11 +1,34 @@
|
||||
#include <stddef.h>
|
||||
#include <initrd.h>
|
||||
#include <utils.h>
|
||||
#include <stddef.h>
|
||||
#include <dtb.h>
|
||||
#include <kmalloc.h>
|
||||
#include <random.h>
|
||||
#include <string.h>
|
||||
#include <uart.h>
|
||||
|
||||
#define nullnode ((file_node_t *)0)
|
||||
|
||||
fdt_callback_t initrd_dtb_cb = {
|
||||
.name = "chosen",
|
||||
.func = initrd_fdt_callback,
|
||||
};
|
||||
|
||||
void *initrd_start = 0x0;
|
||||
void *initrd_end = 0x0;
|
||||
|
||||
void initrd_fdt_callback(const vector_t *props)
|
||||
{
|
||||
for (int i = 0; i < (int)props->size; ++i) {
|
||||
if (!strcmp(VEC_AT(fdt_prop_t, props, i)->name, "linux,initrd-start"))
|
||||
initrd_start = (void *)(uint64_t)ntoh32(
|
||||
*(uint32_t *)VEC_AT(fdt_prop_t, props, i)->value);
|
||||
if (!strcmp(VEC_AT(fdt_prop_t, props, i)->name, "linux,initrd-end"))
|
||||
initrd_end = (void *)(uint64_t)ntoh32(
|
||||
*(uint32_t *)VEC_AT(fdt_prop_t, props, i)->value);
|
||||
}
|
||||
}
|
||||
|
||||
void _init_node(file_node_t *node) {
|
||||
node->l = nullnode;
|
||||
node->r = nullnode;
|
||||
@@ -50,7 +73,7 @@ void _split(file_node_t *rt, const char *s, file_node_t **a, file_node_t **b)
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(s, rt->filename) < 0) {
|
||||
if (strcmp(rt->filename, s) < 0) {
|
||||
*a = rt;
|
||||
_split((*a)->r, s, &(*a)->r, b);
|
||||
_pull(*a);
|
||||
@@ -61,12 +84,53 @@ void _split(file_node_t *rt, const char *s, file_node_t **a, file_node_t **b)
|
||||
}
|
||||
}
|
||||
|
||||
cpio_newc_header_t *initrd_cur;
|
||||
|
||||
file_node_t *initrd_init(void)
|
||||
{
|
||||
// TODO
|
||||
cpio_newc_header_t *header;
|
||||
char *filename;
|
||||
uint8_t *filecontent;
|
||||
|
||||
return nullnode;
|
||||
initrd_cur = (void *)initrd_start;
|
||||
|
||||
file_node_t *root = nullnode, *ltr, *rtr;
|
||||
for (;;) {
|
||||
header = BUMP(cpio_newc_header_t, cpio_newc_header_t, initrd_cur);
|
||||
|
||||
filename = (void *)initrd_cur;
|
||||
if (!strcmp(filename, "TRAILER!!!"))
|
||||
break;
|
||||
initrd_cur = ALIGN4((uint64_t)initrd_cur + atoh32(header->c_namesize));
|
||||
|
||||
filecontent = (void *)initrd_cur;
|
||||
initrd_cur = ALIGN4((uint64_t)initrd_cur + atoh32(header->c_filesize));
|
||||
|
||||
file_node_t *newnode = kmalloc(sizeof(file_node_t));
|
||||
_init_node(newnode);
|
||||
newnode->ino = atoh32(header->c_ino);
|
||||
newnode->mode = atoh32(header->c_mode);
|
||||
newnode->uid = atoh32(header->c_uid);
|
||||
newnode->gid = atoh32(header->c_gid);
|
||||
newnode->nlink = atoh32(header->c_nlink);
|
||||
newnode->mtime = atoh32(header->c_mtime);
|
||||
newnode->filesize = atoh32(header->c_filesize);
|
||||
newnode->devmajor = atoh32(header->c_devmajor);
|
||||
newnode->devminor = atoh32(header->c_devminor);
|
||||
newnode->rdevmajor = atoh32(header->c_rdevmajor);
|
||||
newnode->rdevminor = atoh32(header->c_rdevminor);
|
||||
newnode->namesize = atoh32(header->c_namesize);
|
||||
|
||||
newnode->filename = filename;
|
||||
newnode->filecontent = filecontent;
|
||||
|
||||
DEBUG_s(filename);
|
||||
|
||||
_split(root, filename, <r, &rtr);
|
||||
root = _merge(ltr, _merge(newnode, rtr));
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
file_node_t *_node_bs(file_node_t *cur, const char *s)
|
||||
@@ -74,7 +138,7 @@ file_node_t *_node_bs(file_node_t *cur, const char *s)
|
||||
if (!cur)
|
||||
return nullnode;
|
||||
|
||||
int cmp = strcmp(s, cur->filename);
|
||||
int cmp = strcmp(cur->filename, s);
|
||||
if (cmp < 0)
|
||||
return _node_bs(cur->r, s);
|
||||
if (cmp > 0)
|
||||
@@ -82,7 +146,17 @@ file_node_t *_node_bs(file_node_t *cur, const char *s)
|
||||
return cur; // cmp == 0
|
||||
}
|
||||
|
||||
file_node_t *initrd_get(file_node_t *root, const char *filename)
|
||||
file_node_t *initrd_get(file_node_t *tr, const char *filename)
|
||||
{
|
||||
return _node_bs(root, filename);
|
||||
return _node_bs(tr, filename);
|
||||
}
|
||||
|
||||
void initrd_traverse(file_node_t *tr, initrd_callback_func_t func)
|
||||
{
|
||||
if (!tr)
|
||||
return;
|
||||
|
||||
initrd_traverse(tr->l, func);
|
||||
func(tr);
|
||||
initrd_traverse(tr->r, func);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include <uart.h>
|
||||
#include <errcode.h>
|
||||
#include <utils.h>
|
||||
#include <kmalloc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern void *__heap_start;
|
||||
extern void *__heap_end;
|
||||
extern uint64_t __heap_start;
|
||||
extern uint64_t __heap_end;
|
||||
|
||||
void *_heap_top = (void *)0;
|
||||
|
||||
@@ -10,14 +13,14 @@ void *_heap_top = (void *)0;
|
||||
void *simple_alloc(size_t size)
|
||||
{
|
||||
if (!_heap_top) {
|
||||
_heap_top = __heap_start;
|
||||
_heap_top = (void *)&__heap_start;
|
||||
}
|
||||
|
||||
if (size & 0xff)
|
||||
size = (size & ~0xff) + 0x100;
|
||||
|
||||
if ((uint64_t)_heap_top + size >= (uint64_t)__heap_end)
|
||||
return (void *)0;
|
||||
if ((uint64_t)_heap_top + size >= (uint64_t)&__heap_end)
|
||||
exit(ERR_NO_MEM);
|
||||
|
||||
void *ret = _heap_top;
|
||||
_heap_top = (void *)((uint64_t)_heap_top + size);
|
||||
|
||||
52
lib/shell.c
52
lib/shell.c
@@ -1,4 +1,5 @@
|
||||
#include <stddef.h>
|
||||
#include <utils.h>
|
||||
#include <string.h>
|
||||
#include <uart.h>
|
||||
#include <mbox.h>
|
||||
@@ -17,6 +18,8 @@ void help (void)
|
||||
"help : print this help menu" ENDL
|
||||
"hello : print Hello World!" ENDL
|
||||
"hwinfo: print hardware info" ENDL
|
||||
"ls : list directory contents" ENDL
|
||||
"cat : concatenate files and print" ENDL
|
||||
"reboot: reboot the device" ENDL
|
||||
);
|
||||
}
|
||||
@@ -46,6 +49,27 @@ void hwinfo (void)
|
||||
uart_puts(ENDL);
|
||||
}
|
||||
|
||||
void ls_initrd_callback(file_node_t *tr)
|
||||
{
|
||||
uart_puts(tr->filename);
|
||||
uart_puts(ENDL);
|
||||
}
|
||||
|
||||
void ls(file_node_t *root)
|
||||
{
|
||||
initrd_traverse(root, ls_initrd_callback);
|
||||
}
|
||||
|
||||
void cat(file_node_t *root, const char *filename)
|
||||
{
|
||||
file_node_t *tr = initrd_get(root, filename);
|
||||
if (tr) {
|
||||
uart_puts((char *)tr->filecontent);
|
||||
} else {
|
||||
uart_puts("FILE NOT EXIST!" ENDL);
|
||||
}
|
||||
}
|
||||
|
||||
void set(long addr, unsigned int value) {
|
||||
volatile unsigned int* point = (unsigned int*)addr;
|
||||
*point = value;
|
||||
@@ -61,7 +85,7 @@ void reboot(void)
|
||||
reset(1 << 16);
|
||||
}
|
||||
|
||||
int shell (void)
|
||||
int shell(file_node_t *initrd_root)
|
||||
{
|
||||
uart_puts("# ");
|
||||
|
||||
@@ -74,13 +98,31 @@ int shell (void)
|
||||
uart_puts(ENDL);
|
||||
buf[sz] = '\0';
|
||||
|
||||
if (strcmp(buf, "help") == 0) {
|
||||
const char *i = buf;
|
||||
|
||||
char bin[INPUT_BUFLEN], *j;
|
||||
for (j = bin; *i != '\0' && !isspace(*i); ++i, ++j)
|
||||
*j = *i;
|
||||
*j = '\0';
|
||||
|
||||
for (; *i != '\0' && isspace(*i); ++i);
|
||||
|
||||
char param[INPUT_BUFLEN];
|
||||
for (j = param; *i != '\0' && !isspace(*i); ++i, ++j)
|
||||
*j = *i;
|
||||
*j = '\0';
|
||||
|
||||
if (!strcmp(bin, "help")) {
|
||||
help();
|
||||
} else if (strcmp(buf, "hello") == 0) {
|
||||
} else if (!strcmp(bin, "hello")) {
|
||||
hello();
|
||||
} else if (strcmp(buf, "hwinfo") == 0) {
|
||||
} else if (!strcmp(bin, "hwinfo")) {
|
||||
hwinfo();
|
||||
} else if (strcmp(buf, "reboot") == 0) {
|
||||
} else if (!strcmp(bin, "ls")) {
|
||||
ls(initrd_root);
|
||||
} else if (!strcmp(bin, "cat")) {
|
||||
cat(initrd_root, param);
|
||||
} else if (!strcmp(bin, "reboot")) {
|
||||
reboot();
|
||||
}
|
||||
|
||||
|
||||
25
lib/string.c
25
lib/string.c
@@ -16,11 +16,30 @@ int strcmp(const char *a, const char *b)
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *strcpy(char *destination, const char *source)
|
||||
{
|
||||
char *ret = destination;
|
||||
while (*source != '\0')
|
||||
*destination++ = *source++;
|
||||
*destination = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t strlen(const char *str)
|
||||
{
|
||||
size_t ret = 0;
|
||||
while (*str != '\0')
|
||||
++ret, ++str;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t count)
|
||||
{
|
||||
void *ret = dest;
|
||||
for (const byte_t *p = src; count > 0; --count, ++p, ++dest)
|
||||
*(byte_t *)dest = *p;
|
||||
for (const uint8_t *p = src; count > 0; --count, ++p, ++dest)
|
||||
*(uint8_t *)dest = *p;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -28,7 +47,7 @@ void *memcpy(void *dest, const void *src, size_t count)
|
||||
void *memzero(void *start, void *end)
|
||||
{
|
||||
void *ret = start;
|
||||
for (byte_t *p = start; p < (byte_t *)end; ++p)
|
||||
for (uint8_t *p = start; p < (uint8_t *)end; ++p)
|
||||
*p = 0;
|
||||
|
||||
return ret;
|
||||
|
||||
38
lib/uart.c
38
lib/uart.c
@@ -1,5 +1,6 @@
|
||||
#include <uart.h>
|
||||
#include <gpio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Auxilary mini UART registers */
|
||||
#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004))
|
||||
@@ -15,6 +16,8 @@
|
||||
#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064))
|
||||
#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068))
|
||||
|
||||
int is_uart_init = 0;
|
||||
|
||||
/**
|
||||
* Set baud rate and characteristics (115200 8N1) and map to GPIO
|
||||
*/
|
||||
@@ -42,6 +45,8 @@ void uart_init()
|
||||
r=150; while(r--) { asm volatile("nop"); }
|
||||
*GPPUDCLK0 = 0; // flush GPIO setup
|
||||
*AUX_MU_CNTL = 3; // enable Tx, Rx
|
||||
|
||||
is_uart_init = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,13 +59,13 @@ void uart_send(unsigned int c) {
|
||||
*AUX_MU_IO=c;
|
||||
}
|
||||
|
||||
byte_t uart_getb()
|
||||
uint8_t uart_getb()
|
||||
{
|
||||
byte_t r;
|
||||
uint8_t r;
|
||||
/* wait until something is in the buffer */
|
||||
do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01));
|
||||
/* read it and return */
|
||||
r=(byte_t)(*AUX_MU_IO);
|
||||
r=(uint8_t)(*AUX_MU_IO);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -78,7 +83,7 @@ char uart_getc() {
|
||||
/**
|
||||
* Display a string
|
||||
*/
|
||||
void uart_puts(char *s) {
|
||||
void uart_puts(const char *s) {
|
||||
while(*s) {
|
||||
/* convert newline to carrige return + newline */
|
||||
if(*s=='\n')
|
||||
@@ -90,7 +95,7 @@ void uart_puts(char *s) {
|
||||
/**
|
||||
* Display a binary value in hexadecimal
|
||||
*/
|
||||
void uart_hex(unsigned int d) {
|
||||
void uart_hex(const unsigned int d) {
|
||||
unsigned int n;
|
||||
int c;
|
||||
for(c=28;c>=0;c-=4) {
|
||||
@@ -101,3 +106,26 @@ void uart_hex(unsigned int d) {
|
||||
uart_send(n);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_int(int d)
|
||||
{
|
||||
unsigned int buf[11];
|
||||
int size = 0;
|
||||
|
||||
if (d == 0) {
|
||||
uart_send((unsigned int)'0');
|
||||
return;
|
||||
}
|
||||
|
||||
int is_neg = (d < 0);
|
||||
|
||||
while (d != 0) {
|
||||
buf[size++] = '0' + d % 10;
|
||||
d /= 10;
|
||||
}
|
||||
|
||||
if (is_neg)
|
||||
uart_send((unsigned int)'-');
|
||||
while (size--)
|
||||
uart_send(buf[size]);
|
||||
}
|
||||
|
||||
132
lib/utils.c
Normal file
132
lib/utils.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include <utils.h>
|
||||
#include <errcode.h>
|
||||
#include <uart.h>
|
||||
|
||||
uint32_t msb32(uint32_t x)
|
||||
{
|
||||
static const int msb[32] = {
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
||||
};
|
||||
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
|
||||
return msb[(uint32_t)(x * 0x07c4acddu) >> 27];
|
||||
}
|
||||
|
||||
uint32_t hton32(const uint32_t h)
|
||||
{
|
||||
const uint8_t *p = (const void *)&h;
|
||||
|
||||
return (uint32_t)p[0] << 24 |
|
||||
(uint32_t)p[1] << 16 |
|
||||
(uint32_t)p[2] << 8 |
|
||||
(uint32_t)p[3];
|
||||
}
|
||||
|
||||
uint32_t ntoh32(const uint32_t h)
|
||||
{
|
||||
return hton32(h);
|
||||
}
|
||||
|
||||
uint64_t hton64(const uint64_t h)
|
||||
{
|
||||
return (uint64_t)hton32(h & 0xffffffff) << 32 |
|
||||
(uint64_t)hton32(h >> 32);
|
||||
}
|
||||
|
||||
uint64_t ntoh64(const uint64_t h)
|
||||
{
|
||||
return hton64(h);
|
||||
}
|
||||
|
||||
int isspace(int c)
|
||||
{
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\v':
|
||||
case '\f':
|
||||
case '\r':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int isdigit(int c)
|
||||
{
|
||||
return ('0' <= c && c <= '9');
|
||||
}
|
||||
|
||||
int isxdigit(int c)
|
||||
{
|
||||
return ('0' <= c && c <= '9') ||
|
||||
('a' <= c && c <= 'f') ||
|
||||
('A' <= c && c <= 'F');
|
||||
}
|
||||
|
||||
int isupper(int c)
|
||||
{
|
||||
return ('A' <= c && c <= 'F');
|
||||
}
|
||||
|
||||
int32_t atoi32(const char *s)
|
||||
{
|
||||
if (!s)
|
||||
exit(ERR_CONVERSION);
|
||||
|
||||
int is_neg = 0;
|
||||
if (*s != '\0' && *s == '-')
|
||||
is_neg = 1, s++;
|
||||
|
||||
int32_t ret = 0;
|
||||
for (; *s != '\0'; ++s) {
|
||||
if (!isdigit(*s))
|
||||
exit(ERR_CONVERSION);
|
||||
ret *= 10, ret += *s - '0';
|
||||
}
|
||||
|
||||
return is_neg ? -ret : ret;
|
||||
}
|
||||
|
||||
uint32_t atoh32(const char *s)
|
||||
{
|
||||
if (!s)
|
||||
exit(ERR_CONVERSION);
|
||||
|
||||
uint32_t ret = 0;
|
||||
for (int i = 8; i--; ++s) {
|
||||
if (!isxdigit(*s))
|
||||
exit(ERR_CONVERSION);
|
||||
ret <<= 4, ret |= (isdigit(*s) ? *s - '0' :
|
||||
(isupper(*s) ? *s - 'A' + 10 :
|
||||
*s - 'a' + 10));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void exit(int exit_code)
|
||||
{
|
||||
static int print = 0;
|
||||
if (!print) {
|
||||
uart_puts(
|
||||
"OOPS! YOUR KERNEL DEAD" ENDL
|
||||
"ERROR CODE: "
|
||||
);
|
||||
uart_hex(exit_code);
|
||||
uart_puts(ENDL);
|
||||
print = 1;
|
||||
}
|
||||
|
||||
asm volatile(
|
||||
"wfe\n"
|
||||
"b exit"
|
||||
);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
39
lib/vector.c
Normal file
39
lib/vector.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <errcode.h>
|
||||
#include <uart.h>
|
||||
#include <vector.h>
|
||||
#include <utils.h>
|
||||
#include <kmalloc.h>
|
||||
#include <string.h>
|
||||
|
||||
vector_t *make_vector(size_t size)
|
||||
{
|
||||
vector_t *ret = kmalloc(sizeof(vector_t));
|
||||
ret->size = size;
|
||||
uint32_t msb = msb32(size);
|
||||
ret->cap = (msb == size) ? size : (msb << 1);
|
||||
ret->cap = MAX(ret->cap, 4);
|
||||
ret->data = kmalloc(ret->cap * sizeof(uint64_t));
|
||||
memzero(ret->data, ret->data + ret->cap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t vec_at(const vector_t *vec, size_t idx)
|
||||
{
|
||||
if (idx >= vec->size)
|
||||
exit(ERR_VECTOR_OOR);
|
||||
|
||||
return vec->data[idx];
|
||||
}
|
||||
|
||||
vector_t *vec_push(vector_t *vec, uint64_t val)
|
||||
{
|
||||
if (vec->size == vec->cap) {
|
||||
uint64_t *old = vec->data;
|
||||
vec->data = kmalloc((vec->cap <<= 1) * sizeof(uint64_t));
|
||||
memcpy(vec->data, old, vec->size * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
vec->data[vec->size++] = val;
|
||||
return vec;
|
||||
}
|
||||
1
rootfs/poop/poop/poop.txt
Normal file
1
rootfs/poop/poop/poop.txt
Normal file
@@ -0,0 +1 @@
|
||||
pooppooppoop
|
||||
13
test.py
Executable file
13
test.py
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/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()
|
||||
30
upload.py
Executable file
30
upload.py
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env -S python3
|
||||
from pwn import *
|
||||
from struct import pack
|
||||
from tqdm import tqdm
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("no args for serial device")
|
||||
exit()
|
||||
|
||||
while True:
|
||||
kernel = open("kernel8.img", "rb").read()
|
||||
r = serialtube(sys.argv[1], convert_newlines=False)
|
||||
|
||||
# send size
|
||||
sz = len(kernel)
|
||||
print("size:", sz)
|
||||
r.send(pack("<I", sz))
|
||||
print(r.recvuntil(b"$").decode())
|
||||
|
||||
# send kernel
|
||||
splitsize = 1000
|
||||
for i in tqdm(range(len(kernel) // splitsize), unit="KB"):
|
||||
r.send(kernel[i * splitsize : (i + 1) * splitsize])
|
||||
|
||||
r.send(kernel[len(kernel) // splitsize * splitsize:])
|
||||
|
||||
r.interactive()
|
||||
|
||||
r.send(b"reboot\n")
|
||||
sleep(1)
|
||||
Reference in New Issue
Block a user