1/*++ 2 3Copyright (c) 1998 Intel Corporation 4 5Module Name: 6 7 hand.c 8 9Abstract: 10 11 12 13 14Revision History 15 16--*/ 17 18#include "lib.h" 19#include "efistdarg.h" // !!! 20 21 22EFI_STATUS 23LibLocateProtocol ( 24 IN EFI_GUID *ProtocolGuid, 25 OUT VOID **Interface 26 ) 27// 28// Find the first instance of this Protocol in the system and return it's interface 29// 30{ 31 EFI_STATUS Status; 32 UINTN NumberHandles, Index; 33 EFI_HANDLE *Handles; 34 35 36 *Interface = NULL; 37 Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles); 38 if (EFI_ERROR(Status)) { 39 DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n")); 40 return Status; 41 } 42 43 for (Index=0; Index < NumberHandles; Index++) { 44 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface); 45 if (!EFI_ERROR(Status)) { 46 break; 47 } 48 } 49 50 if (Handles) { 51 FreePool (Handles); 52 } 53 54 return Status; 55} 56 57EFI_STATUS 58LibLocateHandle ( 59 IN EFI_LOCATE_SEARCH_TYPE SearchType, 60 IN EFI_GUID *Protocol OPTIONAL, 61 IN VOID *SearchKey OPTIONAL, 62 IN OUT UINTN *NoHandles, 63 OUT EFI_HANDLE **Buffer 64 ) 65 66{ 67 EFI_STATUS Status; 68 UINTN BufferSize; 69 70 // 71 // Initialize for GrowBuffer loop 72 // 73 74 Status = EFI_SUCCESS; 75 *Buffer = NULL; 76 BufferSize = 50 * sizeof(EFI_HANDLE); 77 78 // 79 // Call the real function 80 // 81 82 while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) { 83 84 Status = uefi_call_wrapper( 85 BS->LocateHandle, 86 5, 87 SearchType, 88 Protocol, 89 SearchKey, 90 &BufferSize, 91 *Buffer 92 ); 93 94 } 95 96 *NoHandles = BufferSize / sizeof (EFI_HANDLE); 97 if (EFI_ERROR(Status)) { 98 *NoHandles = 0; 99 } 100 101 return Status; 102} 103 104EFI_STATUS 105LibLocateHandleByDiskSignature ( 106 IN UINT8 MBRType, 107 IN UINT8 SignatureType, 108 IN VOID *Signature, 109 IN OUT UINTN *NoHandles, 110 OUT EFI_HANDLE **Buffer 111 ) 112 113{ 114 EFI_STATUS Status; 115 UINTN BufferSize; 116 UINTN NoBlockIoHandles; 117 EFI_HANDLE *BlockIoBuffer; 118 EFI_DEVICE_PATH *DevicePath; 119 UINTN Index; 120 EFI_DEVICE_PATH *Start, *Next, *DevPath; 121 HARDDRIVE_DEVICE_PATH *HardDriveDevicePath; 122 BOOLEAN Match; 123 BOOLEAN PreviousNodeIsHardDriveDevicePath; 124 125 // 126 // Initialize for GrowBuffer loop 127 // 128 129 Status = EFI_SUCCESS; 130 BlockIoBuffer = NULL; 131 BufferSize = 50 * sizeof(EFI_HANDLE); 132 133 // 134 // Call the real function 135 // 136 137 while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) { 138 139 // 140 // Get list of device handles that support the BLOCK_IO Protocol. 141 // 142 143 Status = uefi_call_wrapper( 144 BS->LocateHandle, 145 5, 146 ByProtocol, 147 &BlockIoProtocol, 148 NULL, 149 &BufferSize, 150 BlockIoBuffer 151 ); 152 153 } 154 155 NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE); 156 if (EFI_ERROR(Status)) { 157 NoBlockIoHandles = 0; 158 } 159 160 // 161 // If there was an error or there are no device handles that support 162 // the BLOCK_IO Protocol, then return. 163 // 164 165 if (NoBlockIoHandles == 0) { 166 FreePool(BlockIoBuffer); 167 *NoHandles = 0; 168 *Buffer = NULL; 169 return Status; 170 } 171 172 // 173 // Loop through all the device handles that support the BLOCK_IO Protocol 174 // 175 176 *NoHandles = 0; 177 178 for(Index=0;Index<NoBlockIoHandles;Index++) { 179 180 Status = uefi_call_wrapper( 181 BS->HandleProtocol, 182 3, 183 BlockIoBuffer[Index], 184 &DevicePathProtocol, 185 (VOID*)&DevicePath 186 ); 187 188 // 189 // Search DevicePath for a Hard Drive Media Device Path node. 190 // If one is found, then see if it matches the signature that was 191 // passed in. If it does match, and the next node is the End of the 192 // device path, and the previous node is not a Hard Drive Media Device 193 // Path, then we have found a match. 194 // 195 196 Match = FALSE; 197 198 if (DevicePath != NULL) { 199 200 PreviousNodeIsHardDriveDevicePath = FALSE; 201 202 DevPath = DevicePath; 203 Start = DevPath; 204 205 // 206 // Check for end of device path type 207 // 208 209 for (; ;) { 210 211 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && 212 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { 213 214 HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath); 215 216 if (PreviousNodeIsHardDriveDevicePath == FALSE) { 217 218 Next = NextDevicePathNode(DevPath); 219 if (IsDevicePathEndType(Next)) { 220 if ((HardDriveDevicePath->MBRType == MBRType) && 221 (HardDriveDevicePath->SignatureType == SignatureType)) { 222 switch(SignatureType) { 223 case SIGNATURE_TYPE_MBR: 224 if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) { 225 Match = TRUE; 226 } 227 break; 228 case SIGNATURE_TYPE_GUID: 229 if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) { 230 Match = TRUE; 231 } 232 break; 233 } 234 } 235 } 236 } 237 PreviousNodeIsHardDriveDevicePath = TRUE; 238 } else { 239 PreviousNodeIsHardDriveDevicePath = FALSE; 240 } 241 242 if (IsDevicePathEnd(DevPath)) { 243 break; 244 } 245 246 DevPath = NextDevicePathNode(DevPath); 247 } 248 249 } 250 251 if (Match == FALSE) { 252 BlockIoBuffer[Index] = NULL; 253 } else { 254 *NoHandles = *NoHandles + 1; 255 } 256 } 257 258 // 259 // If there are no matches, then return 260 // 261 262 if (*NoHandles == 0) { 263 FreePool(BlockIoBuffer); 264 *NoHandles = 0; 265 *Buffer = NULL; 266 return EFI_SUCCESS; 267 } 268 269 // 270 // Allocate space for the return buffer of device handles. 271 // 272 273 *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE)); 274 275 if (*Buffer == NULL) { 276 FreePool(BlockIoBuffer); 277 *NoHandles = 0; 278 *Buffer = NULL; 279 return EFI_OUT_OF_RESOURCES; 280 } 281 282 // 283 // Build list of matching device handles. 284 // 285 286 *NoHandles = 0; 287 for(Index=0;Index<NoBlockIoHandles;Index++) { 288 if (BlockIoBuffer[Index] != NULL) { 289 (*Buffer)[*NoHandles] = BlockIoBuffer[Index]; 290 *NoHandles = *NoHandles + 1; 291 } 292 } 293 294 FreePool(BlockIoBuffer); 295 296 return EFI_SUCCESS; 297} 298 299EFI_FILE_HANDLE 300LibOpenRoot ( 301 IN EFI_HANDLE DeviceHandle 302 ) 303{ 304 EFI_STATUS Status; 305 EFI_FILE_IO_INTERFACE *Volume; 306 EFI_FILE_HANDLE File; 307 308 309 // 310 // File the file system interface to the device 311 // 312 313 Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume); 314 315 // 316 // Open the root directory of the volume 317 // 318 319 if (!EFI_ERROR(Status)) { 320 Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File); 321 } 322 323 // 324 // Done 325 // 326 327 return EFI_ERROR(Status) ? NULL : File; 328} 329 330EFI_FILE_INFO * 331LibFileInfo ( 332 IN EFI_FILE_HANDLE FHand 333 ) 334{ 335 EFI_STATUS Status; 336 EFI_FILE_INFO *Buffer; 337 UINTN BufferSize; 338 339 // 340 // Initialize for GrowBuffer loop 341 // 342 343 Status = EFI_SUCCESS; 344 Buffer = NULL; 345 BufferSize = SIZE_OF_EFI_FILE_INFO + 200; 346 347 // 348 // Call the real function 349 // 350 351 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 352 Status = uefi_call_wrapper( 353 FHand->GetInfo, 354 4, 355 FHand, 356 &GenericFileInfo, 357 &BufferSize, 358 Buffer 359 ); 360 } 361 362 return Buffer; 363} 364 365 366EFI_FILE_SYSTEM_INFO * 367LibFileSystemInfo ( 368 IN EFI_FILE_HANDLE FHand 369 ) 370{ 371 EFI_STATUS Status; 372 EFI_FILE_SYSTEM_INFO *Buffer; 373 UINTN BufferSize; 374 375 // 376 // Initialize for GrowBuffer loop 377 // 378 379 Status = EFI_SUCCESS; 380 Buffer = NULL; 381 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200; 382 383 // 384 // Call the real function 385 // 386 387 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 388 Status = uefi_call_wrapper( 389 FHand->GetInfo, 390 4, 391 FHand, 392 &FileSystemInfo, 393 &BufferSize, 394 Buffer 395 ); 396 } 397 398 return Buffer; 399} 400 401EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * 402LibFileSystemVolumeLabelInfo ( 403 IN EFI_FILE_HANDLE FHand 404 ) 405{ 406 EFI_STATUS Status; 407 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer; 408 UINTN BufferSize; 409 410 // 411 // Initialize for GrowBuffer loop 412 // 413 414 Status = EFI_SUCCESS; 415 Buffer = NULL; 416 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200; 417 418 // 419 // Call the real function 420 // 421 422 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 423 Status = uefi_call_wrapper( 424 FHand->GetInfo, 425 4, 426 FHand, 427 &FileSystemVolumeLabelInfo, 428 &BufferSize, 429 Buffer 430 ); 431 } 432 433 return Buffer; 434} 435 436 437 438EFI_STATUS 439LibInstallProtocolInterfaces ( 440 IN OUT EFI_HANDLE *Handle, 441 ... 442 ) 443{ 444 va_list args; 445 EFI_STATUS Status; 446 EFI_GUID *Protocol; 447 VOID *Interface; 448 EFI_TPL OldTpl; 449 UINTN Index; 450 EFI_HANDLE OldHandle; 451 452 // 453 // Syncronize with notifcations 454 // 455 456 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); 457 OldHandle = *Handle; 458 459 // 460 // Install the protocol interfaces 461 // 462 463 Index = 0; 464 Status = EFI_SUCCESS; 465 va_start (args, Handle); 466 467 while (!EFI_ERROR(Status)) { 468 469 // 470 // If protocol is NULL, then it's the end of the list 471 // 472 473 Protocol = va_arg(args, EFI_GUID *); 474 if (!Protocol) { 475 break; 476 } 477 478 Interface = va_arg(args, VOID *); 479 480 // 481 // Install it 482 // 483 484 DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface)); 485 Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); 486 if (EFI_ERROR(Status)) { 487 break; 488 } 489 490 Index += 1; 491 } 492 493 // 494 // If there was an error, remove all the interfaces that were 495 // installed without any errors 496 // 497 498 if (EFI_ERROR(Status)) { 499 va_start (args, Handle); 500 while (Index) { 501 502 Protocol = va_arg(args, EFI_GUID *); 503 Interface = va_arg(args, VOID *); 504 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface); 505 506 Index -= 1; 507 } 508 509 *Handle = OldHandle; 510 } 511 512 // 513 // Done 514 // 515 516 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 517 return Status; 518} 519 520 521VOID 522LibUninstallProtocolInterfaces ( 523 IN EFI_HANDLE Handle, 524 ... 525 ) 526{ 527 va_list args; 528 EFI_STATUS Status; 529 EFI_GUID *Protocol; 530 VOID *Interface; 531 532 533 va_start (args, Handle); 534 for (; ;) { 535 536 // 537 // If protocol is NULL, then it's the end of the list 538 // 539 540 Protocol = va_arg(args, EFI_GUID *); 541 if (!Protocol) { 542 break; 543 } 544 545 Interface = va_arg(args, VOID *); 546 547 // 548 // Uninstall it 549 // 550 551 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface); 552 if (EFI_ERROR(Status)) { 553 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle)); 554 } 555 } 556} 557 558 559EFI_STATUS 560LibReinstallProtocolInterfaces ( 561 IN OUT EFI_HANDLE *Handle, 562 ... 563 ) 564{ 565 va_list args; 566 EFI_STATUS Status; 567 EFI_GUID *Protocol; 568 VOID *OldInterface, *NewInterface; 569 EFI_TPL OldTpl; 570 UINTN Index; 571 572 // 573 // Syncronize with notifcations 574 // 575 576 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); 577 578 // 579 // Install the protocol interfaces 580 // 581 582 Index = 0; 583 Status = EFI_SUCCESS; 584 va_start (args, Handle); 585 586 while (!EFI_ERROR(Status)) { 587 588 // 589 // If protocol is NULL, then it's the end of the list 590 // 591 592 Protocol = va_arg(args, EFI_GUID *); 593 if (!Protocol) { 594 break; 595 } 596 597 OldInterface = va_arg(args, VOID *); 598 NewInterface = va_arg(args, VOID *); 599 600 // 601 // Reinstall it 602 // 603 604 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface); 605 if (EFI_ERROR(Status)) { 606 break; 607 } 608 609 Index += 1; 610 } 611 612 // 613 // If there was an error, undo all the interfaces that were 614 // reinstalled without any errors 615 // 616 617 if (EFI_ERROR(Status)) { 618 va_start (args, Handle); 619 while (Index) { 620 621 Protocol = va_arg(args, EFI_GUID *); 622 OldInterface = va_arg(args, VOID *); 623 NewInterface = va_arg(args, VOID *); 624 625 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface); 626 627 Index -= 1; 628 } 629 } 630 631 // 632 // Done 633 // 634 635 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 636 return Status; 637} 638