Feat: lab 4

This commit is contained in:
2025-03-21 03:39:25 +08:00
parent ed2ced5caf
commit 45ebb20cf2
35 changed files with 833 additions and 174 deletions

View File

@@ -1,81 +0,0 @@
#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);
}

View File

@@ -1,162 +0,0 @@
#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;
node->rand = random();
node->node_size = 1;
}
void _pull_from(file_node_t *to, file_node_t *from)
{
if (!from)
return;
to->node_size += from->node_size;
}
void _pull(file_node_t *node)
{
node->node_size = 1;
_pull_from(node, node->l);
_pull_from(node, node->r);
}
file_node_t *_merge(file_node_t *a, file_node_t *b)
{
if (!a || !b)
return a ?: b;
if (a->rand < b->rand) {
a->r = _merge(a->r, b);
_pull(a);
return a;
}
b->l = _merge(a, b->l);
_pull(b);
return b;
}
void _split(file_node_t *rt, const char *s, file_node_t **a, file_node_t **b)
{
if (!rt) {
*a = *b = nullnode;
return;
}
if (strcmp(rt->filename, s) < 0) {
*a = rt;
_split((*a)->r, s, &(*a)->r, b);
_pull(*a);
} else {
*b = rt;
_split((*b)->l, s, a, &(*b)->l);
_pull(*b);
}
}
cpio_newc_header_t *initrd_cur;
file_node_t *initrd_init(void)
{
cpio_newc_header_t *header;
char *filename;
uint8_t *filecontent;
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, &ltr, &rtr);
root = _merge(ltr, _merge(newnode, rtr));
}
return root;
}
file_node_t *_node_bs(file_node_t *cur, const char *s)
{
if (!cur)
return nullnode;
int cmp = strcmp(cur->filename, s);
if (cmp < 0)
return _node_bs(cur->r, s);
if (cmp > 0)
return _node_bs(cur->l, s);
return cur; // cmp == 0
}
file_node_t *initrd_get(file_node_t *tr, const char *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);
}

View File

@@ -1,39 +0,0 @@
#include <uart.h>
#include <errcode.h>
#include <utils.h>
#include <kmalloc.h>
#include <stddef.h>
extern uint64_t __heap_start;
extern uint64_t __heap_end;
void *_heap_top = (void *)0;
// simple 8-byte aligned linear allocation
void *simple_alloc(size_t size)
{
if (!_heap_top) {
_heap_top = (void *)&__heap_start;
}
size = (size_t)ALIGN8(size);
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);
return ret;
}
void *kmalloc(size_t size)
{
return simple_alloc(size);
}
void kfree(void *ptr)
{
// not implemented for now
return;
}

4
lib/logger.c Normal file
View File

@@ -0,0 +1,4 @@
#include <logger.h>
char logger_buf[LOGGER_BUFLEN];
char *logger_cur = logger_buf;

View File

@@ -1,125 +0,0 @@
/*
* Copyright (C) 2018 bzt (bztsrc@github)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
#include <gpio.h>
#include <mbox.h>
/* mailbox message buffer */
volatile unsigned int __attribute__((aligned(16))) mbox[36];
#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880)
#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0))
#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10))
#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14))
#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18))
#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C))
#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20))
#define MBOX_RESPONSE 0x80000000
#define MBOX_FULL 0x80000000
#define MBOX_EMPTY 0x40000000
#define MAILBOX_BASE MMIO_BASE + 0xb880
#define REQUEST_SUCCEED 0x80000000
#define REQUEST_FAILED 0x80000001
#define TAG_MBOX_REQUEST 0x00000000
/**
* Make a mailbox call. Returns 0 on failure, non-zero on success
*/
int mbox_call(unsigned char ch)
{
unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF));
/* wait until we can write to the mailbox */
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL);
/* write the address of our message to the mailbox with channel identifier */
*MBOX_WRITE = r;
/* now wait for the response */
while(1) {
/* is there a response? */
do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY);
/* is it a response to our message? */
if(r == *MBOX_READ)
/* is it a valid successful response? */
return mbox[1]==MBOX_RESPONSE;
}
return 0;
}
unsigned int get_board_revision(void)
{
mbox[0] = 36 * 4;
mbox[1] = MBOX_REQUEST;
// tags
mbox[2] = MBOX_TAG_BOARD_REVISION;
mbox[3] = 4;
mbox[4] = TAG_MBOX_REQUEST;
mbox[5] = 0; // value buffer
mbox[6] = MBOX_TAG_LAST;
mbox_call(MBOX_CH_PROP);
return mbox[5];
}
unsigned int get_memory_base_addr(void)
{
mbox[0] = 36 * 4;
mbox[1] = MBOX_REQUEST;
// tags
mbox[2] = MBOX_TAG_ARM_MEMORY;
mbox[3] = 8;
mbox[4] = 8;
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(MBOX_CH_PROP);
return mbox[5];
}
unsigned int get_memory_size(void)
{
mbox[0] = 36 * 4;
mbox[1] = MBOX_REQUEST;
// tags
mbox[2] = MBOX_TAG_ARM_MEMORY;
mbox[3] = 8;
mbox[4] = 8;
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(MBOX_CH_PROP);
return mbox[6];
}

