📄 efi.c
字号:
hdr->n_type, hdr->n_namesz, hdr->n_descsz);#endif if ((hdr->n_namesz == 10) && (memcmp(n_name, "Etherboot", 10) == 0)) { switch(hdr->n_type) { case EB_IA64_IMAGE_HANDLE: { uint64_t *handlep = (void *)n_desc; etherboot_handle = (EFI_HANDLE)(*handlep); break; } case EB_IA64_SYSTAB: { uint64_t *systabp = (void *)n_desc; efi_info.systab = (void *)(*systabp); efi_info.flags |= READ_SYSTAB; break; } case EB_IA64_FPSWA: { uint64_t*fpswap = (void *)n_desc; efi_info.fpswa = (void *)(*fpswap); efi_info.flags |= READ_FPSWA; break; } case EB_IA64_CONINFO: { struct console_info *coninfop = (void *)n_desc; efi_info.coninfo = *coninfop; efi_info.flags |= READ_CONINFO; break; } case EB_IA64_MEMMAP: { struct efi_mem_map *mem_mapp = (void *)n_desc; efi_info.mem_map = *mem_mapp; efi_info.flags |= READ_MEMMAP; break; } default: break; } } note = next; } if (!(efi_info.flags & READ_SYSTAB)) { printf("No EFI systab\n"); return; } /* If I have an efi memory map assume ExitBootServices has been called. */#warning "FIXME see if there is a better test for boot services still being active " printf("FIXME Develop a better test for boot services still being active\n"); if (!(efi_info.flags & READ_MEMMAP)) { conout = efi_info.systab->ConOut; conin = efi_info.systab->ConIn; boot_services = efi_info.systab->BootServices; } if (!(efi_info.flags & READ_CONINFO)) { efi_info.flags |= READ_CONINFO; efi_get_coninfo(&efi_info.coninfo); } if (!(efi_info.flags & READ_FPSWA)) { efi_info.flags |= READ_FPSWA; efi_info.fpswa = efi_get_fpswa(); } if (!(efi_info.flags & READ_MEMMAP)) { efi_info.flags |= READ_MEMMAP; read_efi_mem_map(&efi_info.mem_map); /* Allocate all of the memory efi can spare */ efi_allocate_memory(&efi_info.mem_map); /* Now refresh the memory map */ read_efi_mem_map(&efi_info.mem_map); } /* Get the io_base for legacy i/o */ set_io_base(&efi_info.mem_map); /* Attempt to disable the watchdog timer.. * Nothing useful can be done if this fails, so ignore the return code. */ status = efi_set_watchdog_timer(0, 1, 0, 0); /* Shutdown efi network drivers so efi doesn't get too confused */ efi_stop_nics(); if (efi_info.systab) { static const EFI_GUID mps_table_guid = MPS_TABLE_GUID; static const EFI_GUID acpi20_table_guid = ACPI_20_TABLE_GUID; static const EFI_GUID smbios_table_guid = SMBIOS_TABLE_GUID; static const EFI_GUID sal_system_table_guid = SAL_SYSTEM_TABLE_GUID; static const EFI_GUID nii_table_guid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL; EFI_SYSTEM_TABLE *systab; unsigned i; systab = efi_info.systab; for(i = 0; i < systab->NumberOfTableEntries; i++) { EFI_GUID *guid; void *table = systab->ConfigurationTable[i].VendorTable; guid = &systab->ConfigurationTable[i].VendorGuid;#if 0 printf("GUID: %x-%hx-%hx-%hhx-%hhx-%hhx-%hhx-%hhx-%hhx-%hhx-%hhx Table: %lx\n", guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7], table);#endif if (memcmp(guid, &mps_table_guid, 16) == 0) { mps_table = table; } if (memcmp(guid, &acpi20_table_guid, 16) == 0) { acpi20_table = table; } if (memcmp(guid, &smbios_table_guid, 16) == 0) { smbios_table = table; } if (memcmp(guid, &sal_system_table_guid, 16) == 0) { parse_sal_system_table(table); } if (memcmp(guid, &nii_table_guid, 16) == 0) { nii_table = table; } } }}void arch_on_exit(int status __unused){ if (!boot_services) return; read_efi_mem_map(&efi_info.mem_map); efi_free_memory(&efi_info.mem_map);}void arch_relocate_to(unsigned long addr){ EFI_PHYSICAL_ADDRESS address, end; UINTN pages; EFI_STATUS status; if (!boot_services) return; /* Find the efi pages where the new etherboot will sit */ address = addr & ~(EFI_PAGE_SIZE -1); end = (addr + (_end - _text) + EFI_PAGE_SIZE -1) & ~EFI_PAGE_SIZE; pages = (end - address)/EFI_PAGE_SIZE; /* Reallocate the memory for the new copy of etherboot as LoaderCode */ status = efi_free_pages(address, pages); if (status != EFI_SUCCESS) { printf("efi_free_pages failed!: %lx\n", status); return; } status = efi_allocate_pages(AllocateAddress, EfiLoaderCode, pages, &address); if (status != EFI_SUCCESS) { printf("efi_allocate_pages failed! %lx\n", status); return; }}struct meminfo meminfo;void get_memsizes(void){ EFI_MEMORY_DESCRIPTOR *desc, *end; struct efi_mem_map *map;#define next_desc(desc, size) ((EFI_MEMORY_DESCRIPTOR *)(((char *)(desc)) + (size))) map = &efi_info.mem_map; end = next_desc(map->map, map->map_size); meminfo.map_count = 0; for(desc = map->map; desc < end ; desc = next_desc(desc, map->descriptor_size)) { uint64_t start, size, end; unsigned long mem_k; start = desc->PhysicalStart; size = desc->NumberOfPages*EFI_PAGE_SIZE; end = start + size; if ((desc->Type != EfiLoaderCode) && (desc->Type != EfiLoaderData)) { continue; } meminfo.map[meminfo.map_count].addr = start; meminfo.map[meminfo.map_count].size = size; meminfo.map[meminfo.map_count].type = E820_RAM; meminfo.map_count++; end >>= 10; mem_k = end; if (end & 0xFFFFFFFF00000000ULL) { mem_k = 0xFFFFFFFF; } /* Set the base basememsize */ if ((mem_k <= 640) && (meminfo.basememsize <= mem_k)) { meminfo.basememsize = mem_k; } /* Set the total memsize */ if ((mem_k >= 1024) && (meminfo.memsize <= (mem_k - 1024))) { meminfo.memsize = mem_k - 1024; } if (meminfo.map_count == E820MAX) break; }#undef next_desc}EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE *lookup_efi_nic(int index){ static EFI_GUID protocol = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL; EFI_HANDLE handles[MAX_EFI_DEVICES]; EFI_STATUS status; UINTN devices; void *that; if (!boot_services) return 0; if (index < 0) { return 0; } devices = sizeof(handles); status = efi_locate_handle( ByProtocol, &protocol, 0, &devices, handles); if (status != EFI_SUCCESS) return 0; devices /= sizeof(handles[0]); if (index >= devices) return 0; status = efi_handle_protocol(handles[index], &protocol, &that); if (status != EFI_SUCCESS) return 0; return that;}#if defined(CONSOLE_FIRMWARE)void console_putc(int c){ CHAR16 str[2]; if (!conout) return; str[0] = c; str[1] = 0; __call(conout->OutputString, conout, str);}static int efi_have_key = 0;static int efi_key;int console_ischar(void){ EFI_STATUS status; EFI_INPUT_KEY new_key; if (!conin) return 0; if (efi_have_key) { return 1; } status = __call(conin->ReadKeyStroke, conin, &new_key); if (status == EFI_SUCCESS) { if ((new_key.UnicodeChar >= 0) && (new_key.UnicodeChar < 0x7f)) { efi_have_key = 1; efi_key = new_key.UnicodeChar; } else if (new_key.ScanCode == 0x17) { efi_have_key = 1; efi_key = K_ESC; } } return efi_have_key;}int console_getc(void){ if (efi_have_key) { efi_have_key = 0; } return efi_key;}#endif /* CONSOLE_FIRMWARE */#define NAME "Etherboot"#define FIRMWARE "EFI"#define SZ(X) ((sizeof(X)+3) & ~3)#define CP(D,S) (memcpy(&(D), &(S), sizeof(S)))struct elf_notes { /* CAREFUL this structure is carefully arranged to avoid * alignment problems. */ /* The note header */ struct Elf_Bhdr hdr; /* First the Fixed sized entries that must be well aligned */ /* Insert a nop record so the next record is 64bit aligned */ Elf_Nhdr nf0; /* Pointer to bootp data */ Elf_Nhdr nf1; char nf1_name[SZ(EB_PARAM_NOTE)]; uint64_t nf1_bootp_data; /* Pointer to ELF header */ Elf_Nhdr nf2; char nf2_name[SZ(EB_PARAM_NOTE)]; uint64_t nf2_header; /* The EFI systab pointer */ Elf_Nhdr nf3; char nf3_name[SZ(EB_PARAM_NOTE)]; uint64_t nf3_systab; /* The FPSWA pointer */ Elf_Nhdr nf4; char nf4_name[SZ(EB_PARAM_NOTE)]; uint64_t nf4_fpswa; /* The memory map */ Elf_Nhdr nf5; char nf5_name[SZ(EB_PARAM_NOTE)]; struct efi_mem_map nf5_map; /* The console info, silly but elilo passes it... */ Elf_Nhdr nf6; char nf6_name[SZ(EB_PARAM_NOTE)]; struct console_info nf6_coninfo; /* Then the variable sized data string data where alignment does not matter */ /* The bootloader name */ Elf_Nhdr nv1; char nv1_desc[SZ(NAME)]; /* The bootloader version */ Elf_Nhdr nv2; char nv2_desc[SZ(VERSION)]; /* The firmware type */ Elf_Nhdr nv3; char nv3_desc[SZ(FIRMWARE)]; /* Name of the loaded image */ Elf_Nhdr nv4; char nv4_loaded_image[128]; /* An empty command line */ Elf_Nhdr nv5; char nv5_cmdline[SZ("")];};#define ELF_NOTE_COUNT (6+5)static struct elf_notes notes;struct Elf_Bhdr *prepare_boot_params(void *header){ /* Shutdown the boot services */ if (boot_services) { efi_get_coninfo(&efi_info.coninfo); read_efi_mem_map(&efi_info.mem_map); efi_exit_boot_services(&efi_info.mem_map); } memset(¬es, 0, sizeof(notes)); notes.hdr.b_signature = 0x0E1FB007; notes.hdr.b_size = sizeof(notes); notes.hdr.b_checksum = 0; notes.hdr.b_records = ELF_NOTE_COUNT; /* Initialize the fixed length entries. */ /* Align the fixed length entries to a 64bit boundary */ notes.nf0.n_namesz = 0; notes.nf0.n_descsz = 0; notes.nf0.n_type = EBN_NOP; notes.nf1.n_namesz = sizeof(EB_PARAM_NOTE); notes.nf1.n_descsz = sizeof(notes.nf1_bootp_data); notes.nf1.n_type = EB_BOOTP_DATA; CP(notes.nf1_name, EB_PARAM_NOTE); notes.nf1_bootp_data = virt_to_phys(BOOTP_DATA_ADDR); notes.nf2.n_namesz = sizeof(EB_PARAM_NOTE); notes.nf2.n_descsz = sizeof(notes.nf2_header); notes.nf2.n_type = EB_HEADER; CP(notes.nf2_name, EB_PARAM_NOTE); notes.nf2_header = virt_to_phys(header); notes.nf3.n_namesz = sizeof(EB_PARAM_NOTE); notes.nf3.n_descsz = sizeof(notes.nf3_systab); notes.nf3.n_type = EB_IA64_SYSTAB; CP(notes.nf3_name, EB_PARAM_NOTE); notes.nf3_systab = (unsigned long)efi_info.systab; notes.nf4.n_namesz = sizeof(EB_PARAM_NOTE); notes.nf4.n_descsz = sizeof(notes.nf4_fpswa); notes.nf4.n_type = EB_IA64_FPSWA; CP(notes.nf4_name, EB_PARAM_NOTE); notes.nf4_fpswa = (unsigned long)efi_info.fpswa; notes.nf5.n_namesz = sizeof(EB_PARAM_NOTE); notes.nf5.n_descsz = sizeof(notes.nf5_map); notes.nf5.n_type = EB_IA64_MEMMAP; CP(notes.nf5_name, EB_PARAM_NOTE); notes.nf5_map = efi_info.mem_map; notes.nf6.n_namesz = sizeof(EB_PARAM_NOTE); notes.nf6.n_descsz = sizeof(notes.nf6_coninfo); notes.nf6.n_type = EB_IA64_CONINFO; CP(notes.nf6_name, EB_PARAM_NOTE); notes.nf6_coninfo = efi_info.coninfo; /* Initialize the variable length entries */ notes.nv1.n_namesz = 0; notes.nv1.n_descsz = sizeof(NAME); notes.nv1.n_type = EBN_BOOTLOADER_NAME; CP(notes.nv1_desc, NAME); notes.nv2.n_namesz = 0; notes.nv2.n_descsz = sizeof(VERSION); notes.nv2.n_type = EBN_BOOTLOADER_VERSION; CP(notes.nv2_desc, VERSION); notes.nv3.n_namesz = 0; notes.nv3.n_descsz = sizeof(FIRMWARE); notes.nv3.n_type = EBN_FIRMWARE_TYPE; CP(notes.nv3_desc, FIRMWARE); /* Attempt to pass the name of the loaded image */ notes.nv4.n_namesz = 0; notes.nv4.n_descsz = sizeof(notes.nv4_loaded_image); notes.nv4.n_type = EBN_LOADED_IMAGE; memcpy(¬es.nv4_loaded_image, KERNEL_BUF, sizeof(notes.nv4_loaded_image)); /* Pass an empty command line for now */ notes.nv5.n_namesz = 0; notes.nv5.n_descsz = sizeof(""); notes.nv5.n_type = EBN_COMMAND_LINE; CP(notes.nv5_cmdline, ""); notes.hdr.b_checksum = ipchksum(¬es, sizeof(notes)); /* Like UDP invert a 0 checksum to show that a checksum is present */ if (notes.hdr.b_checksum == 0) { notes.hdr.b_checksum = 0xffff; } return ¬es.hdr;}int elf_start(unsigned long machine __unused, unsigned long entry, unsigned long params){ struct elf_notes *notes; int result; /* Since we can do both be polite and also pass the linux * ia64_boot_param table. */ static struct ia64_boot_param { uint64_t command_line; /* physical address of command line arguments */ uint64_t efi_systab; /* physical address of EFI system table */ uint64_t efi_memmap; /* physical address of EFI memory map */ uint64_t efi_memmap_size; /* size of EFI memory map */ uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */ uint32_t efi_memdesc_version; /* memory descriptor version */ struct { uint16_t num_cols; /* number of columns on console output device */ uint16_t num_rows; /* number of rows on console output device */ uint16_t orig_x; /* cursor's x position */ uint16_t orig_y; /* cursor's y position */ } console_info; uint64_t fpswa; /* physical address of the fpswa interface */ uint64_t initrd_start; uint64_t initrd_size; } bp; notes = phys_to_virt(params); /* If I don't have notes don't attempt to start the image */ if (notes == 0) { return -2; } bp.command_line = (unsigned long)¬es->nv5_cmdline; bp.efi_systab = notes->nf3_systab; bp.efi_memmap = (unsigned long)¬es->nf5_map.map; bp.efi_memmap_size = notes->nf5_map.map_size; bp.efi_memdesc_size = notes->nf5_map.descriptor_size; bp.efi_memdesc_version = notes->nf5_map.descriptor_version; bp.console_info.num_cols = notes->nf6_coninfo.num_cols; bp.console_info.num_rows = notes->nf6_coninfo.num_rows; bp.console_info.orig_x = notes->nf6_coninfo.orig_x; bp.console_info.orig_y = notes->nf6_coninfo.orig_y; bp.fpswa = notes->nf4_fpswa; bp.initrd_start = 0; bp.initrd_size = 0; asm volatile( ";;\n\t" "mov r28=%2\n\t" "mov out0=%3\n\t" "br.call.sptk.few rp=%1\n\t" "mov %0=r8\n\t" : "=r" (result) : "b"(entry), "r"(&bp),"r"(params) ); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -