Path: blob/master/drivers/firmware/efi/capsule-loader.c
26444 views
// SPDX-License-Identifier: GPL-2.01/*2* EFI capsule loader driver.3*4* Copyright 2015 Intel Corporation5*/67#define pr_fmt(fmt) "efi: " fmt89#include <linux/kernel.h>10#include <linux/module.h>11#include <linux/miscdevice.h>12#include <linux/highmem.h>13#include <linux/io.h>14#include <linux/slab.h>15#include <linux/mutex.h>16#include <linux/efi.h>17#include <linux/vmalloc.h>1819#define NO_FURTHER_WRITE_ACTION -12021/**22* efi_free_all_buff_pages - free all previous allocated buffer pages23* @cap_info: pointer to current instance of capsule_info structure24*25* In addition to freeing buffer pages, it flags NO_FURTHER_WRITE_ACTION26* to cease processing data in subsequent write(2) calls until close(2)27* is called.28**/29static void efi_free_all_buff_pages(struct capsule_info *cap_info)30{31while (cap_info->index > 0)32__free_page(cap_info->pages[--cap_info->index]);3334cap_info->index = NO_FURTHER_WRITE_ACTION;35}3637int __efi_capsule_setup_info(struct capsule_info *cap_info)38{39size_t pages_needed;40int ret;41void *temp_page;4243pages_needed = ALIGN(cap_info->total_size, PAGE_SIZE) / PAGE_SIZE;4445if (pages_needed == 0) {46pr_err("invalid capsule size\n");47return -EINVAL;48}4950/* Check if the capsule binary supported */51ret = efi_capsule_supported(cap_info->header.guid,52cap_info->header.flags,53cap_info->header.imagesize,54&cap_info->reset_type);55if (ret) {56pr_err("capsule not supported\n");57return ret;58}5960temp_page = krealloc(cap_info->pages,61pages_needed * sizeof(void *),62GFP_KERNEL | __GFP_ZERO);63if (!temp_page)64return -ENOMEM;6566cap_info->pages = temp_page;6768temp_page = krealloc(cap_info->phys,69pages_needed * sizeof(phys_addr_t *),70GFP_KERNEL | __GFP_ZERO);71if (!temp_page)72return -ENOMEM;7374cap_info->phys = temp_page;7576return 0;77}7879/**80* efi_capsule_setup_info - obtain the efi capsule header in the binary and81* setup capsule_info structure82* @cap_info: pointer to current instance of capsule_info structure83* @kbuff: a mapped first page buffer pointer84* @hdr_bytes: the total received number of bytes for efi header85*86* Platforms with non-standard capsule update mechanisms can override87* this __weak function so they can perform any required capsule88* image munging. See quark_quirk_function() for an example.89**/90int __weak efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff,91size_t hdr_bytes)92{93/* Only process data block that is larger than efi header size */94if (hdr_bytes < sizeof(efi_capsule_header_t))95return 0;9697memcpy(&cap_info->header, kbuff, sizeof(cap_info->header));98cap_info->total_size = cap_info->header.imagesize;99100return __efi_capsule_setup_info(cap_info);101}102103/**104* efi_capsule_submit_update - invoke the efi_capsule_update API once binary105* upload done106* @cap_info: pointer to current instance of capsule_info structure107**/108static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)109{110bool do_vunmap = false;111int ret;112113/*114* cap_info->capsule may have been assigned already by a quirk115* handler, so only overwrite it if it is NULL116*/117if (!cap_info->capsule) {118cap_info->capsule = vmap(cap_info->pages, cap_info->index,119VM_MAP, PAGE_KERNEL);120if (!cap_info->capsule)121return -ENOMEM;122do_vunmap = true;123}124125ret = efi_capsule_update(cap_info->capsule, cap_info->phys);126if (do_vunmap)127vunmap(cap_info->capsule);128if (ret) {129pr_err("capsule update failed\n");130return ret;131}132133/* Indicate capsule binary uploading is done */134cap_info->index = NO_FURTHER_WRITE_ACTION;135136if (cap_info->header.flags & EFI_CAPSULE_PERSIST_ACROSS_RESET) {137pr_info("Successfully uploaded capsule file with reboot type '%s'\n",138!cap_info->reset_type ? "RESET_COLD" :139cap_info->reset_type == 1 ? "RESET_WARM" :140"RESET_SHUTDOWN");141} else {142pr_info("Successfully processed capsule file\n");143}144145return 0;146}147148/**149* efi_capsule_write - store the capsule binary and pass it to150* efi_capsule_update() API151* @file: file pointer152* @buff: buffer pointer153* @count: number of bytes in @buff154* @offp: not used155*156* Expectation:157* - A user space tool should start at the beginning of capsule binary and158* pass data in sequentially.159* - Users should close and re-open this file note in order to upload more160* capsules.161* - After an error returned, user should close the file and restart the162* operation for the next try otherwise -EIO will be returned until the163* file is closed.164* - An EFI capsule header must be located at the beginning of capsule165* binary file and passed in as first block data of write operation.166**/167static ssize_t efi_capsule_write(struct file *file, const char __user *buff,168size_t count, loff_t *offp)169{170int ret;171struct capsule_info *cap_info = file->private_data;172struct page *page;173void *kbuff = NULL;174size_t write_byte;175176if (count == 0)177return 0;178179/* Return error while NO_FURTHER_WRITE_ACTION is flagged */180if (cap_info->index < 0)181return -EIO;182183/* Only alloc a new page when previous page is full */184if (!cap_info->page_bytes_remain) {185page = alloc_page(GFP_KERNEL);186if (!page) {187ret = -ENOMEM;188goto failed;189}190191cap_info->pages[cap_info->index] = page;192cap_info->phys[cap_info->index] = page_to_phys(page);193cap_info->page_bytes_remain = PAGE_SIZE;194cap_info->index++;195} else {196page = cap_info->pages[cap_info->index - 1];197}198199kbuff = kmap(page);200kbuff += PAGE_SIZE - cap_info->page_bytes_remain;201202/* Copy capsule binary data from user space to kernel space buffer */203write_byte = min_t(size_t, count, cap_info->page_bytes_remain);204if (copy_from_user(kbuff, buff, write_byte)) {205ret = -EFAULT;206goto fail_unmap;207}208cap_info->page_bytes_remain -= write_byte;209210/* Setup capsule binary info structure */211if (cap_info->header.headersize == 0) {212ret = efi_capsule_setup_info(cap_info, kbuff - cap_info->count,213cap_info->count + write_byte);214if (ret)215goto fail_unmap;216}217218cap_info->count += write_byte;219kunmap(page);220221/* Submit the full binary to efi_capsule_update() API */222if (cap_info->header.headersize > 0 &&223cap_info->count >= cap_info->total_size) {224if (cap_info->count > cap_info->total_size) {225pr_err("capsule upload size exceeded header defined size\n");226ret = -EINVAL;227goto failed;228}229230ret = efi_capsule_submit_update(cap_info);231if (ret)232goto failed;233}234235return write_byte;236237fail_unmap:238kunmap(page);239failed:240efi_free_all_buff_pages(cap_info);241return ret;242}243244/**245* efi_capsule_release - called by file close246* @inode: not used247* @file: file pointer248*249* We will not free successfully submitted pages since efi update250* requires data to be maintained across system reboot.251**/252static int efi_capsule_release(struct inode *inode, struct file *file)253{254struct capsule_info *cap_info = file->private_data;255256if (cap_info->index > 0 &&257(cap_info->header.headersize == 0 ||258cap_info->count < cap_info->total_size)) {259pr_err("capsule upload not complete\n");260efi_free_all_buff_pages(cap_info);261}262263kfree(cap_info->pages);264kfree(cap_info->phys);265kfree(file->private_data);266file->private_data = NULL;267return 0;268}269270/**271* efi_capsule_open - called by file open272* @inode: not used273* @file: file pointer274*275* Will allocate each capsule_info memory for each file open call.276* This provided the capability to support multiple file open feature277* where user is not needed to wait for others to finish in order to278* upload their capsule binary.279**/280static int efi_capsule_open(struct inode *inode, struct file *file)281{282struct capsule_info *cap_info;283284cap_info = kzalloc(sizeof(*cap_info), GFP_KERNEL);285if (!cap_info)286return -ENOMEM;287288cap_info->pages = kzalloc(sizeof(void *), GFP_KERNEL);289if (!cap_info->pages) {290kfree(cap_info);291return -ENOMEM;292}293294cap_info->phys = kzalloc(sizeof(phys_addr_t), GFP_KERNEL);295if (!cap_info->phys) {296kfree(cap_info->pages);297kfree(cap_info);298return -ENOMEM;299}300301file->private_data = cap_info;302303return 0;304}305306static const struct file_operations efi_capsule_fops = {307.owner = THIS_MODULE,308.open = efi_capsule_open,309.write = efi_capsule_write,310.release = efi_capsule_release,311};312313static struct miscdevice efi_capsule_misc = {314.minor = MISC_DYNAMIC_MINOR,315.name = "efi_capsule_loader",316.fops = &efi_capsule_fops,317};318319static int __init efi_capsule_loader_init(void)320{321int ret;322323if (!efi_enabled(EFI_RUNTIME_SERVICES))324return -ENODEV;325326ret = misc_register(&efi_capsule_misc);327if (ret)328pr_err("Unable to register capsule loader device\n");329330return ret;331}332module_init(efi_capsule_loader_init);333334static void __exit efi_capsule_loader_exit(void)335{336misc_deregister(&efi_capsule_misc);337}338module_exit(efi_capsule_loader_exit);339340MODULE_DESCRIPTION("EFI capsule firmware binary loader");341MODULE_LICENSE("GPL v2");342343344