]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Foundation/Library/RuntimeDxe/EfiRuntimeLib/ia32/Fvb.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / RuntimeDxe / EfiRuntimeLib / ia32 / Fvb.c
CommitLineData
3eb9473e 1/*++\r
2\r
3Copyright (c) 2004 - 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Fvb.c \r
15\r
16Abstract:\r
17\r
18 Firmware Volume Block Protocol Runtime Abstraction\r
19\r
20 mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the \r
21 index in the mFvbEntry array. This should be the same sequence as the FVB's\r
22 were described in the HOB. We have to remember the handle so we can tell if \r
23 the protocol has been reinstalled and it needs updateing.\r
24\r
25 If you are using any of these lib functions.you must first call FvbInitialize ().\r
26\r
27Key:\r
28 FVB - Firmware Volume Block\r
29\r
30--*/\r
31\r
32#include "Tiano.h"\r
33#include "EfiRuntimeLib.h"\r
34#include EFI_PROTOCOL_DEFINITION (FirmwareVolumeBlock)\r
35#include EFI_PROTOCOL_DEFINITION (FvbExtension)\r
36\r
37//\r
38// Lib will ASSERT if more FVB devices than this are added to the system.\r
39//\r
40UINTN mFvbCount;\r
41VOID *mFvbRegistration;\r
42VOID *mFvbExtRegistration;\r
43static EFI_EVENT mEfiFvbVirtualNotifyEvent;\r
44BOOLEAN gEfiFvbInitialized = FALSE;\r
45EFI_EVENT mFvbEvent;\r
46\r
47BOOLEAN\r
48IsMemoryRuntime (\r
49 IN VOID *Address\r
50 )\r
51/*++\r
52\r
53Routine Description:\r
54 Check whether an address is runtime memory or not.\r
55\r
56Arguments:\r
57\r
58 Address - The Address being checked.\r
59 \r
60Returns: \r
61 TRUE - The address is runtime memory.\r
62 FALSE - The address is not runtime memory.\r
63\r
64--*/\r
65{\r
66 EFI_STATUS Status;\r
67 UINT8 TmpMemoryMap[1];\r
68 UINTN MapKey;\r
69 UINTN DescriptorSize;\r
70 UINT32 DescriptorVersion;\r
71 UINTN MemoryMapSize;\r
72 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
73 EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;\r
74 BOOLEAN IsRuntime;\r
75 UINTN Index;\r
76\r
77 IsRuntime = FALSE;\r
78\r
79 //\r
80 // Get System MemoryMapSize\r
81 //\r
82 MemoryMapSize = 1;\r
83 Status = gBS->GetMemoryMap (\r
84 &MemoryMapSize,\r
85 (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,\r
86 &MapKey,\r
87 &DescriptorSize,\r
88 &DescriptorVersion\r
89 );\r
90 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
91 //\r
92 // Enlarge space here, because we will allocate pool now.\r
93 //\r
94 MemoryMapSize += EFI_PAGE_SIZE;\r
95 Status = gBS->AllocatePool (\r
96 EfiBootServicesData,\r
97 MemoryMapSize,\r
98 (VOID**)&MemoryMap\r
99 );\r
100 ASSERT_EFI_ERROR (Status);\r
101\r
102 //\r
103 // Get System MemoryMap\r
104 //\r
105 Status = gBS->GetMemoryMap (\r
106 &MemoryMapSize,\r
107 MemoryMap,\r
108 &MapKey,\r
109 &DescriptorSize,\r
110 &DescriptorVersion\r
111 );\r
112 ASSERT_EFI_ERROR (Status);\r
113\r
114 MemoryMapPtr = MemoryMap;\r
115 //\r
116 // Search the request Address\r
117 //\r
118 for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {\r
119 if (((EFI_PHYSICAL_ADDRESS)(UINTN)Address >= MemoryMap->PhysicalStart) &&\r
120 ((EFI_PHYSICAL_ADDRESS)(UINTN)Address < MemoryMap->PhysicalStart\r
121 + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) {\r
122 //\r
123 // Found it\r
124 //\r
125 if (MemoryMap->Attribute & EFI_MEMORY_RUNTIME) {\r
126 IsRuntime = TRUE;\r
127 }\r
128 break;\r
129 }\r
130 //\r
131 // Get next item\r
132 //\r
133 MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);\r
134 }\r
135\r
136 //\r
137 // Done\r
138 //\r
139 gBS->FreePool (MemoryMapPtr);\r
140\r
141 return IsRuntime;\r
142}\r
143\r
144VOID\r
145EFIAPI\r
146FvbNotificationFunction (\r
147 IN EFI_EVENT Event,\r
148 IN VOID *Context\r
149 )\r
150/*++\r
151\r
152Routine Description:\r
153 Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is\r
154 reinstalled.\r
155\r
156Arguments:\r
157\r
158 Event - The Event that is being processed\r
159 \r
160 Context - Event Context\r
161\r
162Returns: \r
163 None\r
164\r
165--*/\r
166{\r
167 EFI_STATUS Status;\r
168 UINTN BufferSize;\r
169 EFI_HANDLE Handle;\r
170 UINTN Index;\r
171 UINTN UpdateIndex;\r
172 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
173 EFI_FVB_EXTENSION_PROTOCOL *FvbExtension;\r
174\r
175 while (TRUE) {\r
176 BufferSize = sizeof (Handle);\r
177 Status = gBS->LocateHandle (\r
178 ByRegisterNotify,\r
179 &gEfiFirmwareVolumeBlockProtocolGuid,\r
180 mFvbRegistration,\r
181 &BufferSize,\r
182 &Handle\r
183 );\r
184 if (EFI_ERROR (Status)) {\r
185 //\r
186 // Exit Path of While Loop....\r
187 //\r
188 break;\r
189 }\r
190\r
191 UpdateIndex = MAX_FVB_COUNT;\r
192 for (Index = 0; Index < mFvbCount; Index++) {\r
193 if (mFvbEntry[Index].Handle == Handle) {\r
194 //\r
195 // If the handle is already in the table just update the protocol\r
196 //\r
197 UpdateIndex = Index;\r
198 break;\r
199 }\r
200 }\r
201\r
202 if (UpdateIndex == MAX_FVB_COUNT) {\r
203 //\r
204 // Use the next free slot for a new entry\r
205 //\r
206 UpdateIndex = mFvbCount;\r
207 }\r
208 //\r
209 // The array does not have enough entries\r
210 //\r
211 ASSERT (UpdateIndex < MAX_FVB_COUNT);\r
212\r
213 //\r
214 // Get the interface pointer and if it's ours, skip it.\r
215 // We check Runtime here, because it has no reason to register\r
216 // a boot time FVB protocol.\r
217 //\r
218 Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, &Fvb);\r
219 ASSERT_EFI_ERROR (Status);\r
220 if (IsMemoryRuntime (Fvb)) {\r
221 //\r
222 // Increase mFvbCount if we need to add a new entry\r
223 //\r
224 if (UpdateIndex == mFvbCount) {\r
225 mFvbCount++;\r
226 }\r
227 mFvbEntry[UpdateIndex].Handle = Handle;\r
228 mFvbEntry[UpdateIndex].Fvb = Fvb;\r
229 mFvbEntry[UpdateIndex].FvbExtension = NULL;\r
230\r
231 Status = gBS->HandleProtocol (Handle, &gEfiFvbExtensionProtocolGuid, &FvbExtension);\r
232 if ((Status == EFI_SUCCESS) && IsMemoryRuntime (FvbExtension)) {\r
233 mFvbEntry[UpdateIndex].FvbExtension = FvbExtension;\r
234 }\r
235 }\r
236 }\r
237}\r
238\r
239EFI_STATUS\r
240EfiFvbInitialize (\r
241 VOID\r
242 )\r
243/*++\r
244\r
245Routine Description:\r
246 Initialize globals and register Fvb Protocol notification function.\r
247\r
248Arguments:\r
249 None \r
250\r
251Returns: \r
252 EFI_SUCCESS - Fvb is successfully initialized\r
253 others - Fail to initialize\r
254\r
255--*/\r
256{\r
257 UINTN Status;\r
258 mFvbCount = 0;\r
259\r
260 Status = gBS->AllocatePool (\r
261 EfiRuntimeServicesData,\r
262 (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT,\r
263 (VOID *) &mFvbEntry\r
264 );\r
265\r
266 if (EFI_ERROR (Status)) {\r
267 return Status;\r
268 }\r
269\r
270 EfiZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT);\r
271\r
272 mFvbEvent = RtEfiLibCreateProtocolNotifyEvent (\r
273 &gEfiFirmwareVolumeBlockProtocolGuid,\r
274 EFI_TPL_CALLBACK,\r
275 FvbNotificationFunction,\r
276 NULL,\r
277 &mFvbRegistration\r
278 );\r
279\r
280 //\r
281 // Register SetVirtualAddressMap () notify function\r
282 //\r
283 // Status = gBS->CreateEvent (\r
284 // EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
285 // EFI_TPL_NOTIFY,\r
286 // EfiRuntimeLibFvbVirtualNotifyEvent,\r
287 // NULL,\r
288 // &mEfiFvbVirtualNotifyEvent\r
289 // );\r
290 // ASSERT_EFI_ERROR (Status);\r
291 //\r
292 gEfiFvbInitialized = TRUE;\r
293\r
294 return EFI_SUCCESS;\r
295}\r
296\r
297EFI_STATUS\r
298EfiFvbShutdown (\r
299 VOID\r
300 )\r
301/*++\r
302\r
303Routine Description:\r
304 Release resources allocated in EfiFvbInitialize.\r
305\r
306Arguments:\r
307 None \r
308\r
309Returns: \r
310 EFI_SUCCESS\r
311\r
312--*/\r
313{\r
314 gBS->FreePool ((VOID *) mFvbEntry);\r
315 gBS->CloseEvent (mFvbEvent);\r
316 gEfiFvbInitialized = FALSE;\r
317 return EFI_SUCCESS;\r
318}\r
319\r
320//\r
321// The following functions wrap Fvb protocol in the Runtime Lib functions.\r
322// The Instance translates into Fvb instance. The Fvb order defined by HOBs and\r
323// thus the sequence of FVB protocol addition define Instance.\r
324//\r
325// EfiFvbInitialize () must be called before any of the following functions\r
326// must be called.\r
327//\r
328\r
329EFI_STATUS\r
330EfiFvbReadBlock (\r
331 IN UINTN Instance,\r
332 IN EFI_LBA Lba,\r
333 IN UINTN Offset,\r
334 IN OUT UINTN *NumBytes,\r
335 IN UINT8 *Buffer\r
336 )\r
337/*++\r
338\r
339Routine Description:\r
340 Reads specified number of bytes into a buffer from the specified block\r
341\r
342Arguments:\r
343 Instance - The FV instance to be read from\r
344 Lba - The logical block address to be read from\r
345 Offset - Offset into the block at which to begin reading\r
346 NumBytes - Pointer that on input contains the total size of\r
347 the buffer. On output, it contains the total number\r
348 of bytes read\r
349 Buffer - Pointer to a caller allocated buffer that will be\r
350 used to hold the data read\r
351\r
352Returns: \r
353\r
354 Status code\r
355 \r
356 EFI_INVALID_PARAMETER - invalid parameter\r
357\r
358--*/\r
359{\r
360 if (Instance >= mFvbCount) {\r
361 return EFI_INVALID_PARAMETER;\r
362 }\r
363\r
364 return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);\r
365}\r
366\r
367EFI_STATUS\r
368EfiFvbWriteBlock (\r
369 IN UINTN Instance,\r
370 IN EFI_LBA Lba,\r
371 IN UINTN Offset,\r
372 IN OUT UINTN *NumBytes,\r
373 IN UINT8 *Buffer\r
374 )\r
375/*++\r
376\r
377Routine Description:\r
378 Writes specified number of bytes from the input buffer to the block\r
379\r
380Arguments:\r
381 Instance - The FV instance to be written to\r
382 Lba - The starting logical block index to write to\r
383 Offset - Offset into the block at which to begin writing\r
384 NumBytes - Pointer that on input contains the total size of\r
385 the buffer. On output, it contains the total number\r
386 of bytes actually written\r
387 Buffer - Pointer to a caller allocated buffer that contains\r
388 the source for the write\r
389\r
390Returns: \r
391\r
392 Status code\r
393 \r
394 EFI_INVALID_PARAMETER - invalid parameter\r
395\r
396--*/\r
397{\r
398 if (Instance >= mFvbCount) {\r
399 return EFI_INVALID_PARAMETER;\r
400 }\r
401\r
402 return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);\r
403}\r
404\r
405EFI_STATUS\r
406EfiFvbEraseBlock (\r
407 IN UINTN Instance,\r
408 IN EFI_LBA Lba\r
409 )\r
410/*++\r
411\r
412Routine Description:\r
413 Erases and initializes a firmware volume block\r
414\r
415Arguments:\r
416 Instance - The FV instance to be erased\r
417 Lba - The logical block index to be erased\r
418 \r
419Returns: \r
420\r
421 Status code\r
422 \r
423 EFI_INVALID_PARAMETER - invalid parameter\r
424\r
425--*/\r
426{\r
427 if (Instance >= mFvbCount) {\r
428 return EFI_INVALID_PARAMETER;\r
429 }\r
430\r
431 return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1);\r
432}\r
433\r
434EFI_STATUS\r
435EfiFvbGetVolumeAttributes (\r
436 IN UINTN Instance,\r
437 OUT EFI_FVB_ATTRIBUTES *Attributes\r
438 )\r
439/*++\r
440\r
441Routine Description:\r
442 Retrieves attributes, insures positive polarity of attribute bits, returns\r
443 resulting attributes in output parameter\r
444\r
445Arguments:\r
446 Instance - The FV instance whose attributes is going to be \r
447 returned\r
448 Attributes - Output buffer which contains attributes\r
449\r
450Returns: \r
451 Status code\r
452 \r
453 EFI_INVALID_PARAMETER - invalid parameter\r
454\r
455--*/\r
456{\r
457 if (Instance >= mFvbCount) {\r
458 return EFI_INVALID_PARAMETER;\r
459 }\r
460\r
461 return mFvbEntry[Instance].Fvb->GetVolumeAttributes (mFvbEntry[Instance].Fvb, Attributes);\r
462}\r
463\r
464EFI_STATUS\r
465EfiFvbSetVolumeAttributes (\r
466 IN UINTN Instance,\r
467 IN EFI_FVB_ATTRIBUTES Attributes\r
468 )\r
469/*++\r
470\r
471Routine Description:\r
472 Modifies the current settings of the firmware volume according to the \r
473 input parameter, and returns the new setting of the volume\r
474\r
475Arguments:\r
476 Instance - The FV instance whose attributes is going to be \r
477 modified\r
478 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES \r
479 containing the desired firmware volume settings.\r
480 On successful return, it contains the new settings\r
481 of the firmware volume\r
482\r
483Returns: \r
484 Status code\r
485 \r
486 EFI_INVALID_PARAMETER - invalid parameter\r
487\r
488--*/\r
489{\r
490 if (Instance >= mFvbCount) {\r
491 return EFI_INVALID_PARAMETER;\r
492 }\r
493\r
494 return mFvbEntry[Instance].Fvb->SetVolumeAttributes (mFvbEntry[Instance].Fvb, &Attributes);\r
495}\r
496\r
497EFI_STATUS\r
498EfiFvbGetPhysicalAddress (\r
499 IN UINTN Instance,\r
500 OUT EFI_PHYSICAL_ADDRESS *BaseAddress\r
501 )\r
502/*++\r
503\r
504Routine Description:\r
505 Retrieves the physical address of a memory mapped FV\r
506\r
507Arguments:\r
508 Instance - The FV instance whose base address is going to be\r
509 returned\r
510 BaseAddress - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS \r
511 that on successful return, contains the base address\r
512 of the firmware volume. \r
513\r
514Returns: \r
515\r
516 Status code\r
517 \r
518 EFI_INVALID_PARAMETER - invalid parameter\r
519\r
520--*/\r
521{\r
522 if (Instance >= mFvbCount) {\r
523 return EFI_INVALID_PARAMETER;\r
524 }\r
525\r
526 return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress);\r
527}\r
528\r
529EFI_STATUS\r
530EfiFvbGetBlockSize (\r
531 IN UINTN Instance,\r
532 IN EFI_LBA Lba,\r
533 OUT UINTN *BlockSize,\r
534 OUT UINTN *NumOfBlocks\r
535 )\r
536/*++\r
537\r
538Routine Description:\r
539 Retrieve the size of a logical block\r
540\r
541Arguments:\r
542 Instance - The FV instance whose block size is going to be\r
543 returned\r
544 Lba - Indicates which block to return the size for.\r
545 BlockSize - A pointer to a caller allocated UINTN in which\r
546 the size of the block is returned\r
547 NumOfBlocks - a pointer to a caller allocated UINTN in which the\r
548 number of consecutive blocks starting with Lba is\r
549 returned. All blocks in this range have a size of\r
550 BlockSize\r
551\r
552Returns: \r
553 EFI_SUCCESS - The firmware volume was read successfully and \r
554 contents are in Buffer\r
555 \r
556 EFI_INVALID_PARAMETER - invalid parameter\r
557\r
558--*/\r
559{\r
560 if (Instance >= mFvbCount) {\r
561 return EFI_INVALID_PARAMETER;\r
562 }\r
563\r
564 return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks);\r
565}\r
566\r
567EFI_STATUS\r
568EfiFvbEraseCustomBlockRange (\r
569 IN UINTN Instance,\r
570 IN EFI_LBA StartLba,\r
571 IN UINTN OffsetStartLba,\r
572 IN EFI_LBA LastLba,\r
573 IN UINTN OffsetLastLba\r
574 )\r
575/*++\r
576\r
577Routine Description:\r
578 Erases and initializes a specified range of a firmware volume\r
579\r
580Arguments:\r
581 Instance - The FV instance to be erased\r
582 StartLba - The starting logical block index to be erased\r
583 OffsetStartLba - Offset into the starting block at which to \r
584 begin erasing\r
585 LastLba - The last logical block index to be erased\r
586 OffsetLastLba - Offset into the last block at which to end erasing\r
587\r
588Returns: \r
589\r
590 Status code\r
591 \r
592 EFI_INVALID_PARAMETER - invalid parameter\r
593 \r
594 EFI_UNSUPPORTED - not support\r
595 \r
596--*/\r
597{\r
598 if (Instance >= mFvbCount) {\r
599 return EFI_INVALID_PARAMETER;\r
600 }\r
601\r
602 if (!(mFvbEntry[Instance].FvbExtension)) {\r
603 return EFI_UNSUPPORTED;\r
604 }\r
605\r
606 if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) {\r
607 return EFI_UNSUPPORTED;\r
608 }\r
609\r
610 return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock (\r
611 mFvbEntry[Instance].FvbExtension,\r
612 StartLba,\r
613 OffsetStartLba,\r
614 LastLba,\r
615 OffsetLastLba\r
616 );\r
617}\r