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