18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * EFI capsule support. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2013 Intel Corporation; author Matt Fleming 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "efi: " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci#include <linux/mutex.h> 128c2ecf20Sopenharmony_ci#include <linux/highmem.h> 138c2ecf20Sopenharmony_ci#include <linux/efi.h> 148c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 158c2ecf20Sopenharmony_ci#include <asm/io.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_citypedef struct { 188c2ecf20Sopenharmony_ci u64 length; 198c2ecf20Sopenharmony_ci u64 data; 208c2ecf20Sopenharmony_ci} efi_capsule_block_desc_t; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic bool capsule_pending; 238c2ecf20Sopenharmony_cistatic bool stop_capsules; 248c2ecf20Sopenharmony_cistatic int efi_reset_type = -1; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * capsule_mutex serialises access to both capsule_pending and 288c2ecf20Sopenharmony_ci * efi_reset_type and stop_capsules. 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(capsule_mutex); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/** 338c2ecf20Sopenharmony_ci * efi_capsule_pending - has a capsule been passed to the firmware? 348c2ecf20Sopenharmony_ci * @reset_type: store the type of EFI reset if capsule is pending 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * To ensure that the registered capsule is processed correctly by the 378c2ecf20Sopenharmony_ci * firmware we need to perform a specific type of reset. If a capsule is 388c2ecf20Sopenharmony_ci * pending return the reset type in @reset_type. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * This function will race with callers of efi_capsule_update(), for 418c2ecf20Sopenharmony_ci * example, calling this function while somebody else is in 428c2ecf20Sopenharmony_ci * efi_capsule_update() but hasn't reached efi_capsue_update_locked() 438c2ecf20Sopenharmony_ci * will miss the updates to capsule_pending and efi_reset_type after 448c2ecf20Sopenharmony_ci * efi_capsule_update_locked() completes. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * A non-racy use is from platform reboot code because we use 478c2ecf20Sopenharmony_ci * system_state to ensure no capsules can be sent to the firmware once 488c2ecf20Sopenharmony_ci * we're at SYSTEM_RESTART. See efi_capsule_update_locked(). 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_cibool efi_capsule_pending(int *reset_type) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci if (!capsule_pending) 538c2ecf20Sopenharmony_ci return false; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (reset_type) 568c2ecf20Sopenharmony_ci *reset_type = efi_reset_type; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return true; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* 628c2ecf20Sopenharmony_ci * Whitelist of EFI capsule flags that we support. 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * We do not handle EFI_CAPSULE_INITIATE_RESET because that would 658c2ecf20Sopenharmony_ci * require us to prepare the kernel for reboot. Refuse to load any 668c2ecf20Sopenharmony_ci * capsules with that flag and any other flags that we do not know how 678c2ecf20Sopenharmony_ci * to handle. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_ci#define EFI_CAPSULE_SUPPORTED_FLAG_MASK \ 708c2ecf20Sopenharmony_ci (EFI_CAPSULE_PERSIST_ACROSS_RESET | EFI_CAPSULE_POPULATE_SYSTEM_TABLE) 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/** 738c2ecf20Sopenharmony_ci * efi_capsule_supported - does the firmware support the capsule? 748c2ecf20Sopenharmony_ci * @guid: vendor guid of capsule 758c2ecf20Sopenharmony_ci * @flags: capsule flags 768c2ecf20Sopenharmony_ci * @size: size of capsule data 778c2ecf20Sopenharmony_ci * @reset: the reset type required for this capsule 788c2ecf20Sopenharmony_ci * 798c2ecf20Sopenharmony_ci * Check whether a capsule with @flags is supported by the firmware 808c2ecf20Sopenharmony_ci * and that @size doesn't exceed the maximum size for a capsule. 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * No attempt is made to check @reset against the reset type required 838c2ecf20Sopenharmony_ci * by any pending capsules because of the races involved. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ciint efi_capsule_supported(efi_guid_t guid, u32 flags, size_t size, int *reset) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci efi_capsule_header_t capsule; 888c2ecf20Sopenharmony_ci efi_capsule_header_t *cap_list[] = { &capsule }; 898c2ecf20Sopenharmony_ci efi_status_t status; 908c2ecf20Sopenharmony_ci u64 max_size; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (flags & ~EFI_CAPSULE_SUPPORTED_FLAG_MASK) 938c2ecf20Sopenharmony_ci return -EINVAL; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci capsule.headersize = capsule.imagesize = sizeof(capsule); 968c2ecf20Sopenharmony_ci memcpy(&capsule.guid, &guid, sizeof(efi_guid_t)); 978c2ecf20Sopenharmony_ci capsule.flags = flags; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci status = efi.query_capsule_caps(cap_list, 1, &max_size, reset); 1008c2ecf20Sopenharmony_ci if (status != EFI_SUCCESS) 1018c2ecf20Sopenharmony_ci return efi_status_to_err(status); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (size > max_size) 1048c2ecf20Sopenharmony_ci return -ENOSPC; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(efi_capsule_supported); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci/* 1118c2ecf20Sopenharmony_ci * Every scatter gather list (block descriptor) page must end with a 1128c2ecf20Sopenharmony_ci * continuation pointer. The last continuation pointer of the last 1138c2ecf20Sopenharmony_ci * page must be zero to mark the end of the chain. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci#define SGLIST_PER_PAGE ((PAGE_SIZE / sizeof(efi_capsule_block_desc_t)) - 1) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* 1188c2ecf20Sopenharmony_ci * How many scatter gather list (block descriptor) pages do we need 1198c2ecf20Sopenharmony_ci * to map @count pages? 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_cistatic inline unsigned int sg_pages_num(unsigned int count) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci return DIV_ROUND_UP(count, SGLIST_PER_PAGE); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/** 1278c2ecf20Sopenharmony_ci * efi_capsule_update_locked - pass a single capsule to the firmware 1288c2ecf20Sopenharmony_ci * @capsule: capsule to send to the firmware 1298c2ecf20Sopenharmony_ci * @sg_pages: array of scatter gather (block descriptor) pages 1308c2ecf20Sopenharmony_ci * @reset: the reset type required for @capsule 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * Since this function must be called under capsule_mutex check 1338c2ecf20Sopenharmony_ci * whether efi_reset_type will conflict with @reset, and atomically 1348c2ecf20Sopenharmony_ci * set it and capsule_pending if a capsule was successfully sent to 1358c2ecf20Sopenharmony_ci * the firmware. 1368c2ecf20Sopenharmony_ci * 1378c2ecf20Sopenharmony_ci * We also check to see if the system is about to restart, and if so, 1388c2ecf20Sopenharmony_ci * abort. This avoids races between efi_capsule_update() and 1398c2ecf20Sopenharmony_ci * efi_capsule_pending(). 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_cistatic int 1428c2ecf20Sopenharmony_ciefi_capsule_update_locked(efi_capsule_header_t *capsule, 1438c2ecf20Sopenharmony_ci struct page **sg_pages, int reset) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci efi_physical_addr_t sglist_phys; 1468c2ecf20Sopenharmony_ci efi_status_t status; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci lockdep_assert_held(&capsule_mutex); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* 1518c2ecf20Sopenharmony_ci * If someone has already registered a capsule that requires a 1528c2ecf20Sopenharmony_ci * different reset type, we're out of luck and must abort. 1538c2ecf20Sopenharmony_ci */ 1548c2ecf20Sopenharmony_ci if (efi_reset_type >= 0 && efi_reset_type != reset) { 1558c2ecf20Sopenharmony_ci pr_err("Conflicting capsule reset type %d (%d).\n", 1568c2ecf20Sopenharmony_ci reset, efi_reset_type); 1578c2ecf20Sopenharmony_ci return -EINVAL; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* 1618c2ecf20Sopenharmony_ci * If the system is getting ready to restart it may have 1628c2ecf20Sopenharmony_ci * called efi_capsule_pending() to make decisions (such as 1638c2ecf20Sopenharmony_ci * whether to force an EFI reboot), and we're racing against 1648c2ecf20Sopenharmony_ci * that call. Abort in that case. 1658c2ecf20Sopenharmony_ci */ 1668c2ecf20Sopenharmony_ci if (unlikely(stop_capsules)) { 1678c2ecf20Sopenharmony_ci pr_warn("Capsule update raced with reboot, aborting.\n"); 1688c2ecf20Sopenharmony_ci return -EINVAL; 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci sglist_phys = page_to_phys(sg_pages[0]); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci status = efi.update_capsule(&capsule, 1, sglist_phys); 1748c2ecf20Sopenharmony_ci if (status == EFI_SUCCESS) { 1758c2ecf20Sopenharmony_ci capsule_pending = true; 1768c2ecf20Sopenharmony_ci efi_reset_type = reset; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return efi_status_to_err(status); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci/** 1838c2ecf20Sopenharmony_ci * efi_capsule_update - send a capsule to the firmware 1848c2ecf20Sopenharmony_ci * @capsule: capsule to send to firmware 1858c2ecf20Sopenharmony_ci * @pages: an array of capsule data pages 1868c2ecf20Sopenharmony_ci * 1878c2ecf20Sopenharmony_ci * Build a scatter gather list with EFI capsule block descriptors to 1888c2ecf20Sopenharmony_ci * map the capsule described by @capsule with its data in @pages and 1898c2ecf20Sopenharmony_ci * send it to the firmware via the UpdateCapsule() runtime service. 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * @capsule must be a virtual mapping of the complete capsule update in the 1928c2ecf20Sopenharmony_ci * kernel address space, as the capsule can be consumed immediately. 1938c2ecf20Sopenharmony_ci * A capsule_header_t that describes the entire contents of the capsule 1948c2ecf20Sopenharmony_ci * must be at the start of the first data page. 1958c2ecf20Sopenharmony_ci * 1968c2ecf20Sopenharmony_ci * Even though this function will validate that the firmware supports 1978c2ecf20Sopenharmony_ci * the capsule guid, users will likely want to check that 1988c2ecf20Sopenharmony_ci * efi_capsule_supported() returns true before calling this function 1998c2ecf20Sopenharmony_ci * because it makes it easier to print helpful error messages. 2008c2ecf20Sopenharmony_ci * 2018c2ecf20Sopenharmony_ci * If the capsule is successfully submitted to the firmware, any 2028c2ecf20Sopenharmony_ci * subsequent calls to efi_capsule_pending() will return true. @pages 2038c2ecf20Sopenharmony_ci * must not be released or modified if this function returns 2048c2ecf20Sopenharmony_ci * successfully. 2058c2ecf20Sopenharmony_ci * 2068c2ecf20Sopenharmony_ci * Callers must be prepared for this function to fail, which can 2078c2ecf20Sopenharmony_ci * happen if we raced with system reboot or if there is already a 2088c2ecf20Sopenharmony_ci * pending capsule that has a reset type that conflicts with the one 2098c2ecf20Sopenharmony_ci * required by @capsule. Do NOT use efi_capsule_pending() to detect 2108c2ecf20Sopenharmony_ci * this conflict since that would be racy. Instead, submit the capsule 2118c2ecf20Sopenharmony_ci * to efi_capsule_update() and check the return value. 2128c2ecf20Sopenharmony_ci * 2138c2ecf20Sopenharmony_ci * Return 0 on success, a converted EFI status code on failure. 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_ciint efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci u32 imagesize = capsule->imagesize; 2188c2ecf20Sopenharmony_ci efi_guid_t guid = capsule->guid; 2198c2ecf20Sopenharmony_ci unsigned int count, sg_count; 2208c2ecf20Sopenharmony_ci u32 flags = capsule->flags; 2218c2ecf20Sopenharmony_ci struct page **sg_pages; 2228c2ecf20Sopenharmony_ci int rv, reset_type; 2238c2ecf20Sopenharmony_ci int i, j; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci rv = efi_capsule_supported(guid, flags, imagesize, &reset_type); 2268c2ecf20Sopenharmony_ci if (rv) 2278c2ecf20Sopenharmony_ci return rv; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci count = DIV_ROUND_UP(imagesize, PAGE_SIZE); 2308c2ecf20Sopenharmony_ci sg_count = sg_pages_num(count); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci sg_pages = kcalloc(sg_count, sizeof(*sg_pages), GFP_KERNEL); 2338c2ecf20Sopenharmony_ci if (!sg_pages) 2348c2ecf20Sopenharmony_ci return -ENOMEM; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci for (i = 0; i < sg_count; i++) { 2378c2ecf20Sopenharmony_ci sg_pages[i] = alloc_page(GFP_KERNEL); 2388c2ecf20Sopenharmony_ci if (!sg_pages[i]) { 2398c2ecf20Sopenharmony_ci rv = -ENOMEM; 2408c2ecf20Sopenharmony_ci goto out; 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci for (i = 0; i < sg_count; i++) { 2458c2ecf20Sopenharmony_ci efi_capsule_block_desc_t *sglist; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci sglist = kmap(sg_pages[i]); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) { 2508c2ecf20Sopenharmony_ci u64 sz = min_t(u64, imagesize, 2518c2ecf20Sopenharmony_ci PAGE_SIZE - (u64)*pages % PAGE_SIZE); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci sglist[j].length = sz; 2548c2ecf20Sopenharmony_ci sglist[j].data = *pages++; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci imagesize -= sz; 2578c2ecf20Sopenharmony_ci count--; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* Continuation pointer */ 2618c2ecf20Sopenharmony_ci sglist[j].length = 0; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (i + 1 == sg_count) 2648c2ecf20Sopenharmony_ci sglist[j].data = 0; 2658c2ecf20Sopenharmony_ci else 2668c2ecf20Sopenharmony_ci sglist[j].data = page_to_phys(sg_pages[i + 1]); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci kunmap(sg_pages[i]); 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci mutex_lock(&capsule_mutex); 2728c2ecf20Sopenharmony_ci rv = efi_capsule_update_locked(capsule, sg_pages, reset_type); 2738c2ecf20Sopenharmony_ci mutex_unlock(&capsule_mutex); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ciout: 2768c2ecf20Sopenharmony_ci for (i = 0; rv && i < sg_count; i++) { 2778c2ecf20Sopenharmony_ci if (sg_pages[i]) 2788c2ecf20Sopenharmony_ci __free_page(sg_pages[i]); 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci kfree(sg_pages); 2828c2ecf20Sopenharmony_ci return rv; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(efi_capsule_update); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic int capsule_reboot_notify(struct notifier_block *nb, unsigned long event, void *cmd) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci mutex_lock(&capsule_mutex); 2898c2ecf20Sopenharmony_ci stop_capsules = true; 2908c2ecf20Sopenharmony_ci mutex_unlock(&capsule_mutex); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci return NOTIFY_DONE; 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic struct notifier_block capsule_reboot_nb = { 2968c2ecf20Sopenharmony_ci .notifier_call = capsule_reboot_notify, 2978c2ecf20Sopenharmony_ci}; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic int __init capsule_reboot_register(void) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci return register_reboot_notifier(&capsule_reboot_nb); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_cicore_initcall(capsule_reboot_register); 304