linux/drivers/firmware/efi/capsule-loader.c
<<
>>
Prefs
   1/*
   2 * EFI capsule loader driver.
   3 *
   4 * Copyright 2015 Intel Corporation
   5 *
   6 * This file is part of the Linux kernel, and is made available under
   7 * the terms of the GNU General Public License version 2.
   8 */
   9
  10#define pr_fmt(fmt) "efi: " fmt
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/miscdevice.h>
  15#include <linux/highmem.h>
  16#include <linux/slab.h>
  17#include <linux/mutex.h>
  18#include <linux/efi.h>
  19#include <linux/vmalloc.h>
  20
  21#define NO_FURTHER_WRITE_ACTION -1
  22
  23struct capsule_info {
  24        bool            header_obtained;
  25        int             reset_type;
  26        long            index;
  27        size_t          count;
  28        size_t          total_size;
  29        struct page     **pages;
  30        size_t          page_bytes_remain;
  31};
  32
  33/**
  34 * efi_free_all_buff_pages - free all previous allocated buffer pages
  35 * @cap_info: pointer to current instance of capsule_info structure
  36 *
  37 *      In addition to freeing buffer pages, it flags NO_FURTHER_WRITE_ACTION
  38 *      to cease processing data in subsequent write(2) calls until close(2)
  39 *      is called.
  40 **/
  41static void efi_free_all_buff_pages(struct capsule_info *cap_info)
  42{
  43        while (cap_info->index > 0)
  44                __free_page(cap_info->pages[--cap_info->index]);
  45
  46        cap_info->index = NO_FURTHER_WRITE_ACTION;
  47}
  48
  49/**
  50 * efi_capsule_setup_info - obtain the efi capsule header in the binary and
  51 *                          setup capsule_info structure
  52 * @cap_info: pointer to current instance of capsule_info structure
  53 * @kbuff: a mapped first page buffer pointer
  54 * @hdr_bytes: the total received number of bytes for efi header
  55 **/
  56static ssize_t efi_capsule_setup_info(struct capsule_info *cap_info,
  57                                      void *kbuff, size_t hdr_bytes)
  58{
  59        efi_capsule_header_t *cap_hdr;
  60        size_t pages_needed;
  61        int ret;
  62        void *temp_page;
  63
  64        /* Only process data block that is larger than efi header size */
  65        if (hdr_bytes < sizeof(efi_capsule_header_t))
  66                return 0;
  67
  68        /* Reset back to the correct offset of header */
  69        cap_hdr = kbuff - cap_info->count;
  70        pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT;
  71
  72        if (pages_needed == 0) {
  73                pr_err("%s: pages count invalid\n", __func__);
  74                return -EINVAL;
  75        }
  76
  77        /* Check if the capsule binary supported */
  78        ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags,
  79                                    cap_hdr->imagesize,
  80                                    &cap_info->reset_type);
  81        if (ret) {
  82                pr_err("%s: efi_capsule_supported() failed\n",
  83                       __func__);
  84                return ret;
  85        }
  86
  87        cap_info->total_size = cap_hdr->imagesize;
  88        temp_page = krealloc(cap_info->pages,
  89                             pages_needed * sizeof(void *),
  90                             GFP_KERNEL | __GFP_ZERO);
  91        if (!temp_page) {
  92                pr_debug("%s: krealloc() failed\n", __func__);
  93                return -ENOMEM;
  94        }
  95
  96        cap_info->pages = temp_page;
  97        cap_info->header_obtained = true;
  98
  99        return 0;
 100}
 101
 102/**
 103 * efi_capsule_submit_update - invoke the efi_capsule_update API once binary
 104 *                             upload done
 105 * @cap_info: pointer to current instance of capsule_info structure
 106 **/
 107static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
 108{
 109        int ret;
 110        void *cap_hdr_temp;
 111
 112        cap_hdr_temp = vmap(cap_info->pages, cap_info->index,
 113                        VM_MAP, PAGE_KERNEL);
 114        if (!cap_hdr_temp) {
 115                pr_debug("%s: vmap() failed\n", __func__);
 116                return -EFAULT;
 117        }
 118
 119        ret = efi_capsule_update(cap_hdr_temp, cap_info->pages);
 120        vunmap(cap_hdr_temp);
 121        if (ret) {
 122                pr_err("%s: efi_capsule_update() failed\n", __func__);
 123                return ret;
 124        }
 125
 126        /* Indicate capsule binary uploading is done */
 127        cap_info->index = NO_FURTHER_WRITE_ACTION;
 128        pr_info("%s: Successfully upload capsule file with reboot type '%s'\n",
 129                __func__, !cap_info->reset_type ? "RESET_COLD" :
 130                cap_info->reset_type == 1 ? "RESET_WARM" :
 131                "RESET_SHUTDOWN");
 132        return 0;
 133}
 134
 135/**
 136 * efi_capsule_write - store the capsule binary and pass it to
 137 *                     efi_capsule_update() API
 138 * @file: file pointer
 139 * @buff: buffer pointer
 140 * @count: number of bytes in @buff
 141 * @offp: not used
 142 *
 143 *      Expectation:
 144 *      - A user space tool should start at the beginning of capsule binary and
 145 *        pass data in sequentially.
 146 *      - Users should close and re-open this file note in order to upload more
 147 *        capsules.
 148 *      - After an error returned, user should close the file and restart the
 149 *        operation for the next try otherwise -EIO will be returned until the
 150 *        file is closed.
 151 *      - An EFI capsule header must be located at the beginning of capsule
 152 *        binary file and passed in as first block data of write operation.
 153 **/
 154static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
 155                                 size_t count, loff_t *offp)
 156{
 157        int ret = 0;
 158        struct capsule_info *cap_info = file->private_data;
 159        struct page *page;
 160        void *kbuff = NULL;
 161        size_t write_byte;
 162
 163        if (count == 0)
 164                return 0;
 165
 166        /* Return error while NO_FURTHER_WRITE_ACTION is flagged */
 167        if (cap_info->index < 0)
 168                return -EIO;
 169
 170        /* Only alloc a new page when previous page is full */
 171        if (!cap_info->page_bytes_remain) {
 172                page = alloc_page(GFP_KERNEL);
 173                if (!page) {
 174                        pr_debug("%s: alloc_page() failed\n", __func__);
 175                        ret = -ENOMEM;
 176                        goto failed;
 177                }
 178
 179                cap_info->pages[cap_info->index++] = page;
 180                cap_info->page_bytes_remain = PAGE_SIZE;
 181        }
 182
 183        page = cap_info->pages[cap_info->index - 1];
 184
 185        kbuff = kmap(page);
 186        if (!kbuff) {
 187                pr_debug("%s: kmap() failed\n", __func__);
 188                ret = -EFAULT;
 189                goto failed;
 190        }
 191        kbuff += PAGE_SIZE - cap_info->page_bytes_remain;
 192
 193        /* Copy capsule binary data from user space to kernel space buffer */
 194        write_byte = min_t(size_t, count, cap_info->page_bytes_remain);
 195        if (copy_from_user(kbuff, buff, write_byte)) {
 196                pr_debug("%s: copy_from_user() failed\n", __func__);
 197                ret = -EFAULT;
 198                goto fail_unmap;
 199        }
 200        cap_info->page_bytes_remain -= write_byte;
 201
 202        /* Setup capsule binary info structure */
 203        if (!cap_info->header_obtained) {
 204                ret = efi_capsule_setup_info(cap_info, kbuff,
 205                                             cap_info->count + write_byte);
 206                if (ret)
 207                        goto fail_unmap;
 208        }
 209
 210        cap_info->count += write_byte;
 211        kunmap(page);
 212
 213        /* Submit the full binary to efi_capsule_update() API */
 214        if (cap_info->header_obtained &&
 215            cap_info->count >= cap_info->total_size) {
 216                if (cap_info->count > cap_info->total_size) {
 217                        pr_err("%s: upload size exceeded header defined size\n",
 218                               __func__);
 219                        ret = -EINVAL;
 220                        goto failed;
 221                }
 222
 223                ret = efi_capsule_submit_update(cap_info);
 224                if (ret)
 225                        goto failed;
 226        }
 227
 228        return write_byte;
 229
 230fail_unmap:
 231        kunmap(page);
 232failed:
 233        efi_free_all_buff_pages(cap_info);
 234        return ret;
 235}
 236
 237/**
 238 * efi_capsule_flush - called by file close or file flush
 239 * @file: file pointer
 240 * @id: not used
 241 *
 242 *      If a capsule is being partially uploaded then calling this function
 243 *      will be treated as upload termination and will free those completed
 244 *      buffer pages and -ECANCELED will be returned.
 245 **/
 246static int efi_capsule_flush(struct file *file, fl_owner_t id)
 247{
 248        int ret = 0;
 249        struct capsule_info *cap_info = file->private_data;
 250
 251        if (cap_info->index > 0) {
 252                pr_err("%s: capsule upload not complete\n", __func__);
 253                efi_free_all_buff_pages(cap_info);
 254                ret = -ECANCELED;
 255        }
 256
 257        return ret;
 258}
 259
 260/**
 261 * efi_capsule_release - called by file close
 262 * @inode: not used
 263 * @file: file pointer
 264 *
 265 *      We will not free successfully submitted pages since efi update
 266 *      requires data to be maintained across system reboot.
 267 **/
 268static int efi_capsule_release(struct inode *inode, struct file *file)
 269{
 270        struct capsule_info *cap_info = file->private_data;
 271
 272        kfree(cap_info->pages);
 273        kfree(file->private_data);
 274        file->private_data = NULL;
 275        return 0;
 276}
 277
 278/**
 279 * efi_capsule_open - called by file open
 280 * @inode: not used
 281 * @file: file pointer
 282 *
 283 *      Will allocate each capsule_info memory for each file open call.
 284 *      This provided the capability to support multiple file open feature
 285 *      where user is not needed to wait for others to finish in order to
 286 *      upload their capsule binary.
 287 **/
 288static int efi_capsule_open(struct inode *inode, struct file *file)
 289{
 290        struct capsule_info *cap_info;
 291
 292        cap_info = kzalloc(sizeof(*cap_info), GFP_KERNEL);
 293        if (!cap_info)
 294                return -ENOMEM;
 295
 296        cap_info->pages = kzalloc(sizeof(void *), GFP_KERNEL);
 297        if (!cap_info->pages) {
 298                kfree(cap_info);
 299                return -ENOMEM;
 300        }
 301
 302        file->private_data = cap_info;
 303
 304        return 0;
 305}
 306
 307static const struct file_operations efi_capsule_fops = {
 308        .owner = THIS_MODULE,
 309        .open = efi_capsule_open,
 310        .write = efi_capsule_write,
 311        .flush = efi_capsule_flush,
 312        .release = efi_capsule_release,
 313        .llseek = no_llseek,
 314};
 315
 316static struct miscdevice efi_capsule_misc = {
 317        .minor = MISC_DYNAMIC_MINOR,
 318        .name = "efi_capsule_loader",
 319        .fops = &efi_capsule_fops,
 320};
 321
 322static int __init efi_capsule_loader_init(void)
 323{
 324        int ret;
 325
 326        if (!efi_enabled(EFI_RUNTIME_SERVICES))
 327                return -ENODEV;
 328
 329        ret = misc_register(&efi_capsule_misc);
 330        if (ret)
 331                pr_err("%s: Failed to register misc char file note\n",
 332                       __func__);
 333
 334        return ret;
 335}
 336module_init(efi_capsule_loader_init);
 337
 338static void __exit efi_capsule_loader_exit(void)
 339{
 340        misc_deregister(&efi_capsule_misc);
 341}
 342module_exit(efi_capsule_loader_exit);
 343
 344MODULE_DESCRIPTION("EFI capsule firmware binary loader");
 345MODULE_LICENSE("GPL v2");
 346