summaryrefslogtreecommitdiff
path: root/src/arch/amd64/mboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/amd64/mboot.c')
-rw-r--r--src/arch/amd64/mboot.c246
1 files changed, 201 insertions, 45 deletions
diff --git a/src/arch/amd64/mboot.c b/src/arch/amd64/mboot.c
index 89fb431..7fd3f62 100644
--- a/src/arch/amd64/mboot.c
+++ b/src/arch/amd64/mboot.c
@@ -1,71 +1,227 @@
#include "mboot.h"
+#include "serial.h"
#include "shim.h"
#include <lib.h>
+#include <stdint.h>
+
+extern char symtab;
+#define kaddr(addr) ((uintptr_t)(&addr))
+
+typedef unsigned char mboot_uint8_t;
+typedef unsigned short mboot_uint16_t;
+typedef unsigned int mboot_uint32_t;
+typedef unsigned long long mboot_uint64_t;
+
+struct mboot_info {
+ mboot_uint32_t total_size;
+ mboot_uint32_t reserved;
+ char tags[];
+};
+
+struct mboot_tag {
+ mboot_uint32_t type;
+ mboot_uint32_t size;
+ char data[];
+};
enum mboot_tag_type {
MBOOT_CMDLINE = 0,
MBOOT_MEMORYMAP = 6,
MBOOT_SYMBOLS = 9,
- MBOOT_XSDP = 14
+ MBOOT_RSDP = 14,
+ MBOOT_XSDP = 15,
};
-static void read_cmdline(struct boot_info *shim_info, char *data, uint8_t len) {
- if (len >= CMDLINE_MAX)
- len = CMDLINE_MAX; // truncate :(
- memcpy(shim_info->cmdline, data, len);
- shim_info->cmdline[len] = '\0';
-}
+struct mboot_elf_header_layout {
+ mboot_uint32_t type;
+ mboot_uint32_t size;
+ mboot_uint32_t num;
+ mboot_uint32_t entsize;
+ mboot_uint32_t shndx;
+ char elf_section_headers[];
+};
-static void read_memorymap(struct boot_info *shim_info, uint64_t size, uint32_t *data) {
- shim_info->map = (struct memory_map *) data;
- shim_info->map->size = size;
-}
+struct mboot_elf_section_header {
+ mboot_uint32_t sh_name;
+ mboot_uint32_t sh_type;
+ mboot_uint64_t sh_flags;
+ mboot_uint64_t sh_addr;
+ mboot_uint64_t sh_offset;
+ mboot_uint64_t sh_size;
+ mboot_uint32_t sh_link;
+ mboot_uint32_t sh_info;
+ mboot_uint64_t sh_addralign;
+ mboot_uint64_t sh_entsize;
+};
-static void read_xsdp(struct boot_info *shim_info, char *data) {
- shim_info->acpi_table = (void *) data;
-}
+struct mboot_memory_segment {
+ mboot_uint64_t addr;
+ mboot_uint64_t len;
+ mboot_uint32_t type;
+ mboot_uint32_t reserved;
+};
-static uint32_t *read_tag(uint32_t *data, struct boot_info *shim_info) {
+struct mboot_memory_map {
+ mboot_uint32_t tag;
+ mboot_uint32_t size;
+ mboot_uint32_t entry_size;
+ mboot_uint32_t entry_version;
+ struct memory_segment entries[];
+};
+
+struct mboot_rsdp {
+ mboot_uint32_t tag;
+ mboot_uint32_t size;
+ mboot_uint8_t rsdp[];
+};
- uint16_t type = *((uint16_t *)data);
- uint32_t size = data[1];
+struct mboot_xsdp {
+ mboot_uint32_t tag;
+ mboot_uint32_t size;
+ mboot_uint8_t xsdp[];
+};
- uint8_t data_len = size - 2 * sizeof(uint32_t);
+struct mboot_cmdline {
+ mboot_uint32_t tag;
+ mboot_uint32_t size;
+ char cmdline[];
+};
- switch (type) {
- case MBOOT_CMDLINE:
- read_cmdline(shim_info, (char *)(data + 2), data_len);
- break;
- case MBOOT_MEMORYMAP:
- read_memorymap(shim_info, size, data + 2);
- break;
- case MBOOT_SYMBOLS:
- shim_info->symbol_table = (void *) (data + 2);
- break;
- case MBOOT_XSDP:
- read_xsdp(shim_info, (char *) (data + 2));
- break;
- default:
- break;
- }
+static void read_symbols(
+ struct boot_info *shim_info,
+ struct mboot_elf_header_layout *layout
+) {
- if(size % 8 != 0) {
- size += 8 - (size % 8);
- }
+ shim_info->symbol_table = layout->elf_section_headers;
- return data + size / sizeof(uint32_t);
+// struct mboot_elf_section_header *section =
+// (struct mboot_elf_section_header *) (layout->elf_section_headers);
+//
+// for (mboot_uint32_t i = 0; i < layout->num; i++) {
+// char buf[20];
+//
+// ultoa(i, buf, 10);
+// serial_out_str("[");
+// serial_out_str(buf);
+// serial_out_str("]\t");
+//
+// serial_out_str((char *)(kaddr(symtab) + section->sh_name));
+// serial_out('\t');
+//
+// ultoa(section->sh_type, buf, 16);
+// serial_out_str("type: 0x");
+// serial_out_str(buf);
+// serial_out('\t');
+//
+// ultoa(section->sh_addr, buf, 16);
+// serial_out_str("addr: 0x");
+// serial_out_str(buf);
+// serial_out('\t');
+//
+// ultoa(section->sh_offset, buf, 16);
+// serial_out_str("offset: 0x");
+// serial_out_str(buf);
+// serial_out('\n');
+//
+// section++;
+// }
+}
+
+static void read_cmdline(
+ struct boot_info *shim_info,
+ struct mboot_cmdline *cmdline
+) {
+ mboot_uint32_t size = cmdline->size - 8;
+ if (size >= CMDLINE_MAX)
+ size = CMDLINE_MAX; // truncate :(
+ memcpy(shim_info->cmdline, cmdline->cmdline, size);
+ shim_info->cmdline[size] = '\0';
+}
+
+static void read_memorymap(
+ struct boot_info *shim_info,
+ struct mboot_memory_map *map
+) {
+ int size = map->size - sizeof(mboot_uint32_t) * 4;
+ int count = size / map->entry_size;
+
+ shim_info->map.entry_count = count;
+ shim_info->map.entry_length = map->entry_size;
+ shim_info->map.entries = map->entries;
+}
+
+static void read_rsdp(
+ struct boot_info *shim_info,
+ struct mboot_rsdp *rsdp
+) {
+ if (shim_info->acpi_table != NULL)
+ return; // xsdp is newer and has been loaded
+ shim_info->acpi_table = rsdp->rsdp;
+}
+
+static void read_xsdp(
+ struct boot_info *shim_info,
+ struct mboot_xsdp *xsdp
+) {
+ shim_info->acpi_table = xsdp->xsdp;
}
void mboot_load_info(
- const void *mboot_info,
+ const void *mboot_data_ptr,
struct boot_info *shim_info
) {
- uint32_t* data = (uint32_t*) mboot_info;
- uint32_t total_size = *data++;
- data++; //reserved
- while((uint8_t*) data < (uint8_t*) mboot_info + total_size) {
- data = read_tag(data, shim_info);
- }
+ memset(shim_info, 0, sizeof(struct boot_info));
+
+ struct mboot_info *mboot_info = (struct mboot_info *) mboot_data_ptr;
+ const char *mboot_end = ((char *) mboot_info) + mboot_info->total_size;
+
+ char *tag_ptr = mboot_info->tags;
+
+ while (tag_ptr < mboot_end) {
+ struct mboot_tag *tag = (struct mboot_tag *) tag_ptr;
+
+ switch (tag->type) {
+ case MBOOT_CMDLINE:
+ read_cmdline(
+ shim_info,
+ (struct mboot_cmdline *) tag
+ );
+ break;
+ case MBOOT_MEMORYMAP:
+ read_memorymap(
+ shim_info,
+ (struct mboot_memory_map *) tag
+ );
+ break;
+ case MBOOT_SYMBOLS:
+ read_symbols(
+ shim_info,
+ (struct mboot_elf_header_layout *) tag
+ );
+ break;
+ case MBOOT_RSDP:
+ read_rsdp(
+ shim_info,
+ (struct mboot_rsdp *) tag
+ );
+ break;
+ case MBOOT_XSDP:
+ read_xsdp(
+ shim_info,
+ (struct mboot_xsdp *) tag
+ );
+ break;
+ default:
+ break;
+ }
+
+ int size = tag->size;
+ if (size % 8 != 0) {
+ size += 8 - (size % 8);
+ }
+
+ tag_ptr += size;
+ }
}