linux/drivers/firmware/efi/libstub/efi-stub-helper.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Helper functions used by the EFI stub on multiple
   4 * architectures. This should be #included by the EFI stub
   5 * implementation files.
   6 *
   7 * Copyright 2011 Intel Corporation; author Matt Fleming
   8 */
   9
  10#include <linux/efi.h>
  11#include <asm/efi.h>
  12
  13#include "efistub.h"
  14
  15static bool __efistub_global efi_nochunk;
  16static bool __efistub_global efi_nokaslr;
  17static bool __efistub_global efi_noinitrd;
  18static bool __efistub_global efi_quiet;
  19static bool __efistub_global efi_novamap;
  20static bool __efistub_global efi_nosoftreserve;
  21static bool __efistub_global efi_disable_pci_dma =
  22                                        IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
  23
  24bool __pure nochunk(void)
  25{
  26        return efi_nochunk;
  27}
  28bool __pure nokaslr(void)
  29{
  30        return efi_nokaslr;
  31}
  32bool __pure noinitrd(void)
  33{
  34        return efi_noinitrd;
  35}
  36bool __pure is_quiet(void)
  37{
  38        return efi_quiet;
  39}
  40bool __pure novamap(void)
  41{
  42        return efi_novamap;
  43}
  44bool __pure __efi_soft_reserve_enabled(void)
  45{
  46        return !efi_nosoftreserve;
  47}
  48
  49void efi_printk(char *str)
  50{
  51        char *s8;
  52
  53        for (s8 = str; *s8; s8++) {
  54                efi_char16_t ch[2] = { 0 };
  55
  56                ch[0] = *s8;
  57                if (*s8 == '\n') {
  58                        efi_char16_t nl[2] = { '\r', 0 };
  59                        efi_char16_printk(nl);
  60                }
  61
  62                efi_char16_printk(ch);
  63        }
  64}
  65
  66/*
  67 * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi=
  68 * option, e.g. efi=nochunk.
  69 *
  70 * It should be noted that efi= is parsed in two very different
  71 * environments, first in the early boot environment of the EFI boot
  72 * stub, and subsequently during the kernel boot.
  73 */
  74efi_status_t efi_parse_options(char const *cmdline)
  75{
  76        size_t len = strlen(cmdline) + 1;
  77        efi_status_t status;
  78        char *str, *buf;
  79
  80        status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, len, (void **)&buf);
  81        if (status != EFI_SUCCESS)
  82                return status;
  83
  84        str = skip_spaces(memcpy(buf, cmdline, len));
  85
  86        while (*str) {
  87                char *param, *val;
  88
  89                str = next_arg(str, &param, &val);
  90
  91                if (!strcmp(param, "nokaslr")) {
  92                        efi_nokaslr = true;
  93                } else if (!strcmp(param, "quiet")) {
  94                        efi_quiet = true;
  95                } else if (!strcmp(param, "noinitrd")) {
  96                        efi_noinitrd = true;
  97                } else if (!strcmp(param, "efi") && val) {
  98                        efi_nochunk = parse_option_str(val, "nochunk");
  99                        efi_novamap = parse_option_str(val, "novamap");
 100
 101                        efi_nosoftreserve = IS_ENABLED(CONFIG_EFI_SOFT_RESERVE) &&
 102                                            parse_option_str(val, "nosoftreserve");
 103
 104                        if (parse_option_str(val, "disable_early_pci_dma"))
 105                                efi_disable_pci_dma = true;
 106                        if (parse_option_str(val, "no_disable_early_pci_dma"))
 107                                efi_disable_pci_dma = false;
 108                }
 109        }
 110        efi_bs_call(free_pool, buf);
 111        return EFI_SUCCESS;
 112}
 113
 114/*
 115 * Get the number of UTF-8 bytes corresponding to an UTF-16 character.
 116 * This overestimates for surrogates, but that is okay.
 117 */
 118static int efi_utf8_bytes(u16 c)
 119{
 120        return 1 + (c >= 0x80) + (c >= 0x800);
 121}
 122
 123/*
 124 * Convert an UTF-16 string, not necessarily null terminated, to UTF-8.
 125 */
 126static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n)
 127{
 128        unsigned int c;
 129
 130        while (n--) {
 131                c = *src++;
 132                if (n && c >= 0xd800 && c <= 0xdbff &&
 133                    *src >= 0xdc00 && *src <= 0xdfff) {
 134                        c = 0x10000 + ((c & 0x3ff) << 10) + (*src & 0x3ff);
 135                        src++;
 136                        n--;
 137                }
 138                if (c >= 0xd800 && c <= 0xdfff)
 139                        c = 0xfffd; /* Unmatched surrogate */
 140                if (c < 0x80) {
 141                        *dst++ = c;
 142                        continue;
 143                }
 144                if (c < 0x800) {
 145                        *dst++ = 0xc0 + (c >> 6);
 146                        goto t1;
 147                }
 148                if (c < 0x10000) {
 149                        *dst++ = 0xe0 + (c >> 12);
 150                        goto t2;
 151                }
 152                *dst++ = 0xf0 + (c >> 18);
 153                *dst++ = 0x80 + ((c >> 12) & 0x3f);
 154        t2:
 155                *dst++ = 0x80 + ((c >> 6) & 0x3f);
 156        t1:
 157                *dst++ = 0x80 + (c & 0x3f);
 158        }
 159
 160        return dst;
 161}
 162
 163/*
 164 * Convert the unicode UEFI command line to ASCII to pass to kernel.
 165 * Size of memory allocated return in *cmd_line_len.
 166 * Returns NULL on error.
 167 */
 168char *efi_convert_cmdline(efi_loaded_image_t *image,
 169                          int *cmd_line_len, unsigned long max_addr)
 170{
 171        const u16 *s2;
 172        u8 *s1 = NULL;
 173        unsigned long cmdline_addr = 0;
 174        int load_options_chars = efi_table_attr(image, load_options_size) / 2;
 175        const u16 *options = efi_table_attr(image, load_options);
 176        int options_bytes = 0;  /* UTF-8 bytes */
 177        int options_chars = 0;  /* UTF-16 chars */
 178        efi_status_t status;
 179        u16 zero = 0;
 180
 181        if (options) {
 182                s2 = options;
 183                while (*s2 && *s2 != '\n'
 184                       && options_chars < load_options_chars) {
 185                        options_bytes += efi_utf8_bytes(*s2++);
 186                        options_chars++;
 187                }
 188        }
 189
 190        if (!options_chars) {
 191                /* No command line options, so return empty string*/
 192                options = &zero;
 193        }
 194
 195        options_bytes++;        /* NUL termination */
 196
 197        status = efi_allocate_pages(options_bytes, &cmdline_addr, max_addr);
 198        if (status != EFI_SUCCESS)
 199                return NULL;
 200
 201        s1 = (u8 *)cmdline_addr;
 202        s2 = (const u16 *)options;
 203
 204        s1 = efi_utf16_to_utf8(s1, s2, options_chars);
 205        *s1 = '\0';
 206
 207        *cmd_line_len = options_bytes;
 208        return (char *)cmdline_addr;
 209}
 210
 211/*
 212 * Handle calling ExitBootServices according to the requirements set out by the
 213 * spec.  Obtains the current memory map, and returns that info after calling
 214 * ExitBootServices.  The client must specify a function to perform any
 215 * processing of the memory map data prior to ExitBootServices.  A client
 216 * specific structure may be passed to the function via priv.  The client
 217 * function may be called multiple times.
 218 */
 219efi_status_t efi_exit_boot_services(void *handle,
 220                                    struct efi_boot_memmap *map,
 221                                    void *priv,
 222                                    efi_exit_boot_map_processing priv_func)
 223{
 224        efi_status_t status;
 225
 226        status = efi_get_memory_map(map);
 227
 228        if (status != EFI_SUCCESS)
 229                goto fail;
 230
 231        status = priv_func(map, priv);
 232        if (status != EFI_SUCCESS)
 233                goto free_map;
 234
 235        if (efi_disable_pci_dma)
 236                efi_pci_disable_bridge_busmaster();
 237
 238        status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
 239
 240        if (status == EFI_INVALID_PARAMETER) {
 241                /*
 242                 * The memory map changed between efi_get_memory_map() and
 243                 * exit_boot_services().  Per the UEFI Spec v2.6, Section 6.4:
 244                 * EFI_BOOT_SERVICES.ExitBootServices we need to get the
 245                 * updated map, and try again.  The spec implies one retry
 246                 * should be sufficent, which is confirmed against the EDK2
 247                 * implementation.  Per the spec, we can only invoke
 248                 * get_memory_map() and exit_boot_services() - we cannot alloc
 249                 * so efi_get_memory_map() cannot be used, and we must reuse
 250                 * the buffer.  For all practical purposes, the headroom in the
 251                 * buffer should account for any changes in the map so the call
 252                 * to get_memory_map() is expected to succeed here.
 253                 */
 254                *map->map_size = *map->buff_size;
 255                status = efi_bs_call(get_memory_map,
 256                                     map->map_size,
 257                                     *map->map,
 258                                     map->key_ptr,
 259                                     map->desc_size,
 260                                     map->desc_ver);
 261
 262                /* exit_boot_services() was called, thus cannot free */
 263                if (status != EFI_SUCCESS)
 264                        goto fail;
 265
 266                status = priv_func(map, priv);
 267                /* exit_boot_services() was called, thus cannot free */
 268                if (status != EFI_SUCCESS)
 269                        goto fail;
 270
 271                status = efi_bs_call(exit_boot_services, handle, *map->key_ptr);
 272        }
 273
 274        /* exit_boot_services() was called, thus cannot free */
 275        if (status != EFI_SUCCESS)
 276                goto fail;
 277
 278        return EFI_SUCCESS;
 279
 280free_map:
 281        efi_bs_call(free_pool, *map->map);
 282fail:
 283        return status;
 284}
 285
 286void *get_efi_config_table(efi_guid_t guid)
 287{
 288        unsigned long tables = efi_table_attr(efi_system_table(), tables);
 289        int nr_tables = efi_table_attr(efi_system_table(), nr_tables);
 290        int i;
 291
 292        for (i = 0; i < nr_tables; i++) {
 293                efi_config_table_t *t = (void *)tables;
 294
 295                if (efi_guidcmp(t->guid, guid) == 0)
 296                        return efi_table_attr(t, table);
 297
 298                tables += efi_is_native() ? sizeof(efi_config_table_t)
 299                                          : sizeof(efi_config_table_32_t);
 300        }
 301        return NULL;
 302}
 303
 304void efi_char16_printk(efi_char16_t *str)
 305{
 306        efi_call_proto(efi_table_attr(efi_system_table(), con_out),
 307                       output_string, str);
 308}
 309
 310/*
 311 * The LINUX_EFI_INITRD_MEDIA_GUID vendor media device path below provides a way
 312 * for the firmware or bootloader to expose the initrd data directly to the stub
 313 * via the trivial LoadFile2 protocol, which is defined in the UEFI spec, and is
 314 * very easy to implement. It is a simple Linux initrd specific conduit between
 315 * kernel and firmware, allowing us to put the EFI stub (being part of the
 316 * kernel) in charge of where and when to load the initrd, while leaving it up
 317 * to the firmware to decide whether it needs to expose its filesystem hierarchy
 318 * via EFI protocols.
 319 */
 320static const struct {
 321        struct efi_vendor_dev_path      vendor;
 322        struct efi_generic_dev_path     end;
 323} __packed initrd_dev_path = {
 324        {
 325                {
 326                        EFI_DEV_MEDIA,
 327                        EFI_DEV_MEDIA_VENDOR,
 328                        sizeof(struct efi_vendor_dev_path),
 329                },
 330                LINUX_EFI_INITRD_MEDIA_GUID
 331        }, {
 332                EFI_DEV_END_PATH,
 333                EFI_DEV_END_ENTIRE,
 334                sizeof(struct efi_generic_dev_path)
 335        }
 336};
 337
 338/**
 339 * efi_load_initrd_dev_path - load the initrd from the Linux initrd device path
 340 * @load_addr:  pointer to store the address where the initrd was loaded
 341 * @load_size:  pointer to store the size of the loaded initrd
 342 * @max:        upper limit for the initrd memory allocation
 343 * @return:     %EFI_SUCCESS if the initrd was loaded successfully, in which
 344 *              case @load_addr and @load_size are assigned accordingly
 345 *              %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd
 346 *              device path
 347 *              %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL
 348 *              %EFI_OUT_OF_RESOURCES if memory allocation failed
 349 *              %EFI_LOAD_ERROR in all other cases
 350 */
 351efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
 352                                      unsigned long *load_size,
 353                                      unsigned long max)
 354{
 355        efi_guid_t lf2_proto_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
 356        efi_device_path_protocol_t *dp;
 357        efi_load_file2_protocol_t *lf2;
 358        unsigned long initrd_addr;
 359        unsigned long initrd_size;
 360        efi_handle_t handle;
 361        efi_status_t status;
 362
 363        if (!load_addr || !load_size)
 364                return EFI_INVALID_PARAMETER;
 365
 366        dp = (efi_device_path_protocol_t *)&initrd_dev_path;
 367        status = efi_bs_call(locate_device_path, &lf2_proto_guid, &dp, &handle);
 368        if (status != EFI_SUCCESS)
 369                return status;
 370
 371        status = efi_bs_call(handle_protocol, handle, &lf2_proto_guid,
 372                             (void **)&lf2);
 373        if (status != EFI_SUCCESS)
 374                return status;
 375
 376        status = efi_call_proto(lf2, load_file, dp, false, &initrd_size, NULL);
 377        if (status != EFI_BUFFER_TOO_SMALL)
 378                return EFI_LOAD_ERROR;
 379
 380        status = efi_allocate_pages(initrd_size, &initrd_addr, max);
 381        if (status != EFI_SUCCESS)
 382                return status;
 383
 384        status = efi_call_proto(lf2, load_file, dp, false, &initrd_size,
 385                                (void *)initrd_addr);
 386        if (status != EFI_SUCCESS) {
 387                efi_free(initrd_size, initrd_addr);
 388                return EFI_LOAD_ERROR;
 389        }
 390
 391        *load_addr = initrd_addr;
 392        *load_size = initrd_size;
 393        return EFI_SUCCESS;
 394}
 395