int grub_efi_get_memory_map (grub_efi_uintn_t *map_key, grub_efi_uintn_t *descriptor_size, grub_efi_uint32_t *descriptor_version) { grub_efi_status_t status; grub_efi_boot_services_t *b; grub_efi_uintn_t key; grub_efi_uint32_t version; grub_efi_uintn_t tmp_mmap_size; /* Allow some parameters to be missing. */ if (! map_key) map_key = &key; if (! descriptor_version) descriptor_version = &version; while (1) { b = grub_efi_system_table->boot_services; tmp_mmap_size = PAGES_TO_BYTES(mmap_pages); status = Call_Service_5 (b->get_memory_map, &tmp_mmap_size, mmap_buf, map_key, descriptor_size, descriptor_version); if (status == GRUB_EFI_SUCCESS) { mmap_size = tmp_mmap_size; return 1; } else if (status != GRUB_EFI_BUFFER_TOO_SMALL) return -1; /* we need a larger buffer */ if (mmap_buf) grub_efi_free_pages ((grub_addr_t) mmap_buf, mmap_pages); /* get 1 more page than we need, just in case */ mmap_pages = BYTES_TO_PAGES(tmp_mmap_size + 4095) + 1; mmap_buf = grub_efi_allocate_pages (0, mmap_pages); if (! mmap_buf) { mmap_pages = 0; grub_printf ("cannot allocate memory for memory map"); return -1; } } }
static grub_err_t grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t file = 0; struct linux_kernel_header lh; grub_ssize_t len, start, filelen; void *kernel = NULL; grub_dl_ref (my_mod); if (argc == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } file = grub_file_open (argv[0]); if (! file) goto fail; filelen = grub_file_size (file); kernel = grub_malloc(filelen); if (!kernel) { grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); goto fail; } if (grub_file_read (file, kernel, filelen) != filelen) { grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]); goto fail; } grub_tpm_measure (kernel, filelen, GRUB_KERNEL_PCR); if (! grub_linuxefi_secure_validate (kernel, filelen)) { grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); grub_free (kernel); goto fail; } params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); if (! params) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate kernel parameters"); goto fail; } grub_memset (params, 0, 16384); grub_memcpy (&lh, kernel, sizeof (lh)); if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) { grub_error (GRUB_ERR_BAD_OS, N_("invalid magic number")); goto fail; } if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) { grub_error (GRUB_ERR_BAD_OS, N_("too many setup sectors")); goto fail; } if (lh.version < grub_cpu_to_le16 (0x020b)) { grub_error (GRUB_ERR_BAD_OS, N_("kernel too old")); goto fail; } if (!lh.handover_offset) { grub_error (GRUB_ERR_BAD_OS, N_("kernel doesn't support EFI handover")); goto fail; } linux_cmdline = grub_efi_allocate_pages_max(0x3fffffff, BYTES_TO_PAGES(lh.cmdline_size + 1)); if (!linux_cmdline) { grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate cmdline")); goto fail; } grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE)); grub_create_loader_cmdline (argc, argv, linux_cmdline + sizeof (LINUX_IMAGE) - 1, lh.cmdline_size - (sizeof (LINUX_IMAGE) - 1)); grub_pass_verity_hash(&lh, linux_cmdline); lh.cmd_line_ptr = (grub_uint32_t)(grub_uint64_t)linux_cmdline; handover_offset = lh.handover_offset; start = (lh.setup_sects + 1) * 512; len = grub_file_size(file) - start; kernel_mem = grub_efi_allocate_pages(lh.pref_address, BYTES_TO_PAGES(lh.init_size)); if (!kernel_mem) kernel_mem = grub_efi_allocate_pages_max(0x3fffffff, BYTES_TO_PAGES(lh.init_size)); if (!kernel_mem) { grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate kernel")); goto fail; } grub_memcpy (kernel_mem, (char *)kernel + start, len); grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0); loaded=1; lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem; grub_memcpy (params, &lh, 2 * 512); params->type_of_loader = 0x21; fail: if (file) grub_file_close (file); if (kernel) grub_free (kernel); if (grub_errno != GRUB_ERR_NONE) { grub_dl_unref (my_mod); loaded = 0; } if (linux_cmdline && !loaded) grub_efi_free_pages((grub_efi_physical_address_t)linux_cmdline, BYTES_TO_PAGES(lh.cmdline_size + 1)); if (kernel_mem && !loaded) grub_efi_free_pages((grub_efi_physical_address_t)kernel_mem, BYTES_TO_PAGES(kernel_size)); if (params && !loaded) grub_efi_free_pages((grub_efi_physical_address_t)params, BYTES_TO_PAGES(16384)); return grub_errno; }