diff options
author | Bruce Allan <bruce.w.allan@intel.com> | 2008-10-01 20:18:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-01 20:31:25 -0400 |
commit | 4a7703582836f55a1cbad0e2c1c6ebbee3f9b3a7 (patch) | |
tree | 8ebe25b1ef16c8fd4ced6d356232ddca94ef97a2 /drivers/net/e1000e/ich8lan.c | |
parent | 20b918dc77b383e9779dafceee3f2198a6f7b0e5 (diff) |
e1000e: write protect ICHx NVM to prevent malicious write/erase
Set the hardware to ignore all write/erase cycles to the GbE region in
the ICHx NVM. This feature can be disabled by the WriteProtectNVM module
parameter (enabled by default) only after a hardware reset, but
the machine must be power cycled before trying to enable writes.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
CC: arjan@linux.intel.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/net/e1000e/ich8lan.c')
-rw-r--r-- | drivers/net/e1000e/ich8lan.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 9e38452a738c..d8efba884134 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #define ICH_FLASH_HSFCTL 0x0006 | 58 | #define ICH_FLASH_HSFCTL 0x0006 |
59 | #define ICH_FLASH_FADDR 0x0008 | 59 | #define ICH_FLASH_FADDR 0x0008 |
60 | #define ICH_FLASH_FDATA0 0x0010 | 60 | #define ICH_FLASH_FDATA0 0x0010 |
61 | #define ICH_FLASH_PR0 0x0074 | ||
61 | 62 | ||
62 | #define ICH_FLASH_READ_COMMAND_TIMEOUT 500 | 63 | #define ICH_FLASH_READ_COMMAND_TIMEOUT 500 |
63 | #define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500 | 64 | #define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500 |
@@ -150,6 +151,19 @@ union ich8_hws_flash_regacc { | |||
150 | u16 regval; | 151 | u16 regval; |
151 | }; | 152 | }; |
152 | 153 | ||
154 | /* ICH Flash Protected Region */ | ||
155 | union ich8_flash_protected_range { | ||
156 | struct ich8_pr { | ||
157 | u32 base:13; /* 0:12 Protected Range Base */ | ||
158 | u32 reserved1:2; /* 13:14 Reserved */ | ||
159 | u32 rpe:1; /* 15 Read Protection Enable */ | ||
160 | u32 limit:13; /* 16:28 Protected Range Limit */ | ||
161 | u32 reserved2:2; /* 29:30 Reserved */ | ||
162 | u32 wpe:1; /* 31 Write Protection Enable */ | ||
163 | } range; | ||
164 | u32 regval; | ||
165 | }; | ||
166 | |||
153 | static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); | 167 | static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); |
154 | static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); | 168 | static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); |
155 | static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); | 169 | 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) | |||
1284 | * programming failed. | 1298 | * programming failed. |
1285 | */ | 1299 | */ |
1286 | if (ret_val) { | 1300 | if (ret_val) { |
1301 | /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */ | ||
1287 | hw_dbg(hw, "Flash commit failed.\n"); | 1302 | hw_dbg(hw, "Flash commit failed.\n"); |
1288 | e1000_release_swflag_ich8lan(hw); | 1303 | e1000_release_swflag_ich8lan(hw); |
1289 | return ret_val; | 1304 | return ret_val; |
@@ -1374,6 +1389,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) | |||
1374 | } | 1389 | } |
1375 | 1390 | ||
1376 | /** | 1391 | /** |
1392 | * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only | ||
1393 | * @hw: pointer to the HW structure | ||
1394 | * | ||
1395 | * To prevent malicious write/erase of the NVM, set it to be read-only | ||
1396 | * so that the hardware ignores all write/erase cycles of the NVM via | ||
1397 | * the flash control registers. The shadow-ram copy of the NVM will | ||
1398 | * still be updated, however any updates to this copy will not stick | ||
1399 | * across driver reloads. | ||
1400 | **/ | ||
1401 | void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) | ||
1402 | { | ||
1403 | union ich8_flash_protected_range pr0; | ||
1404 | union ich8_hws_flash_status hsfsts; | ||
1405 | u32 gfpreg; | ||
1406 | s32 ret_val; | ||
1407 | |||
1408 | ret_val = e1000_acquire_swflag_ich8lan(hw); | ||
1409 | if (ret_val) | ||
1410 | return; | ||
1411 | |||
1412 | gfpreg = er32flash(ICH_FLASH_GFPREG); | ||
1413 | |||
1414 | /* Write-protect GbE Sector of NVM */ | ||
1415 | pr0.regval = er32flash(ICH_FLASH_PR0); | ||
1416 | pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK; | ||
1417 | pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK); | ||
1418 | pr0.range.wpe = true; | ||
1419 | ew32flash(ICH_FLASH_PR0, pr0.regval); | ||
1420 | |||
1421 | /* | ||
1422 | * Lock down a subset of GbE Flash Control Registers, e.g. | ||
1423 | * PR0 to prevent the write-protection from being lifted. | ||
1424 | * Once FLOCKDN is set, the registers protected by it cannot | ||
1425 | * be written until FLOCKDN is cleared by a hardware reset. | ||
1426 | */ | ||
1427 | hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); | ||
1428 | hsfsts.hsf_status.flockdn = true; | ||
1429 | ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval); | ||
1430 | |||
1431 | e1000_release_swflag_ich8lan(hw); | ||
1432 | } | ||
1433 | |||
1434 | /** | ||
1377 | * e1000_write_flash_data_ich8lan - Writes bytes to the NVM | 1435 | * e1000_write_flash_data_ich8lan - Writes bytes to the NVM |
1378 | * @hw: pointer to the HW structure | 1436 | * @hw: pointer to the HW structure |
1379 | * @offset: The offset (in bytes) of the byte/word to read. | 1437 | * @offset: The offset (in bytes) of the byte/word to read. |