1 /* $NetBSD: hand.c,v 1.4 2018/08/16 18:22:05 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 494 va_end (args); 495 496 // 497 // If there was an error, remove all the interfaces that were 498 // installed without any errors 499 // 500 501 if (EFI_ERROR(Status)) { 502 va_start (args, Handle); 503 while (Index) { 504 505 Protocol = va_arg(args, EFI_GUID *); 506 Interface = va_arg(args, VOID *); 507 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface); 508 509 Index -= 1; 510 } 511 va_end (args); 512 513 *Handle = OldHandle; 514 } 515 516 // 517 // Done 518 // 519 520 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 521 return Status; 522 } 523 524 525 VOID 526 LibUninstallProtocolInterfaces ( 527 IN EFI_HANDLE Handle, 528 ... 529 ) 530 { 531 va_list args; 532 EFI_STATUS Status; 533 EFI_GUID *Protocol; 534 VOID *Interface; 535 536 537 va_start (args, Handle); 538 for (; ;) { 539 540 // 541 // If protocol is NULL, then it's the end of the list 542 // 543 544 Protocol = va_arg(args, EFI_GUID *); 545 if (!Protocol) { 546 break; 547 } 548 549 Interface = va_arg(args, VOID *); 550 551 // 552 // Uninstall it 553 // 554 555 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface); 556 if (EFI_ERROR(Status)) { 557 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle)); 558 } 559 } 560 va_end (args); 561 } 562 563 564 EFI_STATUS 565 LibReinstallProtocolInterfaces ( 566 IN OUT EFI_HANDLE *Handle, 567 ... 568 ) 569 { 570 va_list args; 571 EFI_STATUS Status; 572 EFI_GUID *Protocol; 573 VOID *OldInterface, *NewInterface; 574 EFI_TPL OldTpl; 575 UINTN Index; 576 577 // 578 // Syncronize with notifcations 579 // 580 581 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); 582 583 // 584 // Install the protocol interfaces 585 // 586 587 Index = 0; 588 Status = EFI_SUCCESS; 589 va_start (args, Handle); 590 591 while (!EFI_ERROR(Status)) { 592 593 // 594 // If protocol is NULL, then it's the end of the list 595 // 596 597 Protocol = va_arg(args, EFI_GUID *); 598 if (!Protocol) { 599 break; 600 } 601 602 OldInterface = va_arg(args, VOID *); 603 NewInterface = va_arg(args, VOID *); 604 605 // 606 // Reinstall it 607 // 608 609 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface); 610 if (EFI_ERROR(Status)) { 611 break; 612 } 613 614 Index += 1; 615 } 616 617 va_end (args); 618 619 // 620 // If there was an error, undo all the interfaces that were 621 // reinstalled without any errors 622 // 623 624 if (EFI_ERROR(Status)) { 625 va_start (args, Handle); 626 while (Index) { 627 628 Protocol = va_arg(args, EFI_GUID *); 629 OldInterface = va_arg(args, VOID *); 630 NewInterface = va_arg(args, VOID *); 631 632 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface); 633 634 Index -= 1; 635 } 636 va_end (args); 637 } 638 639 // 640 // Done 641 // 642 643 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 644 return Status; 645 } 646