Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | // SPDX-License-Identifier: GPL-2.0+ /* * For the code moved from cmd/bootefi.c * Copyright (c) 2016 Alexander Graf */ #define LOG_CATEGORY LOGC_EFI #include <bootflow.h> #include <charset.h> #include <dm.h> #include <efi.h> #include <efi_device_path.h> #include <efi_loader.h> #include <env.h> #include <image.h> #include <log.h> #include <malloc.h> #include <mapmem.h> #include <net.h> static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; static void *image_addr; static size_t image_size; /** * efi_get_image_parameters() - return image parameters * * @img_addr: address of loaded image in memory * @img_size: size of loaded image */ void efi_get_image_parameters(void **img_addr, size_t *img_size) { *img_addr = image_addr; *img_size = image_size; } /** * efi_clear_bootdev() - clear boot device */ void efi_clear_bootdev(void) { efi_free_pool(bootefi_device_path); efi_free_pool(bootefi_image_path); bootefi_device_path = NULL; bootefi_image_path = NULL; image_addr = NULL; image_size = 0; } /** * efi_set_bootdev() - set boot device * * This function is called when a file is loaded, e.g. via the 'load' command. * We use the path to this file to inform the UEFI binary about the boot device. * * For a valid image, it sets: * - image_addr to the provided buffer * - image_size to the provided buffer_size * - bootefi_device_path to the EFI device-path * - bootefi_image_path to the EFI image-path * * @dev: device, e.g. "MMC" * @devnr: number of the device, e.g. "1:2" * @path: path to file loaded * @buffer: buffer with file loaded * @buffer_size: size of file loaded */ void efi_set_bootdev(const char *dev, const char *devnr, const char *path, void *buffer, size_t buffer_size) { efi_status_t ret; log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev, devnr, path, buffer, buffer_size); /* Forget overwritten image */ if (buffer + buffer_size >= image_addr && image_addr + image_size >= buffer) efi_clear_bootdev(); /* Remember only PE-COFF and FIT images */ if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) { if (IS_ENABLED(CONFIG_FIT) && !fit_check_format(buffer, IMAGE_SIZE_INVAL)) { /* * FIT images of type EFI_OS are started via command * bootm. We should not use their boot device with the * bootefi command. */ buffer = 0; buffer_size = 0; } else { log_debug("- not remembering image\n"); return; } } /* efi_set_bootdev() is typically called repeatedly, recover memory */ efi_clear_bootdev(); image_addr = buffer; image_size = buffer_size; ret = calculate_paths(dev, devnr, path, &bootefi_device_path, &bootefi_image_path); if (ret) { log_debug("- efi_dp_from_name() failed, err=%lx\n", ret); efi_clear_bootdev(); } } /** * efi_binary_run() - run loaded UEFI image * * @image: memory address of the UEFI image * @size: size of the UEFI image * @fdt: device-tree * @initrd: initrd * @initrd_sz: initrd size * * Execute an EFI binary image loaded at @image. * @size may be zero if the binary is loaded with U-Boot load command. * * Return: status code */ efi_status_t efi_binary_run(void *image, size_t size, void *fdt, void *initrd, size_t initrd_sz) { efi_handle_t mem_handle = NULL; struct efi_device_path *file_path = NULL; efi_status_t ret; if (!bootefi_device_path || !bootefi_image_path) { log_debug("Not loaded from disk\n"); /* * Special case for efi payload not loaded from disk, * such as 'bootefi hello' or for example payload * loaded directly into memory via JTAG, etc: */ file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, image, size); /* * Make sure that device for device_path exist * in load_image(). Otherwise, shell and grub will fail. */ ret = efi_install_multiple_protocol_interfaces(&mem_handle, &efi_guid_device_path, file_path, NULL); if (ret != EFI_SUCCESS) goto out; bootefi_device_path = file_path; bootefi_image_path = NULL; } else { log_debug("Loaded from disk\n"); } ret = efi_binary_run_dp(image, size, fdt, initrd, initrd_sz, bootefi_device_path, bootefi_image_path); out: if (mem_handle) { efi_status_t r; r = efi_uninstall_multiple_protocol_interfaces(mem_handle, &efi_guid_device_path, file_path, NULL); if (r != EFI_SUCCESS) log_err("Uninstalling protocol interfaces failed\n"); } efi_free_pool(file_path); return ret; } |