#include #include #include #include #include "mboot.h" #define MBOOT_HEADER_MAGIC 0x36D76289 #define MBOOT_CMDLINE 1 #define MBOOT_MEMORY_MAP 6 #define MBOOT_ELF_SYMBOLS 9 #define MBOOT_OLD_RSDP 14 #define MBOOT_NEW_RSDP 15 extern char symtab; #define kaddr(addr) ((uintptr_t)(&addr)) typedef uint8_t mboot_uint8_t; typedef uint16_t mboot_uint16_t; typedef uint32_t mboot_uint32_t; typedef uint64_t 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[]; }; struct mboot_tag_elf_sections { mboot_uint32_t type; mboot_uint32_t size; mboot_uint16_t num; mboot_uint16_t entsize; mboot_uint16_t shndx; mboot_uint16_t reserved; char sections[]; }; struct mboot_tag_elf_sections_entry { 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_mmap_entry { mboot_uint64_t addr; mboot_uint64_t len; mboot_uint32_t type; mboot_uint32_t zero; }; struct mboot_tag_mmap { mboot_uint32_t type; mboot_uint32_t size; mboot_uint32_t entry_size; mboot_uint32_t entry_version; struct mboot_mmap_entry entries[]; }; struct mboot_tag_old_rsdp { mboot_uint32_t type; mboot_uint32_t size; mboot_uint8_t rsdp[]; }; struct mboot_tag_new_rsdp { mboot_uint32_t type; mboot_uint32_t size; mboot_uint8_t rsdp[]; }; struct mboot_tag_cmdline { mboot_uint32_t type; mboot_uint32_t size; mboot_uint8_t cmdline[]; }; static void read_symbols( struct boot_info *shim_info, struct mboot_tag_elf_sections *sections ) { shim_info->symbol_table = sections->sections; // 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_tag_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_memory_map( struct boot_info *shim_info, struct mboot_tag_mmap *map ) { int idx = 0; uintptr_t i = (uintptr_t)map->entries; for ( ; i < (uintptr_t)map->entries + map->size; i += map->entry_size, idx++ ) { struct mboot_mmap_entry *seg = (struct mboot_mmap_entry *) i; shim_info->map.entries[idx].addr = seg->addr; shim_info->map.entries[idx].type = seg->type; shim_info->map.entries[idx].len = seg->len; } shim_info->map.entry_count = idx; } static void read_old_rsdp( struct boot_info *shim_info, struct mboot_tag_old_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_new_rsdp( struct boot_info *shim_info, struct mboot_tag_new_rsdp *rsdp ) { shim_info->acpi_table = rsdp->rsdp; } void mboot_load_info( long mboot_magic, const void *mboot_data_ptr, struct boot_info *shim_info ) { if (mboot_magic != MBOOT_HEADER_MAGIC) panic("invalid multiboot magic"); 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_tag_cmdline *) tag ); break; case MBOOT_MEMORY_MAP: read_memory_map( shim_info, (struct mboot_tag_mmap *) tag ); break; case MBOOT_ELF_SYMBOLS: read_symbols( shim_info, (struct mboot_tag_elf_sections *) tag ); break; case MBOOT_OLD_RSDP: read_old_rsdp( shim_info, (struct mboot_tag_old_rsdp *) tag ); break; case MBOOT_NEW_RSDP: read_new_rsdp( shim_info, (struct mboot_tag_new_rsdp *) tag ); break; default: break; } int size = tag->size; if (size % 8 != 0) { size += 8 - (size % 8); } tag_ptr += size; } }