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