]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteDxe/Ia32/Ia32FtwMisc.c
replace PCI Root Bridge I/O protocol with PciLib to achieve M2 qulity.
[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 Get swap state.
39
40 This is a internal function.
41
42 @param FtwLiteDevice Calling context
43 @param SwapState Swap state
44
45 @retval EFI_SUCCESS State successfully got
46
47 **/
48 EFI_STATUS
49 GetSwapState (
50 IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
51 OUT BOOLEAN *SwapState
52 )
53 {
54 UINT32 Value;
55 Value = PciRead32(EFI_PCI_ADDRESS (LPC_BUS_NUMBER, LPC_DEVICE_NUMBER, LPC_IF, GEN_STATUS))
56
57 //
58 // Top swap status is 13 bit
59 //
60 *SwapState = (BOOLEAN) ((Value & TOP_SWAP_BIT) != 0);
61
62 return EFI_SUCCESS;
63 }
64
65 /**
66 Set swap state.
67
68 This is a internal function.
69
70 @param FtwLiteDevice Indicates a pointer to the calling context.
71 @param TopSwap New swap state
72
73 @retval EFI_SUCCESS The function completed successfully
74 Note:
75 the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
76 software will not be able to clear the Top-Swap bit until the system is
77 rebooted without GNT[A]# being pulled down.
78
79 **/
80 EFI_STATUS
81 SetSwapState (
82 IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
83 IN BOOLEAN TopSwap
84 )
85 {
86 UINT32 GenStatus;
87 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
88 EFI_STATUS Status;
89
90 //
91 // Top-Swap bit (bit 13, D31: F0, Offset D4h)
92 //
93 GenStatus = PciRead32(EFI_PCI_ADDRESS (LPC_BUS_NUMBER, LPC_DEVICE_NUMBER, LPC_IF, GEN_STATUS));
94
95 //
96 // Set 13 bit, according to input NewSwapState
97 //
98 if (TopSwap) {
99 GenStatus |= TOP_SWAP_BIT;
100 } else {
101 GenStatus &= ~TOP_SWAP_BIT;
102 }
103
104 //
105 // Write back the GenStatus register
106 //
107 PciWrite32(EFI_PCI_ADDRESS (LPC_BUS_NUMBER, LPC_DEVICE_NUMBER, LPC_IF, GEN_STATUS), GenStatus);
108
109 DEBUG_CODE_BEGIN ();
110 if (TopSwap) {
111 DEBUG ((EFI_D_ERROR, "SAR: Set top swap\n"));
112 } else {
113 DEBUG ((EFI_D_ERROR, "SAR: Clear top swap\n"));
114 }
115 DEBUG_CODE_END ();
116
117 return EFI_SUCCESS;
118 }
119
120 /**
121
122 Check whether the block is a boot block.
123
124
125 @param FtwLiteDevice Calling context
126 @param FvBlock Fvb protocol instance
127 @param Lba Lba value
128
129 @retval FALSE This is a boot block.
130 @retval TRUE This is not a boot block.
131
132 **/
133 BOOLEAN
134 IsBootBlock (
135 EFI_FTW_LITE_DEVICE *FtwLiteDevice,
136 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
137 EFI_LBA Lba
138 )
139 {
140 EFI_STATUS Status;
141 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
142
143 Status = GetFvbByAddress (BOOT_BLOCK_BASE, &BootFvb);
144 if (EFI_ERROR (Status)) {
145 return FALSE;
146 }
147 //
148 // Compare the Fvb
149 //
150 return (BOOLEAN) (FvBlock == BootFvb);
151 }
152
153 /**
154 Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
155 Spare block is accessed by FTW backup FVB protocol interface. LBA is
156 FtwLiteDevice->FtwSpareLba.
157 Boot block is accessed by BootFvb protocol interface. LBA is 0.
158
159
160 @param FtwLiteDevice The private data of FTW_LITE driver
161
162 @retval EFI_SUCCESS Spare block content is copied to boot block
163 @retval EFI_INVALID_PARAMETER Input parameter error
164 @retval EFI_OUT_OF_RESOURCES Allocate memory error
165 @retval EFI_ABORTED The function could not complete successfully
166 Notes:
167 FTW will do extra work on boot block update.
168 FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL,
169 which is produced by a chipset driver.
170 FTW updating boot block steps:
171 1. Erase top swap block (0xFFFE-0xFFFEFFFF) and write data to it ready
172 2. Read data from top swap block to memory buffer
173 3. SetSwapState(EFI_SWAPPED)
174 4. Erasing boot block (0xFFFF-0xFFFFFFFF)
175 5. Programming boot block until the boot block is ok.
176 6. SetSwapState(UNSWAPPED)
177 Notes:
178 1. Since the SwapState bit is saved in CMOS, FTW can restore and continue
179 even in the scenario of power failure.
180 2. FTW shall not allow to update boot block when battery state is error.
181
182 **/
183 EFI_STATUS
184 FlushSpareBlockToBootBlock (
185 EFI_FTW_LITE_DEVICE *FtwLiteDevice
186 )
187 {
188 EFI_STATUS Status;
189 UINTN Length;
190 UINT8 *Buffer;
191 UINTN Count;
192 UINT8 *Ptr;
193 UINTN Index;
194 BOOLEAN TopSwap;
195 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
196 EFI_LBA BootLba;
197
198 //
199 // Allocate a memory buffer
200 //
201 Length = FtwLiteDevice->SpareAreaLength;
202 Buffer = AllocatePool (Length);
203 if (Buffer == NULL) {
204 return EFI_OUT_OF_RESOURCES;
205 }
206 //
207 // Get TopSwap bit state
208 //
209 Status = GetSwapState (FtwLiteDevice, &TopSwap);
210 if (EFI_ERROR (Status)) {
211 DEBUG ((EFI_D_ERROR, "FtwLite: Get Top Swapped status - %r\n", Status));
212 FreePool (Buffer);
213 return EFI_ABORTED;
214 }
215
216 if (TopSwap) {
217 //
218 // Get FVB of current boot block
219 //
220 Status = GetFvbByAddress (FtwLiteDevice->SpareAreaAddress + FTW_BLOCK_SIZE, &BootFvb);
221 if (EFI_ERROR (Status)) {
222 FreePool (Buffer);
223 return Status;
224 }
225 //
226 // Read data from current boot block
227 //
228 BootLba = 0;
229 Ptr = Buffer;
230 for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
231 Count = FtwLiteDevice->SizeOfSpareBlock;
232 Status = BootFvb->Read (
233 BootFvb,
234 BootLba + Index,
235 0,
236 &Count,
237 Ptr
238 );
239 if (EFI_ERROR (Status)) {
240 FreePool (Buffer);
241 return Status;
242 }
243
244 Ptr += Count;
245 }
246
247 } else {
248 //
249 // Read data from spare block
250 //
251 Ptr = Buffer;
252 for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
253 Count = FtwLiteDevice->SizeOfSpareBlock;
254 Status = FtwLiteDevice->FtwBackupFvb->Read (
255 FtwLiteDevice->FtwBackupFvb,
256 FtwLiteDevice->FtwSpareLba + Index,
257 0,
258 &Count,
259 Ptr
260 );
261 if (EFI_ERROR (Status)) {
262 FreePool (Buffer);
263 return Status;
264 }
265
266 Ptr += Count;
267 }
268 //
269 // Set TopSwap bit
270 //
271 Status = SetSwapState (FtwLiteDevice, TRUE);
272 DEBUG ((EFI_D_ERROR, "FtwLite: Set Swap State - %r\n", Status));
273 ASSERT_EFI_ERROR (Status);
274 }
275 //
276 // Erase boot block. After setting TopSwap bit, it's spare block now!
277 //
278 Status = FtwEraseSpareBlock (FtwLiteDevice);
279 if (EFI_ERROR (Status)) {
280 FreePool (Buffer);
281 return EFI_ABORTED;
282 }
283 //
284 // Write memory buffer to currenet spare block
285 //
286 Ptr = Buffer;
287 for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
288 Count = FtwLiteDevice->SizeOfSpareBlock;
289 Status = FtwLiteDevice->FtwBackupFvb->Write (
290 FtwLiteDevice->FtwBackupFvb,
291 FtwLiteDevice->FtwSpareLba + Index,
292 0,
293 &Count,
294 Ptr
295 );
296 if (EFI_ERROR (Status)) {
297 DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write boot block - %r\n", Status));
298 FreePool (Buffer);
299 return Status;
300 }
301
302 Ptr += Count;
303 }
304
305 FreePool (Buffer);
306
307 //
308 // Clear TopSwap bit
309 //
310 Status = SetSwapState (FtwLiteDevice, FALSE);
311 DEBUG ((EFI_D_ERROR, "FtwLite: Clear Swap State - %r\n", Status));
312 ASSERT_EFI_ERROR (Status);
313
314 return EFI_SUCCESS;
315 }