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