| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * EFI capsule loader driver. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * 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 | 6 | */ |
|---|
| 9 | 7 | |
|---|
| 10 | 8 | #define pr_fmt(fmt) "efi: " fmt |
|---|
| .. | .. |
|---|
| 13 | 11 | #include <linux/module.h> |
|---|
| 14 | 12 | #include <linux/miscdevice.h> |
|---|
| 15 | 13 | #include <linux/highmem.h> |
|---|
| 14 | +#include <linux/io.h> |
|---|
| 16 | 15 | #include <linux/slab.h> |
|---|
| 17 | 16 | #include <linux/mutex.h> |
|---|
| 18 | 17 | #include <linux/efi.h> |
|---|
| .. | .. |
|---|
| 169 | 168 | static ssize_t efi_capsule_write(struct file *file, const char __user *buff, |
|---|
| 170 | 169 | size_t count, loff_t *offp) |
|---|
| 171 | 170 | { |
|---|
| 172 | | - int ret = 0; |
|---|
| 171 | + int ret; |
|---|
| 173 | 172 | struct capsule_info *cap_info = file->private_data; |
|---|
| 174 | 173 | struct page *page; |
|---|
| 175 | 174 | void *kbuff = NULL; |
|---|
| .. | .. |
|---|
| 244 | 243 | } |
|---|
| 245 | 244 | |
|---|
| 246 | 245 | /** |
|---|
| 247 | | - * efi_capsule_flush - called by file close or file flush |
|---|
| 248 | | - * @file: file pointer |
|---|
| 249 | | - * @id: not used |
|---|
| 250 | | - * |
|---|
| 251 | | - * If a capsule is being partially uploaded then calling this function |
|---|
| 252 | | - * will be treated as upload termination and will free those completed |
|---|
| 253 | | - * buffer pages and -ECANCELED will be returned. |
|---|
| 254 | | - **/ |
|---|
| 255 | | -static int efi_capsule_flush(struct file *file, fl_owner_t id) |
|---|
| 256 | | -{ |
|---|
| 257 | | - int ret = 0; |
|---|
| 258 | | - struct capsule_info *cap_info = file->private_data; |
|---|
| 259 | | - |
|---|
| 260 | | - if (cap_info->index > 0) { |
|---|
| 261 | | - pr_err("capsule upload not complete\n"); |
|---|
| 262 | | - efi_free_all_buff_pages(cap_info); |
|---|
| 263 | | - ret = -ECANCELED; |
|---|
| 264 | | - } |
|---|
| 265 | | - |
|---|
| 266 | | - return ret; |
|---|
| 267 | | -} |
|---|
| 268 | | - |
|---|
| 269 | | -/** |
|---|
| 270 | 246 | * efi_capsule_release - called by file close |
|---|
| 271 | 247 | * @inode: not used |
|---|
| 272 | 248 | * @file: file pointer |
|---|
| .. | .. |
|---|
| 277 | 253 | static int efi_capsule_release(struct inode *inode, struct file *file) |
|---|
| 278 | 254 | { |
|---|
| 279 | 255 | struct capsule_info *cap_info = file->private_data; |
|---|
| 256 | + |
|---|
| 257 | + if (cap_info->index > 0 && |
|---|
| 258 | + (cap_info->header.headersize == 0 || |
|---|
| 259 | + cap_info->count < cap_info->total_size)) { |
|---|
| 260 | + pr_err("capsule upload not complete\n"); |
|---|
| 261 | + efi_free_all_buff_pages(cap_info); |
|---|
| 262 | + } |
|---|
| 280 | 263 | |
|---|
| 281 | 264 | kfree(cap_info->pages); |
|---|
| 282 | 265 | kfree(cap_info->phys); |
|---|
| .. | .. |
|---|
| 325 | 308 | .owner = THIS_MODULE, |
|---|
| 326 | 309 | .open = efi_capsule_open, |
|---|
| 327 | 310 | .write = efi_capsule_write, |
|---|
| 328 | | - .flush = efi_capsule_flush, |
|---|
| 329 | 311 | .release = efi_capsule_release, |
|---|
| 330 | 312 | .llseek = no_llseek, |
|---|
| 331 | 313 | }; |
|---|