3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Ia32 platform related code to support FtwLite..
28 // MACROs for boot block update
30 #define BOOT_BLOCK_BASE 0xFFFF0000
35 #define LPC_BUS_NUMBER 0x00
36 #define LPC_DEVICE_NUMBER 0x1F
41 #define GEN_STATUS 0xD4
42 #define TOP_SWAP_BIT (1 << 13)
53 Read PCI register value.
57 Offset - Offset of the register
67 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
70 Status
= gBS
->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, (VOID
**) &PciRootBridgeIo
);
71 if (EFI_ERROR (Status
)) {
72 DEBUG ((EFI_D_ERROR
, "FtwLite: Locate PCI root bridge io protocol - %r", Status
));
76 Status
= PciRootBridgeIo
->Pci
.Read (
88 ASSERT_EFI_ERROR (Status
);
96 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
97 OUT BOOLEAN
*SwapState
107 FtwLiteDevice - Calling context
108 SwapState - Swap state
112 EFI_SUCCESS - State successfully got
117 // Top swap status is 13 bit
119 *SwapState
= (BOOLEAN
) ((ReadPciRegister (GEN_STATUS
) & TOP_SWAP_BIT
) != 0);
127 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
136 FtwLiteDevice - Indicates a pointer to the calling context.
137 TopSwap - New swap state
140 EFI_SUCCESS - The function completed successfully
143 the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
144 software will not be able to clear the Top-Swap bit until the system is
145 rebooted without GNT[A]# being pulled down.
150 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
154 // Top-Swap bit (bit 13, D31: F0, Offset D4h)
156 GenStatus
= ReadPciRegister (GEN_STATUS
);
159 // Set 13 bit, according to input NewSwapState
162 GenStatus
|= TOP_SWAP_BIT
;
164 GenStatus
&= ~TOP_SWAP_BIT
;
167 Status
= gBS
->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid
, NULL
, (VOID
**) &PciRootBridgeIo
);
168 if (EFI_ERROR (Status
)) {
169 DEBUG ((EFI_D_ERROR
, "FtwLite: Locate PCI root bridge io protocol - %r", Status
));
173 // Write back the GenStatus register
175 Status
= PciRootBridgeIo
->Pci
.Write (
190 DEBUG ((EFI_D_ERROR
, "SAR: Set top swap\n"));
192 DEBUG ((EFI_D_ERROR
, "SAR: Clear top swap\n"));
201 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
202 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
209 Check whether the block is a boot block.
213 FtwLiteDevice - Calling context
214 FvBlock - Fvb protocol instance
219 Is a boot block or not
224 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*BootFvb
;
226 Status
= GetFvbByAddress (BOOT_BLOCK_BASE
, &BootFvb
);
227 if (EFI_ERROR (Status
)) {
233 return (BOOLEAN
) (FvBlock
== BootFvb
);
237 FlushSpareBlockToBootBlock (
238 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
243 Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
244 Spare block is accessed by FTW backup FVB protocol interface. LBA is
245 FtwLiteDevice->FtwSpareLba.
246 Boot block is accessed by BootFvb protocol interface. LBA is 0.
249 FtwLiteDevice - The private data of FTW_LITE driver
252 EFI_SUCCESS - Spare block content is copied to boot block
253 EFI_INVALID_PARAMETER - Input parameter error
254 EFI_OUT_OF_RESOURCES - Allocate memory error
255 EFI_ABORTED - The function could not complete successfully
258 FTW will do extra work on boot block update.
259 FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL,
260 which is produced by a chipset driver.
262 FTW updating boot block steps:
263 1. Erase top swap block (0xFFFE-0xFFFEFFFF) and write data to it ready
264 2. Read data from top swap block to memory buffer
265 3. SetSwapState(EFI_SWAPPED)
266 4. Erasing boot block (0xFFFF-0xFFFFFFFF)
267 5. Programming boot block until the boot block is ok.
268 6. SetSwapState(UNSWAPPED)
271 1. Since the SwapState bit is saved in CMOS, FTW can restore and continue
272 even in the scenario of power failure.
273 2. FTW shall not allow to update boot block when battery state is error.
284 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*BootFvb
;
288 // Allocate a memory buffer
290 Length
= FtwLiteDevice
->SpareAreaLength
;
291 Buffer
= AllocatePool (Length
);
292 if (Buffer
== NULL
) {
295 // Get TopSwap bit state
297 Status
= GetSwapState (FtwLiteDevice
, &TopSwap
);
298 if (EFI_ERROR (Status
)) {
299 DEBUG ((EFI_D_ERROR
, "FtwLite: Get Top Swapped status - %r\n", Status
));
306 // Get FVB of current boot block
308 Status
= GetFvbByAddress (FtwLiteDevice
->SpareAreaAddress
+ FTW_BLOCK_SIZE
, &BootFvb
);
309 if (EFI_ERROR (Status
)) {
314 // Read data from current boot block
318 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
319 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
320 Status
= BootFvb
->Read (
327 if (EFI_ERROR (Status
)) {
337 // Read data from spare block
340 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
341 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
342 Status
= FtwLiteDevice
->FtwBackupFvb
->Read (
343 FtwLiteDevice
->FtwBackupFvb
,
344 FtwLiteDevice
->FtwSpareLba
+ Index
,
349 if (EFI_ERROR (Status
)) {
359 Status
= SetSwapState (FtwLiteDevice
, TRUE
);
360 DEBUG ((EFI_D_ERROR
, "FtwLite: Set Swap State - %r\n", Status
));
361 ASSERT_EFI_ERROR (Status
);
364 // Erase boot block. After setting TopSwap bit, it's spare block now!
366 Status
= FtwEraseSpareBlock (FtwLiteDevice
);
367 if (EFI_ERROR (Status
)) {
372 // Write memory buffer to currenet spare block
375 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
376 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
377 Status
= FtwLiteDevice
->FtwBackupFvb
->Write (
378 FtwLiteDevice
->FtwBackupFvb
,
379 FtwLiteDevice
->FtwSpareLba
+ Index
,
384 if (EFI_ERROR (Status
)) {
385 DEBUG ((EFI_D_FTW_LITE
, "FtwLite: FVB Write boot block - %r\n", Status
));
398 Status
= SetSwapState (FtwLiteDevice
, FALSE
);
399 DEBUG ((EFI_D_ERROR
, "FtwLite: Clear Swap State - %r\n", Status
));
400 ASSERT_EFI_ERROR (Status
);