|
@@ -8,6 +8,7 @@
|
|
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
|
+ * Copyright(c) 2018 Intel Corporation
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
@@ -30,6 +31,7 @@
|
|
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
|
+ * Copyright(c) 2018 Intel Corporation
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -163,7 +165,7 @@ static int iwl_alloc_fw_paging_mem(struct iwl_fw_runtime *fwrt,
|
|
|
static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
|
|
|
const struct fw_img *image)
|
|
|
{
|
|
|
- int sec_idx, idx;
|
|
|
+ int sec_idx, idx, ret;
|
|
|
u32 offset = 0;
|
|
|
|
|
|
/*
|
|
@@ -190,17 +192,23 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
|
|
|
*/
|
|
|
if (sec_idx >= image->num_sec - 1) {
|
|
|
IWL_ERR(fwrt, "Paging: Missing CSS and/or paging sections\n");
|
|
|
- iwl_free_fw_paging(fwrt);
|
|
|
- return -EINVAL;
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
}
|
|
|
|
|
|
/* copy the CSS block to the dram */
|
|
|
IWL_DEBUG_FW(fwrt, "Paging: load paging CSS to FW, sec = %d\n",
|
|
|
sec_idx);
|
|
|
|
|
|
+ if (image->sec[sec_idx].len > fwrt->fw_paging_db[0].fw_paging_size) {
|
|
|
+ IWL_ERR(fwrt, "CSS block is larger than paging size\n");
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
memcpy(page_address(fwrt->fw_paging_db[0].fw_paging_block),
|
|
|
image->sec[sec_idx].data,
|
|
|
- fwrt->fw_paging_db[0].fw_paging_size);
|
|
|
+ image->sec[sec_idx].len);
|
|
|
dma_sync_single_for_device(fwrt->trans->dev,
|
|
|
fwrt->fw_paging_db[0].fw_paging_phys,
|
|
|
fwrt->fw_paging_db[0].fw_paging_size,
|
|
@@ -221,6 +229,14 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
|
|
|
for (idx = 1; idx < fwrt->num_of_paging_blk; idx++) {
|
|
|
struct iwl_fw_paging *block = &fwrt->fw_paging_db[idx];
|
|
|
|
|
|
+ if (block->fw_paging_size > image->sec[sec_idx].len - offset) {
|
|
|
+ IWL_ERR(fwrt,
|
|
|
+ "Paging: paging size is larger than remaining data in block %d\n",
|
|
|
+ idx);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
memcpy(page_address(block->fw_paging_block),
|
|
|
image->sec[sec_idx].data + offset,
|
|
|
block->fw_paging_size);
|
|
@@ -231,19 +247,32 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
|
|
|
|
|
|
IWL_DEBUG_FW(fwrt,
|
|
|
"Paging: copied %d paging bytes to block %d\n",
|
|
|
- fwrt->fw_paging_db[idx].fw_paging_size,
|
|
|
- idx);
|
|
|
+ block->fw_paging_size, idx);
|
|
|
|
|
|
- offset += fwrt->fw_paging_db[idx].fw_paging_size;
|
|
|
+ offset += block->fw_paging_size;
|
|
|
+
|
|
|
+ if (offset > image->sec[sec_idx].len) {
|
|
|
+ IWL_ERR(fwrt,
|
|
|
+ "Paging: offset goes over section size\n");
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* copy the last paging block */
|
|
|
if (fwrt->num_of_pages_in_last_blk > 0) {
|
|
|
struct iwl_fw_paging *block = &fwrt->fw_paging_db[idx];
|
|
|
|
|
|
+ if (image->sec[sec_idx].len - offset > block->fw_paging_size) {
|
|
|
+ IWL_ERR(fwrt,
|
|
|
+ "Paging: last block is larger than paging size\n");
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
memcpy(page_address(block->fw_paging_block),
|
|
|
image->sec[sec_idx].data + offset,
|
|
|
- FW_PAGING_SIZE * fwrt->num_of_pages_in_last_blk);
|
|
|
+ image->sec[sec_idx].len - offset);
|
|
|
dma_sync_single_for_device(fwrt->trans->dev,
|
|
|
block->fw_paging_phys,
|
|
|
block->fw_paging_size,
|
|
@@ -255,6 +284,10 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
+
|
|
|
+err:
|
|
|
+ iwl_free_fw_paging(fwrt);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int iwl_save_fw_paging(struct iwl_fw_runtime *fwrt,
|