1 /* $NetBSD: hand.c,v 1.1.1.1 2014/04/01 16:16:07 jakllsch 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 *Start, *Next, *DevPath; 123 HARDDRIVE_DEVICE_PATH *HardDriveDevicePath; 124 BOOLEAN Match; 125 BOOLEAN PreviousNodeIsHardDriveDevicePath; 126 127 // 128 // Initialize for GrowBuffer loop 129 // 130 131 BlockIoBuffer = NULL; 132 BufferSize = 50 * sizeof(EFI_HANDLE); 133 134 // 135 // Call the real function 136 // 137 138 while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) { 139 140 // 141 // Get list of device handles that support the BLOCK_IO Protocol. 142 // 143 144 Status = uefi_call_wrapper( 145 BS->LocateHandle, 146 5, 147 ByProtocol, 148 &BlockIoProtocol, 149 NULL, 150 &BufferSize, 151 BlockIoBuffer 152 ); 153 154 } 155 156 NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE); 157 if (EFI_ERROR(Status)) { 158 NoBlockIoHandles = 0; 159 } 160 161 // 162 // If there was an error or there are no device handles that support 163 // the BLOCK_IO Protocol, then return. 164 // 165 166 if (NoBlockIoHandles == 0) { 167 FreePool(BlockIoBuffer); 168 *NoHandles = 0; 169 *Buffer = NULL; 170 return Status; 171 } 172 173 // 174 // Loop through all the device handles that support the BLOCK_IO Protocol 175 // 176 177 *NoHandles = 0; 178 179 for(Index=0;Index<NoBlockIoHandles;Index++) { 180 181 Status = uefi_call_wrapper( 182 BS->HandleProtocol, 183 3, 184 BlockIoBuffer[Index], 185 &DevicePathProtocol, 186 (VOID*)&DevicePath 187 ); 188 189 // 190 // Search DevicePath for a Hard Drive Media Device Path node. 191 // If one is found, then see if it matches the signature that was 192 // passed in. If it does match, and the next node is the End of the 193 // device path, and the previous node is not a Hard Drive Media Device 194 // Path, then we have found a match. 195 // 196 197 Match = FALSE; 198 199 if (DevicePath != NULL) { 200 201 PreviousNodeIsHardDriveDevicePath = FALSE; 202 203 DevPath = DevicePath; 204 Start = DevPath; 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 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 366 EFI_FILE_SYSTEM_INFO * 367 LibFileSystemInfo ( 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 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 Buffer = NULL; 414 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200; 415 416 // 417 // Call the real function 418 // 419 420 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 421 Status = uefi_call_wrapper( 422 FHand->GetInfo, 423 4, 424 FHand, 425 &FileSystemVolumeLabelInfo, 426 &BufferSize, 427 Buffer 428 ); 429 } 430 431 return Buffer; 432 } 433 434 435 436 EFI_STATUS 437 LibInstallProtocolInterfaces ( 438 IN OUT EFI_HANDLE *Handle, 439 ... 440 ) 441 { 442 va_list args; 443 EFI_STATUS Status; 444 EFI_GUID *Protocol; 445 VOID *Interface; 446 EFI_TPL OldTpl; 447 UINTN Index; 448 EFI_HANDLE OldHandle; 449 450 // 451 // Syncronize with notifcations 452 // 453 454 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); 455 OldHandle = *Handle; 456 457 // 458 // Install the protocol interfaces 459 // 460 461 Index = 0; 462 Status = EFI_SUCCESS; 463 va_start (args, Handle); 464 465 while (!EFI_ERROR(Status)) { 466 467 // 468 // If protocol is NULL, then it's the end of the list 469 // 470 471 Protocol = va_arg(args, EFI_GUID *); 472 if (!Protocol) { 473 break; 474 } 475 476 Interface = va_arg(args, VOID *); 477 478 // 479 // Install it 480 // 481 482 DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface)); 483 Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); 484 if (EFI_ERROR(Status)) { 485 break; 486 } 487 488 Index += 1; 489 } 490 491 // 492 // If there was an error, remove all the interfaces that were 493 // installed without any errors 494 // 495 496 if (EFI_ERROR(Status)) { 497 va_start (args, Handle); 498 while (Index) { 499 500 Protocol = va_arg(args, EFI_GUID *); 501 Interface = va_arg(args, VOID *); 502 uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface); 503 504 Index -= 1; 505 } 506 507 *Handle = OldHandle; 508 } 509 510 // 511 // Done 512 // 513 514 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 515 return Status; 516 } 517 518 519 VOID 520 LibUninstallProtocolInterfaces ( 521 IN EFI_HANDLE Handle, 522 ... 523 ) 524 { 525 va_list args; 526 EFI_STATUS Status; 527 EFI_GUID *Protocol; 528 VOID *Interface; 529 530 531 va_start (args, Handle); 532 for (; ;) { 533 534 // 535 // If protocol is NULL, then it's the end of the list 536 // 537 538 Protocol = va_arg(args, EFI_GUID *); 539 if (!Protocol) { 540 break; 541 } 542 543 Interface = va_arg(args, VOID *); 544 545 // 546 // Uninstall it 547 // 548 549 Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface); 550 if (EFI_ERROR(Status)) { 551 DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle)); 552 } 553 } 554 } 555 556 557 EFI_STATUS 558 LibReinstallProtocolInterfaces ( 559 IN OUT EFI_HANDLE *Handle, 560 ... 561 ) 562 { 563 va_list args; 564 EFI_STATUS Status; 565 EFI_GUID *Protocol; 566 VOID *OldInterface, *NewInterface; 567 EFI_TPL OldTpl; 568 UINTN Index; 569 570 // 571 // Syncronize with notifcations 572 // 573 574 OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); 575 576 // 577 // Install the protocol interfaces 578 // 579 580 Index = 0; 581 Status = EFI_SUCCESS; 582 va_start (args, Handle); 583 584 while (!EFI_ERROR(Status)) { 585 586 // 587 // If protocol is NULL, then it's the end of the list 588 // 589 590 Protocol = va_arg(args, EFI_GUID *); 591 if (!Protocol) { 592 break; 593 } 594 595 OldInterface = va_arg(args, VOID *); 596 NewInterface = va_arg(args, VOID *); 597 598 // 599 // Reinstall it 600 // 601 602 Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface); 603 if (EFI_ERROR(Status)) { 604 break; 605 } 606 607 Index += 1; 608 } 609 610 // 611 // If there was an error, undo all the interfaces that were 612 // reinstalled without any errors 613 // 614 615 if (EFI_ERROR(Status)) { 616 va_start (args, Handle); 617 while (Index) { 618 619 Protocol = va_arg(args, EFI_GUID *); 620 OldInterface = va_arg(args, VOID *); 621 NewInterface = va_arg(args, VOID *); 622 623 uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface); 624 625 Index -= 1; 626 } 627 } 628 629 // 630 // Done 631 // 632 633 uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); 634 return Status; 635 } 636