1 /*++ 2 3 Copyright (c) 1998 Intel Corporation 4 5 Module Name: 6 7 hand.c 8 9 Abstract: 10 11 12 13 14 Revision History 15 16 --*/ 17 18 #include "lib.h" 19 #include "efistdarg.h" // !!! 20 21 22 EFI_STATUS 23 LibLocateProtocol ( 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 57 EFI_STATUS 58 LibLocateHandle ( 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 104 EFI_STATUS 105 LibLocateHandleByDiskSignature ( 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 *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 204 // 205 // Check for end of device path type 206 // 207 208 for (; ;) { 209 210 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && 211 (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { 212 213 HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath); 214 215 if (PreviousNodeIsHardDriveDevicePath == FALSE) { 216 217 Next = NextDevicePathNode(DevPath); 218 if (IsDevicePathEndType(Next)) { 219 if ((HardDriveDevicePath->MBRType == MBRType) && 220 (HardDriveDevicePath->SignatureType == SignatureType)) { 221 switch(SignatureType) { 222 case SIGNATURE_TYPE_MBR: 223 if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) { 224 Match = TRUE; 225 } 226 break; 227 case SIGNATURE_TYPE_GUID: 228 if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) { 229 Match = TRUE; 230 } 231 break; 232 } 233 } 234 } 235 } 236 PreviousNodeIsHardDriveDevicePath = TRUE; 237 } else { 238 PreviousNodeIsHardDriveDevicePath = FALSE; 239 } 240 241 if (IsDevicePathEnd(DevPath)) { 242 break; 243 } 244 245 DevPath = NextDevicePathNode(DevPath); 246 } 247 248 } 249 250 if (Match == FALSE) { 251 BlockIoBuffer[Index] = NULL; 252 } else { 253 *NoHandles = *NoHandles + 1; 254 } 255 } 256 257 // 258 // If there are no matches, then return 259 // 260 261 if (*NoHandles == 0) { 262 FreePool(BlockIoBuffer); 263 *NoHandles = 0; 264 *Buffer = NULL; 265 return EFI_SUCCESS; 266 } 267 268 // 269 // Allocate space for the return buffer of device handles. 270 // 271 272 *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE)); 273 274 if (*Buffer == NULL) { 275 FreePool(BlockIoBuffer); 276 *NoHandles = 0; 277 *Buffer = NULL; 278 return EFI_OUT_OF_RESOURCES; 279 } 280 281 // 282 // Build list of matching device handles. 283 // 284 285 *NoHandles = 0; 286 for(Index=0;Index<NoBlockIoHandles;Index++) { 287 if (BlockIoBuffer[Index] != NULL) { 288 (*Buffer)[*NoHandles] = BlockIoBuffer[Index]; 289 *NoHandles = *NoHandles + 1; 290 } 291 } 292 293 FreePool(BlockIoBuffer); 294 295 return EFI_SUCCESS; 296 } 297 298 EFI_FILE_HANDLE 299 LibOpenRoot ( 300 IN EFI_HANDLE DeviceHandle 301 ) 302 { 303 EFI_STATUS Status; 304 EFI_FILE_IO_INTERFACE *Volume; 305 EFI_FILE_HANDLE File; 306 307 308 // 309 // File the file system interface to the device 310 // 311 312 Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume); 313 314 // 315 // Open the root directory of the volume 316 // 317 318 if (!EFI_ERROR(Status)) { 319 Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File); 320 } 321 322 // 323 // Done 324 // 325 326 return EFI_ERROR(Status) ? NULL : File; 327 } 328 329 EFI_FILE_INFO * 330 LibFileInfo ( 331 IN EFI_FILE_HANDLE FHand 332 ) 333 { 334 EFI_STATUS Status; 335 EFI_FILE_INFO *Buffer; 336 UINTN BufferSize; 337 338 // 339 // Initialize for GrowBuffer loop 340 // 341 342 Status = EFI_SUCCESS; 343 Buffer = NULL; 344 BufferSize = SIZE_OF_EFI_FILE_INFO + 200; 345 346 // 347 // Call the real function 348 // 349 350 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 351 Status = uefi_call_wrapper( 352 FHand->GetInfo, 353 4, 354 FHand, 355 &GenericFileInfo, 356 &BufferSize, 357 Buffer 358 ); 359 } 360 361 return Buffer; 362 } 363 364 365 EFI_FILE_SYSTEM_INFO * 366 LibFileSystemInfo ( 367 IN EFI_FILE_HANDLE FHand 368 ) 369 { 370 EFI_STATUS Status; 371 EFI_FILE_SYSTEM_INFO *Buffer; 372 UINTN BufferSize; 373 374 // 375 // Initialize for GrowBuffer loop 376 // 377 378 Status = EFI_SUCCESS; 379 Buffer = NULL; 380 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200; 381 382 // 383 // Call the real function 384 // 385 386 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 387 Status = uefi_call_wrapper( 388 FHand->GetInfo, 389 4, 390 FHand, 391 &FileSystemInfo, 392 &BufferSize, 393 Buffer 394 ); 395 } 396 397 return Buffer; 398 } 399 400 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * 401 LibFileSystemVolumeLabelInfo ( 402 IN EFI_FILE_HANDLE FHand 403 ) 404 { 405 EFI_STATUS Status; 406 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer; 407 UINTN BufferSize; 408 409 // 410 // Initialize for GrowBuffer loop 411 // 412 413 Status = EFI_SUCCESS; 414 Buffer = NULL; 415 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200; 416 417 // 418 // Call the real function 419 // 420 421 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 422 Status = uefi_call_wrapper( 423 FHand->GetInfo, 424 4, 425 FHand, 426 &FileSystemVolumeLabelInfo, 427 &BufferSize, 428 Buffer 429 ); 430 } 431 432 return Buffer; 433 } 434 435 436 437 EFI_STATUS 438 LibInstallProtocolInterfaces ( 439 IN OUT EFI_HANDLE *Handle, 440 ... 441 ) 442 { 443 va_list args; 444 EFI_STATUS Status; 445 EFI_GUID *Protocol; 446 VOID *Interface; 447 EFI_TPL OldTpl; 448 UINTN Index; 449 EFI_HANDLE OldHandle; 450 451 // 452 // Syncronize with notifcations 453 // 454 455 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); 456 OldHandle = *Handle; 457 458 // 459 // Install the protocol interfaces 460 // 461 462 Index = 0; 463 Status = EFI_SUCCESS; 464 va_start (args, Handle); 465 466 while (!EFI_ERROR(Status)) { 467 468 // 469 // If protocol is NULL, then it's the end of the list 470 // 471 472 Protocol = va_arg(args, EFI_GUID *); 473 if (!Protocol) { 474 break; 475 } 476 477 Interface = va_arg(args, VOID *); 478 479 // 480 // Install it 481 // 482 483 DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface)); 484 Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); 485 if (EFI_ERROR(Status)) { 486 break; 487 } 488 489 Index += 1; 490 } 491 va_end (args); 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 va_end (args); 511 } 512 513 // 514 // Done 515 // 516 517 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 518 return Status; 519 } 520 521 522 VOID 523 LibUninstallProtocolInterfaces ( 524 IN EFI_HANDLE Handle, 525 ... 526 ) 527 { 528 va_list args; 529 EFI_STATUS Status; 530 EFI_GUID *Protocol; 531 VOID *Interface; 532 533 534 va_start (args, Handle); 535 for (; ;) { 536 537 // 538 // If protocol is NULL, then it's the end of the list 539 // 540 541 Protocol = va_arg(args, EFI_GUID *); 542 if (!Protocol) { 543 break; 544 } 545 546 Interface = va_arg(args, VOID *); 547 548 // 549 // Uninstall it 550 // 551 552 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface); 553 if (EFI_ERROR(Status)) { 554 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle)); 555 } 556 } 557 va_end (args); 558 } 559 560 561 EFI_STATUS 562 LibReinstallProtocolInterfaces ( 563 IN OUT EFI_HANDLE *Handle, 564 ... 565 ) 566 { 567 va_list args; 568 EFI_STATUS Status; 569 EFI_GUID *Protocol; 570 VOID *OldInterface, *NewInterface; 571 EFI_TPL OldTpl; 572 UINTN Index; 573 574 // 575 // Syncronize with notifcations 576 // 577 578 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); 579 580 // 581 // Install the protocol interfaces 582 // 583 584 Index = 0; 585 Status = EFI_SUCCESS; 586 va_start (args, Handle); 587 588 while (!EFI_ERROR(Status)) { 589 590 // 591 // If protocol is NULL, then it's the end of the list 592 // 593 594 Protocol = va_arg(args, EFI_GUID *); 595 if (!Protocol) { 596 break; 597 } 598 599 OldInterface = va_arg(args, VOID *); 600 NewInterface = va_arg(args, VOID *); 601 602 // 603 // Reinstall it 604 // 605 606 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface); 607 if (EFI_ERROR(Status)) { 608 break; 609 } 610 611 Index += 1; 612 } 613 va_end (args); 614 615 // 616 // If there was an error, undo all the interfaces that were 617 // reinstalled without any errors 618 // 619 620 if (EFI_ERROR(Status)) { 621 va_start (args, Handle); 622 while (Index) { 623 624 Protocol = va_arg(args, EFI_GUID *); 625 OldInterface = va_arg(args, VOID *); 626 NewInterface = va_arg(args, VOID *); 627 628 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface); 629 630 Index -= 1; 631 } 632 va_end (args); 633 } 634 635 // 636 // Done 637 // 638 639 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 640 return Status; 641 } 642