]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteDxe/Ia32/Ia32FtwMisc.c
remove the unused msa files in MdeModulePkg.
[mirror_edk2.git] / MdeModulePkg / Universal / FirmwareVolume / FaultTolerantWriteDxe / Ia32 / Ia32FtwMisc.c
1 /** @file
2
3 Ia32 platform related code to support FtwLite.
4
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include <FtwLite.h>
18
19 //
20 // MACROs for boot block update
21 //
22 #define BOOT_BLOCK_BASE 0xFFFF0000
23
24 //
25 // (LPC -- D31:F0)
26 //
27 #define LPC_BUS_NUMBER 0x00
28 #define LPC_DEVICE_NUMBER 0x1F
29 #define LPC_IF 0xF0
30 //
31 // Top swap
32 //
33 #define GEN_STATUS 0xD4
34 #define TOP_SWAP_BIT (1 << 13)
35
36 /**
37
38 Read PCI register value.
39 This is a internal function.
40
41
42 @param Offset Offset of the register
43
44 @return The pci register value.
45
46 **/
47 UINT32
48 ReadPciRegister (
49 IN UINT32 Offset
50 )
51 {
52 EFI_STATUS Status;
53 UINT32 Value;
54 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
55
56 Value = 0;
57 Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo);
58 if (EFI_ERROR (Status)) {
59 DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status));
60 return 0;
61 }
62
63 Status = PciRootBridgeIo->Pci.Read (
64 PciRootBridgeIo,
65 EfiPciWidthUint32,
66 EFI_PCI_ADDRESS (
67 LPC_BUS_NUMBER,
68 LPC_DEVICE_NUMBER,
69 LPC_IF,
70 Offset
71 ),
72 1,
73 &Value
74 );
75 ASSERT_EFI_ERROR (Status);
76
77 return Value;
78 }
79
80 /**
81
82 Get swap state
83
84 This is a internal function.
85
86 @param FtwLiteDevice Calling context
87 @param SwapState Swap state
88
89 @retval EFI_SUCCESS State successfully got
90
91 **/
92 EFI_STATUS
93 GetSwapState (
94 IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
95 OUT BOOLEAN *SwapState
96 )
97 {
98 //
99 // Top swap status is 13 bit
100 //
101 *SwapState = (BOOLEAN) ((ReadPciRegister (GEN_STATUS) & TOP_SWAP_BIT) != 0);
102
103 return EFI_SUCCESS;
104 }
105
106 /**
107 Set swap state.
108
109 This is a internal function.
110
111 @param FtwLiteDevice Indicates a pointer to the calling context.
112 @param TopSwap New swap state
113
114 @retval EFI_SUCCESS The function completed successfully
115 Note:
116 the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
117 software will not be able to clear the Top-Swap bit until the system is
118 rebooted without GNT[A]# being pulled down.
119
120 **/
121 EFI_STATUS
122 SetSwapState (
123 IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
124 IN BOOLEAN TopSwap
125 )
126 {
127 UINT32 GenStatus;
128 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
129 EFI_STATUS Status;
130
131 //
132 // Top-Swap bit (bit 13, D31: F0, Offset D4h)
133 //
134 GenStatus = ReadPciRegister (GEN_STATUS);
135
136 //
137 // Set 13 bit, according to input NewSwapState
138 //
139 if (TopSwap) {
140 GenStatus |= TOP_SWAP_BIT;
141 } else {
142 GenStatus &= ~TOP_SWAP_BIT;
143 }
144
145 Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo);
146 if (EFI_ERROR (Status)) {
147 DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status));
148 return Status;
149 }
150 //
151 // Write back the GenStatus register
152 //
153 Status = PciRootBridgeIo->Pci.Write (
154 PciRootBridgeIo,
155 EfiPciWidthUint32,
156 EFI_PCI_ADDRESS (
157 LPC_BUS_NUMBER,
158 LPC_DEVICE_NUMBER,
159 LPC_IF,
160 GEN_STATUS
161 ),
162 1,
163 &GenStatus
164 );
165
166 DEBUG_CODE_BEGIN ();
167 if (TopSwap) {
168 DEBUG ((EFI_D_ERROR, "SAR: Set top swap\n"));
169 } else {
170 DEBUG ((EFI_D_ERROR, "SAR: Clear top swap\n"));
171 }
172 DEBUG_CODE_END ();
173
174 return EFI_SUCCESS;
175 }
176
177 /**
178
179 Check whether the block is a boot block.
180
181
182 @param FtwLiteDevice Calling context
183 @param FvBlock Fvb protocol instance
184 @param Lba Lba value
185
186 @retval FALSE This is a boot block.
187 @retval TRUE This is not a boot block.
188
189 **/
190 BOOLEAN
191 IsBootBlock (
192 EFI_FTW_LITE_DEVICE *FtwLiteDevice,
193 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
194 EFI_LBA Lba
195 )
196 {
197 EFI_STATUS Status;
198 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
199
200 Status = GetFvbByAddress (BOOT_BLOCK_BASE, &BootFvb);
201 if (EFI_ERROR (Status)) {
202 return FALSE;
203 }
204 //
205 // Compare the Fvb
206 //
207 return (BOOLEAN) (FvBlock == BootFvb);
208 }
209
210 /**
211 Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
212 Spare block is accessed by FTW backup FVB protocol interface. LBA is
213 FtwLiteDevice->FtwSpareLba.
214 Boot block is accessed by BootFvb protocol interface. LBA is 0.
215
216
217 @param FtwLiteDevice The private data of FTW_LITE driver
218
219 @retval EFI_SUCCESS Spare block content is copied to boot block
220 @retval EFI_INVALID_PARAMETER Input parameter error
221 @retval EFI_OUT_OF_RESOURCES Allocate memory error
222 @retval EFI_ABORTED The function could not complete successfully
223 Notes:
224 FTW will do extra work on boot block update.
225 FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL,
226 which is produced by a chipset driver.
227 FTW updating boot block steps:
228 1. Erase top swap block (0xFFFE-0xFFFEFFFF) and write data to it ready
229 2. Read data from top swap block to memory buffer
230 3. SetSwapState(EFI_SWAPPED)
231 4. Erasing boot block (0xFFFF-0xFFFFFFFF)
232 5. Programming boot block until the boot block is ok.
233 6. SetSwapState(UNSWAPPED)
234 Notes:
235 1. Since the SwapState bit is saved in CMOS, FTW can restore and continue
236 even in the scenario of power failure.
237 2. FTW shall not allow to update boot block when battery state is error.
238
239 **/
240 EFI_STATUS
241 FlushSpareBlockToBootBlock (
242 EFI_FTW_LITE_DEVICE *FtwLiteDevice
243 )
244 {
245 EFI_STATUS Status;
246 UINTN Length;
247 UINT8 *Buffer;
248 UINTN Count;
249 UINT8 *Ptr;
250 UINTN Index;
251 BOOLEAN TopSwap;
252 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
253 EFI_LBA BootLba;
254
255 //
256 // Allocate a memory buffer
257 //
258 Length = FtwLiteDevice->SpareAreaLength;
259 Buffer = AllocatePool (Length);
260 if (Buffer == NULL) {
261 return EFI_OUT_OF_RESOURCES;
262 }
263 //
264 // Get TopSwap bit state
265 //
266 Status = GetSwapState (FtwLiteDevice, &TopSwap);
267 if (EFI_ERROR (Status)) {
268 DEBUG ((EFI_D_ERROR, "FtwLite: Get Top Swapped status - %r\n", Status));
269 FreePool (Buffer);
270 return EFI_ABORTED;
271 }
272
273 if (TopSwap) {
274 //
275 // Get FVB of current boot block
276 //
277 Status = GetFvbByAddress (FtwLiteDevice->SpareAreaAddress + FTW_BLOCK_SIZE, &BootFvb);
278 if (EFI_ERROR (Status)) {
279 FreePool (Buffer);
280 return Status;
281 }
282 //
283 // Read data from current boot block
284 //
285 BootLba = 0;
286 Ptr = Buffer;
287 for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
288 Count = FtwLiteDevice->SizeOfSpareBlock;
289 Status = BootFvb->Read (
290 BootFvb,
291 BootLba + Index,
292 0,
293 &Count,
294 Ptr
295 );
296 if (EFI_ERROR (Status)) {
297 FreePool (Buffer);
298 return Status;
299 }
300
301 Ptr += Count;
302 }
303
304 } else {
305 //
306 // Read data from spare block
307 //
308 Ptr = Buffer;
309 for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
310 Count = FtwLiteDevice->SizeOfSpareBlock;
311 Status = FtwLiteDevice->FtwBackupFvb->Read (
312 FtwLiteDevice->FtwBackupFvb,
313 FtwLiteDevice->FtwSpareLba + Index,
314 0,
315 &Count,
316 Ptr
317 );
318 if (EFI_ERROR (Status)) {
319 FreePool (Buffer);
320 return Status;
321 }
322
323 Ptr += Count;
324 }
325 //
326 // Set TopSwap bit
327 //
328 Status = SetSwapState (FtwLiteDevice, TRUE);
329 DEBUG ((EFI_D_ERROR, "FtwLite: Set Swap State - %r\n", Status));
330 ASSERT_EFI_ERROR (Status);
331 }
332 //
333 // Erase boot block. After setting TopSwap bit, it's spare block now!
334 //
335 Status = FtwEraseSpareBlock (FtwLiteDevice);
336 if (EFI_ERROR (Status)) {
337 FreePool (Buffer);
338 return EFI_ABORTED;
339 }
340 //
341 // Write memory buffer to currenet spare block
342 //
343 Ptr = Buffer;
344 for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
345 Count = FtwLiteDevice->SizeOfSpareBlock;
346 Status = FtwLiteDevice->FtwBackupFvb->Write (
347 FtwLiteDevice->FtwBackupFvb,
348 FtwLiteDevice->FtwSpareLba + Index,
349 0,
350 &Count,
351 Ptr
352 );
353 if (EFI_ERROR (Status)) {
354 DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write boot block - %r\n", Status));
355 FreePool (Buffer);
356 return Status;
357 }
358
359 Ptr += Count;
360 }
361
362 FreePool (Buffer);
363
364 //
365 // Clear TopSwap bit
366 //
367 Status = SetSwapState (FtwLiteDevice, FALSE);
368 DEBUG ((EFI_D_ERROR, "FtwLite: Clear Swap State - %r\n", Status));
369 ASSERT_EFI_ERROR (Status);
370
371 return EFI_SUCCESS;
372 }