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