diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/initrd.c | 135 |
1 files changed, 0 insertions, 135 deletions
diff --git a/kernel/initrd.c b/kernel/initrd.c deleted file mode 100644 index 62a4e20..0000000 --- a/kernel/initrd.c +++ /dev/null @@ -1,135 +0,0 @@ -#include <fbos/init.h> -#include <fbos/sched.h> -#include <fbos/printk.h> -#include <fbos/string.h> - -#define BUFFER_SIZE 32 - -#define CPIO_HEADER_FILESIZE 54 -#define CPIO_HEADER_NAMESIZE 94 -#define CPIO_HEADER_SIZE 110 - -// Converts the given string 'str' of 'n' length to an integer by assuming it's -// in base 16. -__kernel uint64_t strtoul16(const char *str, size_t n) -{ - char c; - uint64_t ret = 0; - uint64_t aux = 0; - - for (uint64_t i = 1; n > 0; i *= 16, n--) { - c = str[n - 1]; - if (c >= 'A' && c <= 'F') { - aux = 10 + (uint64_t)(c - 'A'); - } else if (c >= 'a' && c <= 'f') { - aux = 10 + (uint64_t)(c - 'a'); - } else if (c < '0' || c > '9') { - die("Bad number\n"); - } else { - aux = (uint64_t)c - '0'; - } - - ret += aux * i; - } - return ret; -} - -// Returns the 'enum taks_id' that can be gathered by the given path. -__kernel int get_task_id_from_path(const char *const path) -{ - if (strcmp(path, "usr/bin/init") == 0) { - return TASK_INIT; - } else if (strcmp(path, "usr/bin/fizz") == 0) { - return TASK_FIZZ; - } else if (strcmp(path, "usr/bin/buzz") == 0) { - return TASK_BUZZ; - } else if (strcmp(path, "usr/bin/fizzbuzz") == 0) { - return TASK_FIZZBUZZ; - } - return TASK_UNKNOWN; -} - -// Fetch the 'entry_addr' for the ELF binary pointed by 'addr'. If everything -// goes right, the task identified by 'task_id' will finally be initialized with -// said address. -__kernel const void *get_task_entry_addr(const unsigned char *const addr) -{ - uint64_t offset; - - if (addr[0] != 0x7F || memcmp(&addr[1], "ELF", 3) != 0) { - die("Bad ELF format\n"); - } - if (addr[4] != 2) { - die("64-bit format is mandatory\n"); - } - if (addr[5] != 1) { - die("Little-endian only\n"); - } - - offset = (uint64_t)addr[0x18]; - return (const void *)(addr + offset); -} - -__kernel void extract_initrd(const unsigned char *const initrd_addr, uint64_t size, - struct task_struct g_tasks[4]) -{ - char buffer[BUFFER_SIZE]; - uint64_t name_size, file_size, padding, base = 0; - int task_id; - - // The `base` is the index from `initrd_addr` which points to the first byte - // of the header of the currently evaluated file inside of the CPIO archive. - while (base < size) { - // Only the "newc" format is supported, without checksums nor fancy - // stuff. - if (memcmp(&initrd_addr[base], "070701", 6) != 0) { - if (memcmp(&initrd_addr[base], "070702", 6) == 0 || - memcmp(&initrd_addr[base], "070707", 6) == 0) { - die("Incorrect cpio format: stick to 'newc'"); - } else { - die("No cpio magic number"); - } - } - - // We identify the task being extracted by looking at the file's path, - // so let's first get the size of it. - memcpy(buffer, &initrd_addr[base + CPIO_HEADER_NAMESIZE], 8); - buffer[8] = '\0'; - name_size = strtoul16(buffer, 8); - if (name_size >= BUFFER_SIZE) { - die("Path too large for initrd executable"); - } - - // Right after the header (hence current header + its size) there is the - // actual file's path, which is exactly `name_size` long. Fetch it now - // to identify the task at hand. - memcpy(buffer, &initrd_addr[base + CPIO_HEADER_SIZE], name_size); - buffer[name_size] = '\0'; - task_id = get_task_id_from_path(buffer); - - // Note that this is not necessarily a bad CPIO archive, it might just - // be the end "TRAILER!!!" delimiter. Either way, just quit at this - // point. - if (task_id == TASK_UNKNOWN) { - break; - } - - // Fetch the size of the executable, which is needed for `extract_elf`, - // as well as for advancing the `base` to the next file. - memcpy(buffer, &initrd_addr[base + CPIO_HEADER_FILESIZE], 8); - buffer[8] = '\0'; - file_size = strtoul16(buffer, 8); - - // Files are aligned in 4-byte boundaries after the header. That's why - // there might be some padding in between the header and the file. - padding = 4 - ((CPIO_HEADER_SIZE + name_size) & 3); - - // And extract the entry address for the current task from the ELF - // binary. - g_tasks[task_id].entry_addr = - get_task_entry_addr(&initrd_addr[base + name_size + CPIO_HEADER_SIZE + padding]); - - // Advance the base to the next file. - base += CPIO_HEADER_SIZE + name_size + padding + file_size; - } -} |
