1 /*++ 2 3 Copyright (c) 2005 - 2008, Intel Corporation. All rights reserved.<BR> 4 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, (VOID **) &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, (VOID **) &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. 477 478 Arguments: 479 Instance - The FV instance whose attributes is going to be 480 modified 481 Attributes - It is a pointer to EFI_FVB_ATTRIBUTES 482 containing the desired firmware volume settings. 483 484 Returns: 485 Status code 486 487 EFI_INVALID_PARAMETER - invalid parameter 488 489 --*/ 490 { 491 if (Instance >= mFvbCount) { 492 return EFI_INVALID_PARAMETER; 493 } 494 495 return mFvbEntry[Instance].Fvb->SetVolumeAttributes (mFvbEntry[Instance].Fvb, &Attributes); 496 } 497 498 EFI_STATUS 499 EfiFvbGetPhysicalAddress ( 500 IN UINTN Instance, 501 OUT EFI_PHYSICAL_ADDRESS *BaseAddress 502 ) 503 /*++ 504 505 Routine Description: 506 Retrieves the physical address of a memory mapped FV 507 508 Arguments: 509 Instance - The FV instance whose base address is going to be 510 returned 511 BaseAddress - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS 512 that on successful return, contains the base address 513 of the firmware volume. 514 515 Returns: 516 517 Status code 518 519 EFI_INVALID_PARAMETER - invalid parameter 520 521 --*/ 522 { 523 if (Instance >= mFvbCount) { 524 return EFI_INVALID_PARAMETER; 525 } 526 527 return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress); 528 } 529 530 EFI_STATUS 531 EfiFvbGetBlockSize ( 532 IN UINTN Instance, 533 IN EFI_LBA Lba, 534 OUT UINTN *BlockSize, 535 OUT UINTN *NumOfBlocks 536 ) 537 /*++ 538 539 Routine Description: 540 Retrieve the size of a logical block 541 542 Arguments: 543 Instance - The FV instance whose block size is going to be 544 returned 545 Lba - Indicates which block to return the size for. 546 BlockSize - A pointer to a caller allocated UINTN in which 547 the size of the block is returned 548 NumOfBlocks - a pointer to a caller allocated UINTN in which the 549 number of consecutive blocks starting with Lba is 550 returned. All blocks in this range have a size of 551 BlockSize 552 553 Returns: 554 EFI_SUCCESS - The firmware volume was read successfully and 555 contents are in Buffer 556 557 EFI_INVALID_PARAMETER - invalid parameter 558 559 --*/ 560 { 561 if (Instance >= mFvbCount) { 562 return EFI_INVALID_PARAMETER; 563 } 564 565 return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks); 566 } 567 568 EFI_STATUS 569 EfiFvbEraseCustomBlockRange ( 570 IN UINTN Instance, 571 IN EFI_LBA StartLba, 572 IN UINTN OffsetStartLba, 573 IN EFI_LBA LastLba, 574 IN UINTN OffsetLastLba 575 ) 576 /*++ 577 578 Routine Description: 579 Erases and initializes a specified range of a firmware volume 580 581 Arguments: 582 Instance - The FV instance to be erased 583 StartLba - The starting logical block index to be erased 584 OffsetStartLba - Offset into the starting block at which to 585 begin erasing 586 LastLba - The last logical block index to be erased 587 OffsetLastLba - Offset into the last block at which to end erasing 588 589 Returns: 590 591 Status code 592 593 EFI_INVALID_PARAMETER - invalid parameter 594 595 EFI_UNSUPPORTED - not support 596 597 --*/ 598 { 599 if (Instance >= mFvbCount) { 600 return EFI_INVALID_PARAMETER; 601 } 602 603 if (!(mFvbEntry[Instance].FvbExtension)) { 604 return EFI_UNSUPPORTED; 605 } 606 607 if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) { 608 return EFI_UNSUPPORTED; 609 } 610 611 return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock ( 612 mFvbEntry[Instance].FvbExtension, 613 StartLba, 614 OffsetStartLba, 615 LastLba, 616 OffsetLastLba 617 ); 618 } 619