#include "mboot.h" #include "serial.h" #include "shim.h" #include #include 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_RSDP = 14, MBOOT_XSDP = 15, }; 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[]; }; 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; }; struct mboot_memory_segment { mboot_uint64_t addr; mboot_uint64_t len; mboot_uint32_t type; mboot_uint32_t reserved; }; 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[]; }; struct mboot_xsdp { mboot_uint32_t tag; mboot_uint32_t size; mboot_uint8_t xsdp[]; }; struct mboot_cmdline { mboot_uint32_t tag; mboot_uint32_t size; char cmdline[]; }; static void read_symbols( struct boot_info *shim_info, struct mboot_elf_header_layout *layout ) { shim_info->symbol_table = layout->elf_section_headers; // 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_data_ptr, struct boot_info *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; } }