struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg) { struct screen_info *si; efi_status_t status; /* * Unlike on arm64, where we can directly fill out the screen_info * structure from the stub, we need to allocate a buffer to hold * its contents while we hand over to the kernel proper from the * decompressor. */ status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA, sizeof(*si), (void **)&si); if (status != EFI_SUCCESS) return NULL; status = efi_call_early(install_configuration_table, &screen_info_guid, si); if (status == EFI_SUCCESS) return si; efi_call_early(free_pool, si); return NULL; }
void setup_graphics(struct boot_params *boot_params) { efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; struct screen_info *si; efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; efi_status_t status; unsigned long size; void **gop_handle = NULL; void **uga_handle = NULL; si = &boot_params->screen_info; memset(si, 0, sizeof(*si)); size = 0; status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, &graphics_proto, NULL, &size, gop_handle); if (status == EFI_BUFFER_TOO_SMALL) status = efi_setup_gop(NULL, si, &graphics_proto, size); if (status != EFI_SUCCESS) { size = 0; status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, &uga_proto, NULL, &size, uga_handle); if (status == EFI_BUFFER_TOO_SMALL) setup_uga(si, &uga_proto, size); } }
void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si) { if (!si) return; efi_call_early(install_configuration_table, &screen_info_guid, NULL); efi_call_early(free_pool, si); }
static efi_status_t __file_size64(void *__fh, efi_char16_t *filename_16, void **handle, u64 *file_sz) { efi_file_handle_64_t *h, *fh = __fh; efi_file_info_t *info; efi_status_t status; efi_guid_t info_guid = EFI_FILE_INFO_ID; u64 info_sz; status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16, EFI_FILE_MODE_READ, (u64)0); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to open file: "); efi_char16_printk(sys_table, filename_16); efi_printk(sys_table, "\n"); return status; } *handle = h; info_sz = 0; status = efi_early->call((unsigned long)h->get_info, h, &info_guid, &info_sz, NULL); if (status != EFI_BUFFER_TOO_SMALL) { efi_printk(sys_table, "Failed to get file info size\n"); return status; } grow: status = efi_call_early(allocate_pool, EFI_LOADER_DATA, info_sz, (void **)&info); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to alloc mem for file info\n"); return status; } status = efi_early->call((unsigned long)h->get_info, h, &info_guid, &info_sz, info); if (status == EFI_BUFFER_TOO_SMALL) { efi_call_early(free_pool, info); goto grow; } *file_sz = info->file_size; efi_call_early(free_pool, info); if (status != EFI_SUCCESS) efi_printk(sys_table, "Failed to get initrd info\n"); return status; }
/* * See if we have Universal Graphics Adapter (UGA) protocol */ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size) { efi_status_t status; u32 width, height; void **uga_handle = NULL; status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, (void **)&uga_handle); if (status != EFI_SUCCESS) return status; status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, uga_proto, NULL, &size, uga_handle); if (status != EFI_SUCCESS) goto free_handle; height = 0; width = 0; if (efi_early->is64) status = setup_uga64(uga_handle, size, &width, &height); else status = setup_uga32(uga_handle, size, &width, &height); if (!width && !height) goto free_handle; /* EFI framebuffer */ si->orig_video_isVGA = VIDEO_TYPE_EFI; si->lfb_depth = 32; si->lfb_width = width; si->lfb_height = height; si->red_size = 8; si->red_pos = 16; si->green_size = 8; si->green_pos = 8; si->blue_size = 8; si->blue_pos = 0; si->rsvd_size = 8; si->rsvd_pos = 24; free_handle: efi_call_early(free_pool, uga_handle); return status; }
efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, efi_memory_desc_t **map, unsigned long *map_size, unsigned long *desc_size, u32 *desc_ver, unsigned long *key_ptr) { efi_memory_desc_t *m = NULL; efi_status_t status; unsigned long key; u32 desc_version; *map_size = 0; *desc_size = 0; key = 0; status = efi_call_early(get_memory_map, map_size, NULL, &key, desc_size, &desc_version); if (status != EFI_BUFFER_TOO_SMALL) return EFI_LOAD_ERROR; /* * Add an additional efi_memory_desc_t because we're doing an * allocation which may be in a new descriptor region. */ *map_size += *desc_size; status = efi_call_early(allocate_pool, EFI_LOADER_DATA, *map_size, (void **)&m); if (status != EFI_SUCCESS) goto fail; status = efi_call_early(get_memory_map, map_size, m, &key, desc_size, &desc_version); if (status == EFI_BUFFER_TOO_SMALL) { efi_call_early(free_pool, m); return EFI_LOAD_ERROR; } if (status != EFI_SUCCESS) efi_call_early(free_pool, m); if (key_ptr && status == EFI_SUCCESS) *key_ptr = key; if (desc_ver && status == EFI_SUCCESS) *desc_ver = desc_version; fail: *map = m; return status; }
static inline efi_status_t __open_volume64(void *__image, void **__fh) { efi_file_io_interface_t *io; efi_loaded_image_64_t *image = __image; efi_file_handle_64_t *fh; efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; efi_status_t status; void *handle = (void *)(unsigned long)image->device_handle; unsigned long func; status = efi_call_early(handle_protocol, handle, &fs_proto, (void **)&io); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to handle fs_proto\n"); return status; } func = (unsigned long)io->open_volume; status = efi_early->call(func, io, &fh); if (status != EFI_SUCCESS) efi_printk(sys_table, "Failed to open volume\n"); *__fh = fh; return status; }
/* * Relocate a kernel image, either compressed or uncompressed. * In the ARM64 case, all kernel images are currently * uncompressed, and as such when we relocate it we need to * allocate additional space for the BSS segment. Any low * memory that this function should avoid needs to be * unavailable in the EFI memory map, as if the preferred * address is not available the lowest available address will * be used. */ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, unsigned long *image_addr, unsigned long image_size, unsigned long alloc_size, unsigned long preferred_addr, unsigned long alignment) { unsigned long cur_image_addr; unsigned long new_addr = 0; efi_status_t status; unsigned long nr_pages; efi_physical_addr_t efi_addr = preferred_addr; if (!image_addr || !image_size || !alloc_size) return EFI_INVALID_PARAMETER; if (alloc_size < image_size) return EFI_INVALID_PARAMETER; cur_image_addr = *image_addr; /* * The EFI firmware loader could have placed the kernel image * anywhere in memory, but the kernel has restrictions on the * max physical address it can run at. Some architectures * also have a prefered address, so first try to relocate * to the preferred address. If that fails, allocate as low * as possible while respecting the required alignment. */ nr_pages = round_up(alloc_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, nr_pages, &efi_addr); new_addr = efi_addr; /* * If preferred address allocation failed allocate as low as * possible. */ if (status != EFI_SUCCESS) { status = efi_low_alloc(sys_table_arg, alloc_size, alignment, &new_addr); } if (status != EFI_SUCCESS) { efi_printk(sys_table_arg, "ERROR: Failed to allocate usable memory for kernel.\n"); return status; } /* * We know source/dest won't overlap since both memory ranges * have been allocated by UEFI, so we can safely use memcpy. */ memcpy((void *)new_addr, (void *)cur_image_addr, image_size); /* Return the new address of the relocated image. */ *image_addr = new_addr; return status; }
static efi_status_t setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height) { struct efi_uga_draw_protocol *uga = NULL, *first_uga; efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID; unsigned long nr_ugas; u64 *handles = (u64 *)uga_handle;; efi_status_t status = EFI_INVALID_PARAMETER; int i; first_uga = NULL; nr_ugas = size / sizeof(u64); for (i = 0; i < nr_ugas; i++) { efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; u32 w, h, depth, refresh; void *pciio; u64 handle = handles[i]; status = efi_call_early(handle_protocol, handle, &uga_proto, (void **)&uga); if (status != EFI_SUCCESS) continue; efi_call_early(handle_protocol, handle, &pciio_proto, &pciio); status = efi_early->call((unsigned long)uga->get_mode, uga, &w, &h, &depth, &refresh); if (status == EFI_SUCCESS && (!first_uga || pciio)) { *width = w; *height = h; /* * Once we've found a UGA supporting PCIIO, * don't bother looking any further. */ if (pciio) break; first_uga = uga; } } return status; }
static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, unsigned long addr) { unsigned long nr_pages; if (!size) return; nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; efi_call_early(free_pages, addr, nr_pages); }
static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext, u32 *e820ext_size) { efi_status_t status; unsigned long size; size = sizeof(struct setup_data) + sizeof(struct e820entry) * nr_desc; if (*e820ext) { efi_call_early(free_pool, *e820ext); *e820ext = NULL; *e820ext_size = 0; } status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, (void **)e820ext); if (status == EFI_SUCCESS) *e820ext_size = size; return status; }
/* * There's no way to return an informative status from this function, * because any analysis (and printing of error messages) needs to be * done directly at the EFI function call-site. * * For example, EFI_INVALID_PARAMETER could indicate a bug or maybe we * just didn't find any PCI devices, but there's no way to tell outside * the context of the call. */ static void setup_efi_pci(struct boot_params *params) { efi_status_t status; void **pci_handle = NULL; efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; unsigned long size = 0; status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto, NULL, &size, pci_handle); if (status == EFI_BUFFER_TOO_SMALL) { status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, (void **)&pci_handle); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to alloc mem for pci_handle\n"); return; } status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto, NULL, &size, pci_handle); } if (status != EFI_SUCCESS) goto free_handle; if (efi_early->is64) setup_efi_pci64(params, pci_handle, size); else setup_efi_pci32(params, pci_handle, size); free_handle: efi_call_early(free_pool, pci_handle); }
static void setup_efi_pci64(struct boot_params *params, void **pci_handle, unsigned long size) { efi_pci_io_protocol_64 *pci = NULL; efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; u64 *handles = (u64 *)(unsigned long)pci_handle; efi_status_t status; unsigned long nr_pci; struct setup_data *data; int i; data = (struct setup_data *)(unsigned long)params->hdr.setup_data; while (data && data->next) data = (struct setup_data *)(unsigned long)data->next; nr_pci = size / sizeof(u64); for (i = 0; i < nr_pci; i++) { struct pci_setup_rom *rom = NULL; u64 h = handles[i]; status = efi_call_early(handle_protocol, h, &pci_proto, (void **)&pci); if (status != EFI_SUCCESS) continue; if (!pci) continue; status = __setup_efi_pci64(pci, &rom); if (status != EFI_SUCCESS) continue; if (data) data->next = (unsigned long)rom; else params->hdr.setup_data = (unsigned long)rom; data = (struct setup_data *)rom; } }
static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg) { efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; efi_status_t status; unsigned long size; void **gop_handle = NULL; struct screen_info *si = NULL; size = 0; status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL, &gop_proto, NULL, &size, gop_handle); if (status == EFI_BUFFER_TOO_SMALL) { si = alloc_screen_info(sys_table_arg); if (!si) return NULL; efi_setup_gop(sys_table_arg, si, &gop_proto, size); } return si; }
unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) { efi_status_t status; unsigned long map_size; unsigned long membase = EFI_ERROR; struct efi_memory_map map; efi_memory_desc_t *md; status = efi_get_memory_map(sys_table_arg, (efi_memory_desc_t **)&map.map, &map_size, &map.desc_size, NULL, NULL); if (status != EFI_SUCCESS) return membase; map.map_end = map.map + map_size; for_each_efi_memory_desc(&map, md) if (md->attribute & EFI_MEMORY_WB) if (membase > md->phys_addr) membase = md->phys_addr; efi_call_early(free_pool, map.map); return membase; }
/* * Allocate at the highest possible address that is not above 'max'. */ static efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, unsigned long size, unsigned long align, unsigned long *addr, unsigned long max) { unsigned long map_size, desc_size; efi_memory_desc_t *map; efi_status_t status; unsigned long nr_pages; u64 max_addr = 0; int i; status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size, NULL, NULL); if (status != EFI_SUCCESS) goto fail; /* * Enforce minimum alignment that EFI requires when requesting * a specific address. We are doing page-based allocations, * so we must be aligned to a page. */ if (align < EFI_PAGE_SIZE) align = EFI_PAGE_SIZE; nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; again: for (i = 0; i < map_size / desc_size; i++) { efi_memory_desc_t *desc; unsigned long m = (unsigned long)map; u64 start, end; desc = (efi_memory_desc_t *)(m + (i * desc_size)); if (desc->type != EFI_CONVENTIONAL_MEMORY) continue; if (desc->num_pages < nr_pages) continue; start = desc->phys_addr; end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); if ((start + size) > end || (start + size) > max) continue; if (end - size > max) end = max; if (round_down(end - size, align) < start) continue; start = round_down(end - size, align); /* * Don't allocate at 0x0. It will confuse code that * checks pointers against NULL. */ if (start == 0x0) continue; if (start > max_addr) max_addr = start; } if (!max_addr) status = EFI_NOT_FOUND; else { status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, nr_pages, &max_addr); if (status != EFI_SUCCESS) { max = max_addr; max_addr = 0; goto again; } *addr = max_addr; } efi_call_early(free_pool, map); fail: return status; }
static efi_status_t __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom) { struct pci_setup_rom *rom; efi_status_t status; unsigned long size; uint64_t attributes; status = efi_early->call(pci->attributes, pci, EfiPciIoAttributeOperationGet, 0, &attributes); if (status != EFI_SUCCESS) return status; if (!pci->romimage || !pci->romsize) return EFI_INVALID_PARAMETER; size = pci->romsize + sizeof(*rom); status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to alloc mem for rom\n"); return status; } rom->data.type = SETUP_PCI; rom->data.len = size - sizeof(struct setup_data); rom->data.next = 0; rom->pcilen = pci->romsize; *__rom = rom; status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1, &(rom->vendor)); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to read rom->vendor\n"); goto free_struct; } status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1, &(rom->devid)); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to read rom->devid\n"); goto free_struct; } status = efi_early->call(pci->get_location, pci, &(rom->segment), &(rom->bus), &(rom->device), &(rom->function)); if (status != EFI_SUCCESS) goto free_struct; memcpy(rom->romdata, pci->romimage, pci->romsize); return status; free_struct: efi_call_early(free_pool, rom); return status; }
/* * Check the cmdline for a LILO-style file= arguments. * * We only support loading a file from the same filesystem as * the kernel image. */ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, efi_loaded_image_t *image, char *cmd_line, char *option_string, unsigned long max_addr, unsigned long *load_addr, unsigned long *load_size) { struct file_info *files; unsigned long file_addr; u64 file_size_total; efi_file_handle_t *fh; efi_status_t status; int nr_files; char *str; int i, j, k; file_addr = 0; file_size_total = 0; str = cmd_line; j = 0; /* See close_handles */ if (!load_addr || !load_size) return EFI_INVALID_PARAMETER; *load_addr = 0; *load_size = 0; if (!str || !*str) return EFI_SUCCESS; for (nr_files = 0; *str; nr_files++) { str = strstr(str, option_string); if (!str) break; str += strlen(option_string); /* Skip any leading slashes */ while (*str == '/' || *str == '\\') str++; while (*str && *str != ' ' && *str != '\n') str++; } if (!nr_files) return EFI_SUCCESS; status = efi_call_early(allocate_pool, EFI_LOADER_DATA, nr_files * sizeof(*files), (void **)&files); if (status != EFI_SUCCESS) { efi_printk(sys_table_arg, "Failed to alloc mem for file handle list\n"); goto fail; } str = cmd_line; for (i = 0; i < nr_files; i++) { struct file_info *file; efi_char16_t filename_16[256]; efi_char16_t *p; str = strstr(str, option_string); if (!str) break; str += strlen(option_string); file = &files[i]; p = filename_16; /* Skip any leading slashes */ while (*str == '/' || *str == '\\') str++; while (*str && *str != ' ' && *str != '\n') { if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16)) break; if (*str == '/') { *p++ = '\\'; str++; } else { *p++ = *str++; } } *p = '\0'; /* Only open the volume once. */ if (!i) { status = efi_open_volume(sys_table_arg, image, (void **)&fh); if (status != EFI_SUCCESS) goto free_files; } status = efi_file_size(sys_table_arg, fh, filename_16, (void **)&file->handle, &file->size); if (status != EFI_SUCCESS) goto close_handles; file_size_total += file->size; } if (file_size_total) { unsigned long addr; /* * Multiple files need to be at consecutive addresses in memory, * so allocate enough memory for all the files. This is used * for loading multiple files. */ status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000, &file_addr, max_addr); if (status != EFI_SUCCESS) { efi_printk(sys_table_arg, "Failed to alloc highmem for files\n"); goto close_handles; } /* We've run out of free low memory. */ if (file_addr > max_addr) { efi_printk(sys_table_arg, "We've run out of free low memory\n"); status = EFI_INVALID_PARAMETER; goto free_file_total; } addr = file_addr; for (j = 0; j < nr_files; j++) { unsigned long size; size = files[j].size; while (size) { unsigned long chunksize; if (size > EFI_READ_CHUNK_SIZE) chunksize = EFI_READ_CHUNK_SIZE; else chunksize = size; status = efi_file_read(fh, files[j].handle, &chunksize, (void *)addr); if (status != EFI_SUCCESS) { efi_printk(sys_table_arg, "Failed to read file\n"); goto free_file_total; } addr += chunksize; size -= chunksize; } efi_file_close(fh, files[j].handle); } } efi_call_early(free_pool, files); *load_addr = file_addr; *load_size = file_size_total; return status; free_file_total: efi_free(sys_table_arg, file_size_total, file_addr); close_handles: for (k = j; k < i; k++) efi_file_close(fh, files[k].handle); free_files: efi_call_early(free_pool, files); fail: *load_addr = 0; *load_size = 0; return status; }
/* * Allocate at the lowest possible address. */ static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, unsigned long size, unsigned long align, unsigned long *addr) { unsigned long map_size, desc_size; efi_memory_desc_t *map; efi_status_t status; unsigned long nr_pages; int i; status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size, NULL, NULL); if (status != EFI_SUCCESS) goto fail; /* * Enforce minimum alignment that EFI requires when requesting * a specific address. We are doing page-based allocations, * so we must be aligned to a page. */ if (align < EFI_PAGE_SIZE) align = EFI_PAGE_SIZE; nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; for (i = 0; i < map_size / desc_size; i++) { efi_memory_desc_t *desc; unsigned long m = (unsigned long)map; u64 start, end; desc = (efi_memory_desc_t *)(m + (i * desc_size)); if (desc->type != EFI_CONVENTIONAL_MEMORY) continue; if (desc->num_pages < nr_pages) continue; start = desc->phys_addr; end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); /* * Don't allocate at 0x0. It will confuse code that * checks pointers against NULL. Skip the first 8 * bytes so we start at a nice even number. */ if (start == 0x0) start += 8; start = round_up(start, align); if ((start + size) > end) continue; status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, nr_pages, &start); if (status == EFI_SUCCESS) { *addr = start; break; } } if (i == map_size / desc_size) status = EFI_NOT_FOUND; efi_call_early(free_pool, map); fail: return status; }
static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) { efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID; efi_status_t status; efi_physical_addr_t log_location, log_last_entry; struct linux_efi_tpm_eventlog *log_tbl = NULL; unsigned long first_entry_addr, last_entry_addr; size_t log_size, last_entry_size; efi_bool_t truncated; void *tcg2_protocol = NULL; status = efi_call_early(locate_protocol, &tcg2_guid, NULL, &tcg2_protocol); if (status != EFI_SUCCESS) return; status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2, &log_location, &log_last_entry, &truncated); if (status != EFI_SUCCESS) return; if (!log_location) return; first_entry_addr = (unsigned long) log_location; /* * We populate the EFI table even if the logs are empty. */ if (!log_last_entry) { log_size = 0; } else { last_entry_addr = (unsigned long) log_last_entry; /* * get_event_log only returns the address of the last entry. * We need to calculate its size to deduce the full size of * the logs. */ last_entry_size = sizeof(struct tcpa_event) + ((struct tcpa_event *) last_entry_addr)->event_size; log_size = log_last_entry - log_location + last_entry_size; } /* Allocate space for the logs and copy them. */ status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*log_tbl) + log_size, (void **) &log_tbl); if (status != EFI_SUCCESS) { efi_printk(sys_table_arg, "Unable to allocate memory for event log\n"); return; } memset(log_tbl, 0, sizeof(*log_tbl) + log_size); log_tbl->size = log_size; log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; memcpy(log_tbl->log, (void *) first_entry_addr, log_size); status = efi_call_early(install_configuration_table, &linux_eventlog_guid, log_tbl); if (status != EFI_SUCCESS) goto err_free; return; err_free: efi_call_early(free_pool, log_tbl); }
/* * Because the x86 boot code expects to be passed a boot_params we * need to create one ourselves (usually the bootloader would create * one for us). * * The caller is responsible for filling out ->code32_start in the * returned boot_params. */ struct boot_params *make_boot_params(struct efi_config *c) { struct boot_params *boot_params; struct apm_bios_info *bi; struct setup_header *hdr; efi_loaded_image_t *image; void *options, *handle; efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; int options_size = 0; efi_status_t status; char *cmdline_ptr; u16 *s2; u8 *s1; int i; unsigned long ramdisk_addr; unsigned long ramdisk_size; efi_early = c; sys_table = (efi_system_table_t *)(unsigned long)efi_early->table; handle = (void *)(unsigned long)efi_early->image_handle; /* Check if we were booted by the EFI firmware */ if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) return NULL; if (efi_early->is64) setup_boot_services64(efi_early); else setup_boot_services32(efi_early); status = efi_call_early(handle_protocol, handle, &proto, (void *)&image); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); return NULL; } status = efi_low_alloc(sys_table, 0x4000, 1, (unsigned long *)&boot_params); if (status != EFI_SUCCESS) { efi_printk(sys_table, "Failed to alloc lowmem for boot params\n"); return NULL; } memset(boot_params, 0x0, 0x4000); hdr = &boot_params->hdr; bi = &boot_params->apm_bios_info; /* Copy the second sector to boot_params */ memcpy(&hdr->jump, image->image_base + 512, 512); /* * Fill out some of the header fields ourselves because the * EFI firmware loader doesn't load the first sector. */ hdr->root_flags = 1; hdr->vid_mode = 0xffff; hdr->boot_flag = 0xAA55; hdr->type_of_loader = 0x21; /* Convert unicode cmdline to ascii */ cmdline_ptr = efi_convert_cmdline(sys_table, image, &options_size); if (!cmdline_ptr) goto fail; hdr->cmd_line_ptr = (unsigned long)cmdline_ptr; /* Fill in upper bits of command line address, NOP on 32 bit */ boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32; hdr->ramdisk_image = 0; hdr->ramdisk_size = 0; /* Clear APM BIOS info */ memset(bi, 0, sizeof(*bi)); status = efi_parse_options(cmdline_ptr); if (status != EFI_SUCCESS) goto fail2; status = handle_cmdline_files(sys_table, image, (char *)(unsigned long)hdr->cmd_line_ptr, "initrd=", hdr->initrd_addr_max, &ramdisk_addr, &ramdisk_size); if (status != EFI_SUCCESS && hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G) { efi_printk(sys_table, "Trying to load files to higher address\n"); status = handle_cmdline_files(sys_table, image, (char *)(unsigned long)hdr->cmd_line_ptr, "initrd=", -1UL, &ramdisk_addr, &ramdisk_size); } if (status != EFI_SUCCESS) goto fail2; hdr->ramdisk_image = ramdisk_addr & 0xffffffff; hdr->ramdisk_size = ramdisk_size & 0xffffffff; boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32; boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; return boot_params; fail2: efi_free(sys_table, options_size, hdr->cmd_line_ptr); fail: efi_free(sys_table, 0x4000, (unsigned long)boot_params); return NULL; }