View File

@@ -1,12 +0,0 @@
#include <random.h>
const int _random_a = 100003;
const int _random_c = 114514 + 33;
const int _random_m = 1000000007;
int seed = 0;
int random(void)
{
seed = _random_a * (seed + _random_c) % _random_m;
return seed;
}

View File

@@ -1,141 +0,0 @@
#include <stddef.h>
#include <kmalloc.h>
#include <utils.h>
#include <string.h>
#include <uart.h>
#include <mbox.h>
#include <shell.h>
#define INPUT_BUFLEN 1000
#define PM_PASSWORD 0x5a000000
#define PM_RSTC 0x3F10001c
#define PM_WDOG 0x3F100024
void help (void)
{
uart_puts(
"help : print this help menu" ENDL
"hello : print Hello World!" ENDL
"hwinfo : print hardware info" ENDL
"memalloc : alloate memory and print" ENDL
"ls : list directory contents" ENDL
"cat : concatenate files and print" ENDL
"reboot : reboot the device" ENDL
);
}
void hello (void)
{
uart_puts("hello, world" ENDL);
}
void hwinfo (void)
{
uart_puts(
"hwinfo: " ENDL
"board revision: "
);
uart_hex(get_board_revision());
uart_puts(
ENDL
"memory base addr: "
);
uart_hex(get_memory_base_addr());
uart_puts(
ENDL
"memory size: "
);
uart_hex(get_memory_size());
uart_puts(ENDL);
}
void memalloc(size_t size)
{
DEBUG(size);
void *addr = kmalloc(size);
DEBUG(addr);
}
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;
}
void reset(int tick) { // reboot after watchdog timer expire
set(PM_RSTC, PM_PASSWORD | 0x20); // full reset
set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick
}
void reboot(void)
{
reset(1 << 16);
}
int shell(file_node_t *initrd_root)
{
uart_puts("# ");
char buf[INPUT_BUFLEN], ch;
int sz = 0;
while ((ch = uart_getc()) != '\n') {
buf[sz++] = ch;
uart_send(ch);
}
uart_puts(ENDL);
buf[sz] = '\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(bin, "hello")) {
hello();
} else if (!strcmp(bin, "hwinfo")) {
hwinfo();
} else if (!strcmp(bin, "memalloc")){
memalloc((size_t)atoi32(param));
} else if (!strcmp(bin, "ls")) {
ls(initrd_root);
} else if (!strcmp(bin, "cat")) {
cat(initrd_root, param);
} else if (!strcmp(bin, "reboot")) {
reboot();
}
return true;
}

View File

@@ -95,7 +95,7 @@ void uart_puts(const char *s) {
/**
* Display a binary value in hexadecimal
*/
void uart_hex(const unsigned int d) {
void uart_hex(uint64_t d) {
unsigned int n;
int c;
for(c=28;c>=0;c-=4) {

View File

@@ -1,132 +0,0 @@
#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();
}

View File

@@ -1,39 +0,0 @@
#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;
}