|
@@ -58,6 +58,7 @@
|
|
|
#define ICH_FLASH_HSFCTL 0x0006
|
|
|
#define ICH_FLASH_FADDR 0x0008
|
|
|
#define ICH_FLASH_FDATA0 0x0010
|
|
|
+#define ICH_FLASH_PR0 0x0074
|
|
|
|
|
|
#define ICH_FLASH_READ_COMMAND_TIMEOUT 500
|
|
|
#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500
|
|
@@ -150,6 +151,19 @@ union ich8_hws_flash_regacc {
|
|
|
u16 regval;
|
|
|
};
|
|
|
|
|
|
+/* ICH Flash Protected Region */
|
|
|
+union ich8_flash_protected_range {
|
|
|
+ struct ich8_pr {
|
|
|
+ u32 base:13; /* 0:12 Protected Range Base */
|
|
|
+ u32 reserved1:2; /* 13:14 Reserved */
|
|
|
+ u32 rpe:1; /* 15 Read Protection Enable */
|
|
|
+ u32 limit:13; /* 16:28 Protected Range Limit */
|
|
|
+ u32 reserved2:2; /* 29:30 Reserved */
|
|
|
+ u32 wpe:1; /* 31 Write Protection Enable */
|
|
|
+ } range;
|
|
|
+ u32 regval;
|
|
|
+};
|
|
|
+
|
|
|
static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw);
|
|
|
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
|
|
|
static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
|
|
@@ -1284,6 +1298,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|
|
* programming failed.
|
|
|
*/
|
|
|
if (ret_val) {
|
|
|
+ /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
|
|
|
hw_dbg(hw, "Flash commit failed.\n");
|
|
|
e1000_release_swflag_ich8lan(hw);
|
|
|
return ret_val;
|
|
@@ -1373,6 +1388,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|
|
return e1000e_validate_nvm_checksum_generic(hw);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ *
|
|
|
+ * To prevent malicious write/erase of the NVM, set it to be read-only
|
|
|
+ * so that the hardware ignores all write/erase cycles of the NVM via
|
|
|
+ * the flash control registers. The shadow-ram copy of the NVM will
|
|
|
+ * still be updated, however any updates to this copy will not stick
|
|
|
+ * across driver reloads.
|
|
|
+ **/
|
|
|
+void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
|
|
|
+{
|
|
|
+ union ich8_flash_protected_range pr0;
|
|
|
+ union ich8_hws_flash_status hsfsts;
|
|
|
+ u32 gfpreg;
|
|
|
+ s32 ret_val;
|
|
|
+
|
|
|
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
|
|
|
+ if (ret_val)
|
|
|
+ return;
|
|
|
+
|
|
|
+ gfpreg = er32flash(ICH_FLASH_GFPREG);
|
|
|
+
|
|
|
+ /* Write-protect GbE Sector of NVM */
|
|
|
+ pr0.regval = er32flash(ICH_FLASH_PR0);
|
|
|
+ pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK;
|
|
|
+ pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK);
|
|
|
+ pr0.range.wpe = true;
|
|
|
+ ew32flash(ICH_FLASH_PR0, pr0.regval);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Lock down a subset of GbE Flash Control Registers, e.g.
|
|
|
+ * PR0 to prevent the write-protection from being lifted.
|
|
|
+ * Once FLOCKDN is set, the registers protected by it cannot
|
|
|
+ * be written until FLOCKDN is cleared by a hardware reset.
|
|
|
+ */
|
|
|
+ hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
|
|
|
+ hsfsts.hsf_status.flockdn = true;
|
|
|
+ ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval);
|
|
|
+
|
|
|
+ e1000_release_swflag_ich8lan(hw);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* e1000_write_flash_data_ich8lan - Writes bytes to the NVM
|
|
|
* @hw: pointer to the HW structure
|