1 /**@file 2 3 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 14 WinNtBusDriver.c 15 16 Abstract: 17 18 This following section documents the envirnoment variables for the Win NT 19 build. These variables are used to define the (virtual) hardware 20 configuration of the NT environment 21 22 A ! can be used to seperate multiple instances in a variable. Each 23 instance represents a seperate hardware device. 24 25 EFI_WIN_NT_PHYSICAL_DISKS - maps to drives on your system 26 EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file 27 EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system 28 EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!) 29 EFI_WIN_NT_GOP - Builds GOP Windows of Width and Height 30 EFI_WIN_NT_SERIAL_PORT - maps physical serial ports 31 32 <F>ixed - Fixed disk like a hard drive. 33 <R>emovable - Removable media like a floppy or CD-ROM. 34 Read <O>nly - Write protected device. 35 Read <W>rite - Read write device. 36 <block count> - Decimal number of blocks a device supports. 37 <block size> - Decimal number of bytes per block. 38 39 NT envirnonment variable contents. '<' and '>' are not part of the variable, 40 they are just used to make this help more readable. There should be no 41 spaces between the ';'. Extra spaces will break the variable. A '!' is 42 used to seperate multiple devices in a variable. 43 44 EFI_WIN_NT_VIRTUAL_DISKS = 45 <F | R><O | W>;<block count>;<block size>[!...] 46 47 EFI_WIN_NT_PHYSICAL_DISKS = 48 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...] 49 50 Virtual Disks: These devices use a file to emulate a hard disk or removable 51 media device. 52 53 Thus a 20 MB emulated hard drive would look like: 54 EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512 55 56 A 1.44MB emulated floppy with a block size of 1024 would look like: 57 EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024 58 59 Physical Disks: These devices use NT to open a real device in your system 60 61 Thus a 120 MB floppy would look like: 62 EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512 63 64 Thus a standard CD-ROM floppy would look like: 65 EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048 66 67 EFI_WIN_NT_FILE_SYSTEM = 68 <directory path>[!...] 69 70 Mounting the two directories C:\FOO and C:\BAR would look like: 71 EFI_WIN_NT_FILE_SYSTEM=c:\foo!c:\bar 72 73 EFI_WIN_NT_CONSOLE = 74 <window title> 75 76 Declaring a text console window with the title "My EFI Console" woild look like: 77 EFI_WIN_NT_CONSOLE=My EFI Console 78 79 EFI_WIN_NT_GOP = 80 <width> <height>[!...] 81 82 Declaring a two GOP windows with resolutions of 800x600 and 1024x768 would look like: 83 Example : EFI_WIN_NT_GOP=800 600!1024 768 84 85 EFI_WIN_NT_SERIAL_PORT = 86 <port name>[!...] 87 88 Declaring two serial ports on COM1 and COM2 would look like: 89 Example : EFI_WIN_NT_SERIAL_PORT=COM1!COM2 90 91 EFI_WIN_NT_PASS_THROUGH = 92 <BaseAddress>;<Bus#>;<Device#>;<Function#> 93 94 Declaring a base address of 0xE0000000 (used for PCI Express devices) 95 and having NT32 talk to a device located at bus 0, device 1, function 0: 96 Example : EFI_WIN_NT_PASS_THROUGH=E000000;0;1;0 97 98 ---*/ 99 100 // 101 // The package level header files this module uses 102 // 103 #include <Uefi.h> 104 #include <WinNtDxe.h> 105 // 106 // The protocols, PPI and GUID defintions for this module 107 // 108 #include <Protocol/WinNtThunk.h> 109 #include <Protocol/WinNtIo.h> 110 #include <Protocol/ComponentName.h> 111 #include <Protocol/DriverBinding.h> 112 #include <Protocol/DevicePath.h> 113 // 114 // The Library classes this module consumes 115 // 116 #include <Library/DebugLib.h> 117 #include <Library/BaseLib.h> 118 #include <Library/UefiDriverEntryPoint.h> 119 #include <Library/UefiLib.h> 120 #include <Library/PcdLib.h> 121 #include <Library/BaseMemoryLib.h> 122 #include <Library/UefiBootServicesTableLib.h> 123 #include <Library/DevicePathLib.h> 124 #include <Library/MemoryAllocationLib.h> 125 126 #include "WinNtBusDriver.h" 127 128 extern EFI_GUID gWinNtBusDriverGuid; 129 // 130 // DriverBinding protocol global 131 // 132 EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding = { 133 WinNtBusDriverBindingSupported, 134 WinNtBusDriverBindingStart, 135 WinNtBusDriverBindingStop, 136 0xa, 137 NULL, 138 NULL 139 }; 140 141 #define NT_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(NT_PCD_ENTRY)) 142 143 // 144 // Table to map NT Environment variable to the GUID that should be in 145 // device path. 146 // 147 NT_PCD_ENTRY mPcdEnvironment[] = { 148 PcdToken(PcdWinNtConsole), &gEfiWinNtConsoleGuid, 149 PcdToken(PcdWinNtGop), &gEfiWinNtGopGuid, 150 PcdToken(PcdWinNtSerialPort), &gEfiWinNtSerialPortGuid, 151 PcdToken(PcdWinNtFileSystem), &gEfiWinNtFileSystemGuid, 152 PcdToken(PcdWinNtVirtualDisk), &gEfiWinNtVirtualDisksGuid, 153 PcdToken(PcdWinNtPhysicalDisk), &gEfiWinNtPhysicalDisksGuid 154 }; 155 156 /** 157 The user Entry Point for module WinNtBusDriver. The user code starts with this function. 158 159 @param[in] ImageHandle The firmware allocated handle for the EFI image. 160 @param[in] SystemTable A pointer to the EFI System Table. 161 162 @retval EFI_SUCCESS The entry point is executed successfully. 163 @retval other Some error occurs when executing this entry point. 164 165 **/ 166 EFI_STATUS 167 EFIAPI 168 InitializeWinNtBusDriver( 169 IN EFI_HANDLE ImageHandle, 170 IN EFI_SYSTEM_TABLE *SystemTable 171 ) 172 { 173 EFI_STATUS Status; 174 175 // 176 // Install driver model protocol(s). 177 // 178 Status = EfiLibInstallDriverBindingComponentName2 ( 179 ImageHandle, 180 SystemTable, 181 &gWinNtBusDriverBinding, 182 ImageHandle, 183 &gWinNtBusDriverComponentName, 184 &gWinNtBusDriverComponentName2 185 ); 186 ASSERT_EFI_ERROR (Status); 187 188 189 return Status; 190 } 191 192 VOID * 193 AllocateMemory ( 194 IN UINTN Size 195 ) 196 { 197 VOID *Buffer; 198 199 Buffer = AllocatePool (Size); 200 ASSERT (Buffer != NULL); 201 202 return Buffer; 203 } 204 205 206 EFI_STATUS 207 EFIAPI 208 WinNtBusDriverBindingSupported ( 209 IN EFI_DRIVER_BINDING_PROTOCOL *This, 210 IN EFI_HANDLE ControllerHandle, 211 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 212 ) 213 /*++ 214 215 Routine Description: 216 217 Arguments: 218 219 Returns: 220 221 None 222 223 **/ 224 // TODO: This - add argument and description to function comment 225 // TODO: ControllerHandle - add argument and description to function comment 226 // TODO: RemainingDevicePath - add argument and description to function comment 227 // TODO: EFI_UNSUPPORTED - add return value to function comment 228 // TODO: EFI_UNSUPPORTED - add return value to function comment 229 // TODO: EFI_SUCCESS - add return value to function comment 230 // TODO: EFI_SUCCESS - add return value to function comment 231 { 232 EFI_STATUS Status; 233 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 234 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; 235 UINTN Index; 236 237 // 238 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure 239 // it is a legal Device Path Node for this bus driver's children. 240 // 241 if (RemainingDevicePath != NULL) { 242 // 243 // Check if RemainingDevicePath is the End of Device Path Node, 244 // if yes, go on checking other conditions 245 // 246 if (!IsDevicePathEnd (RemainingDevicePath)) { 247 // 248 // If RemainingDevicePath isn't the End of Device Path Node, 249 // check its validation 250 // 251 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH || 252 RemainingDevicePath->SubType != HW_VENDOR_DP || 253 DevicePathNodeLength(RemainingDevicePath) != sizeof(WIN_NT_VENDOR_DEVICE_PATH_NODE)) { 254 return EFI_UNSUPPORTED; 255 } 256 257 for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) { 258 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) { 259 break; 260 } 261 } 262 263 if (Index >= NT_PCD_ARRAY_SIZE) { 264 return EFI_UNSUPPORTED; 265 } 266 } 267 } 268 269 // 270 // Open the IO Abstraction(s) needed to perform the supported test 271 // 272 Status = gBS->OpenProtocol ( 273 ControllerHandle, 274 &gEfiWinNtThunkProtocolGuid, 275 (VOID **) &WinNtThunk, 276 This->DriverBindingHandle, 277 ControllerHandle, 278 EFI_OPEN_PROTOCOL_BY_DRIVER 279 ); 280 if (Status == EFI_ALREADY_STARTED) { 281 return EFI_SUCCESS; 282 } 283 284 if (EFI_ERROR (Status)) { 285 return Status; 286 } 287 288 // 289 // Close the I/O Abstraction(s) used to perform the supported test 290 // 291 gBS->CloseProtocol ( 292 ControllerHandle, 293 &gEfiWinNtThunkProtocolGuid, 294 This->DriverBindingHandle, 295 ControllerHandle 296 ); 297 298 // 299 // Open the EFI Device Path protocol needed to perform the supported test 300 // 301 Status = gBS->OpenProtocol ( 302 ControllerHandle, 303 &gEfiDevicePathProtocolGuid, 304 (VOID **) &ParentDevicePath, 305 This->DriverBindingHandle, 306 ControllerHandle, 307 EFI_OPEN_PROTOCOL_BY_DRIVER 308 ); 309 if (Status == EFI_ALREADY_STARTED) { 310 return EFI_SUCCESS; 311 } 312 313 if (EFI_ERROR (Status)) { 314 return Status; 315 } 316 317 // 318 // Since we call through WinNtThunk we need to make sure it's valid 319 // 320 Status = EFI_SUCCESS; 321 if (WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) { 322 Status = EFI_UNSUPPORTED; 323 } 324 325 // 326 // Close protocol, don't use device path protocol in the Support() function 327 // 328 gBS->CloseProtocol ( 329 ControllerHandle, 330 &gEfiDevicePathProtocolGuid, 331 This->DriverBindingHandle, 332 ControllerHandle 333 ); 334 335 return Status; 336 } 337 338 EFI_STATUS 339 EFIAPI 340 WinNtBusDriverBindingStart ( 341 IN EFI_DRIVER_BINDING_PROTOCOL *This, 342 IN EFI_HANDLE ControllerHandle, 343 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 344 ) 345 /*++ 346 347 Routine Description: 348 349 Arguments: 350 351 Returns: 352 353 None 354 355 --*/ 356 // TODO: This - add argument and description to function comment 357 // TODO: ControllerHandle - add argument and description to function comment 358 // TODO: RemainingDevicePath - add argument and description to function comment 359 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment 360 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment 361 // TODO: EFI_SUCCESS - add return value to function comment 362 { 363 EFI_STATUS Status; 364 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; 365 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; 366 WIN_NT_BUS_DEVICE *WinNtBusDevice; 367 WIN_NT_IO_DEVICE *WinNtDevice; 368 UINTN Index; 369 CHAR16 *StartString; 370 CHAR16 *SubString; 371 UINT16 Count; 372 UINTN StringSize; 373 UINT16 ComponentName[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH]; 374 WIN_NT_VENDOR_DEVICE_PATH_NODE *Node; 375 BOOLEAN CreateDevice; 376 CHAR16 *TempStr; 377 CHAR16 *PcdTempStr; 378 UINTN TempStrSize; 379 380 Status = EFI_UNSUPPORTED; 381 382 // 383 // Grab the protocols we need 384 // 385 Status = gBS->OpenProtocol ( 386 ControllerHandle, 387 &gEfiDevicePathProtocolGuid, 388 (VOID **) &ParentDevicePath, 389 This->DriverBindingHandle, 390 ControllerHandle, 391 EFI_OPEN_PROTOCOL_BY_DRIVER 392 ); 393 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 394 return Status; 395 } 396 397 Status = gBS->OpenProtocol ( 398 ControllerHandle, 399 &gEfiWinNtThunkProtocolGuid, 400 (VOID **) &WinNtThunk, 401 This->DriverBindingHandle, 402 ControllerHandle, 403 EFI_OPEN_PROTOCOL_BY_DRIVER 404 ); 405 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { 406 return Status; 407 } 408 409 if (Status != EFI_ALREADY_STARTED) { 410 WinNtBusDevice = AllocatePool (sizeof (WIN_NT_BUS_DEVICE)); 411 if (WinNtBusDevice == NULL) { 412 return EFI_OUT_OF_RESOURCES; 413 } 414 415 WinNtBusDevice->Signature = WIN_NT_BUS_DEVICE_SIGNATURE; 416 WinNtBusDevice->ControllerNameTable = NULL; 417 418 AddUnicodeString2 ( 419 "eng", 420 gWinNtBusDriverComponentName.SupportedLanguages, 421 &WinNtBusDevice->ControllerNameTable, 422 L"Windows Bus Controller", 423 TRUE 424 ); 425 AddUnicodeString2 ( 426 "en", 427 gWinNtBusDriverComponentName2.SupportedLanguages, 428 &WinNtBusDevice->ControllerNameTable, 429 L"Windows Bus Controller", 430 FALSE 431 ); 432 433 434 Status = gBS->InstallMultipleProtocolInterfaces ( 435 &ControllerHandle, 436 &gWinNtBusDriverGuid, 437 WinNtBusDevice, 438 NULL 439 ); 440 if (EFI_ERROR (Status)) { 441 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable); 442 FreePool (WinNtBusDevice); 443 return Status; 444 } 445 } 446 447 // 448 // Loop on the Variable list. Parse each variable to produce a set of handles that 449 // represent virtual hardware devices. 450 // 451 for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) { 452 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token); 453 ASSERT (PcdTempStr != NULL); 454 455 TempStrSize = StrLen (PcdTempStr); 456 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1); 457 StrCpy (TempStr, PcdTempStr); 458 459 StartString = TempStr; 460 461 // 462 // Parse the envirnment variable into sub strings using '!' as a delimator. 463 // Each substring needs it's own handle to be added to the system. This code 464 // does not understand the sub string. Thats the device drivers job. 465 // 466 Count = 0; 467 while (*StartString != '\0') { 468 469 // 470 // Find the end of the sub string 471 // 472 SubString = StartString; 473 while (*SubString != '\0' && *SubString != '!') { 474 SubString++; 475 } 476 477 if (*SubString == '!') { 478 // 479 // Replace token with '\0' to make sub strings. If this is the end 480 // of the string SubString will already point to NULL. 481 // 482 *SubString = '\0'; 483 SubString++; 484 } 485 486 CreateDevice = TRUE; 487 if (RemainingDevicePath != NULL) { 488 CreateDevice = FALSE; 489 // 490 // Check if RemainingDevicePath is the End of Device Path Node, 491 // if yes, don't create any child device 492 // 493 if (!IsDevicePathEnd (RemainingDevicePath)) { 494 // 495 // If RemainingDevicePath isn't the End of Device Path Node, 496 // check its validation 497 // 498 Node = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath; 499 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH && 500 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP && 501 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE) 502 ) { 503 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) && 504 Node->Instance == Count 505 ) { 506 CreateDevice = TRUE; 507 } 508 } 509 } 510 } 511 512 if (CreateDevice) { 513 514 // 515 // Allocate instance structure, and fill in parent information. 516 // 517 WinNtDevice = AllocateMemory (sizeof (WIN_NT_IO_DEVICE)); 518 if (WinNtDevice == NULL) { 519 return EFI_OUT_OF_RESOURCES; 520 } 521 522 WinNtDevice->Handle = NULL; 523 WinNtDevice->ControllerHandle = ControllerHandle; 524 WinNtDevice->ParentDevicePath = ParentDevicePath; 525 526 WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk; 527 528 // 529 // Plus 2 to account for the NULL at the end of the Unicode string 530 // 531 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16); 532 WinNtDevice->WinNtIo.EnvString = AllocateMemory (StringSize); 533 if (WinNtDevice->WinNtIo.EnvString != NULL) { 534 CopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize); 535 } 536 537 WinNtDevice->ControllerNameTable = NULL; 538 539 WinNtThunk->SPrintf (ComponentName, sizeof (ComponentName), L"%s", WinNtDevice->WinNtIo.EnvString); 540 541 WinNtDevice->DevicePath = WinNtBusCreateDevicePath ( 542 ParentDevicePath, 543 mPcdEnvironment[Index].DevicePathGuid, 544 Count 545 ); 546 if (WinNtDevice->DevicePath == NULL) { 547 FreePool (WinNtDevice); 548 return EFI_OUT_OF_RESOURCES; 549 } 550 551 AddUnicodeString2 ( 552 "eng", 553 gWinNtBusDriverComponentName.SupportedLanguages, 554 &WinNtDevice->ControllerNameTable, 555 ComponentName, 556 TRUE 557 ); 558 AddUnicodeString2 ( 559 "en", 560 gWinNtBusDriverComponentName2.SupportedLanguages, 561 &WinNtDevice->ControllerNameTable, 562 ComponentName, 563 FALSE 564 ); 565 566 567 WinNtDevice->WinNtIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid; 568 WinNtDevice->WinNtIo.InstanceNumber = Count; 569 570 WinNtDevice->Signature = WIN_NT_IO_DEVICE_SIGNATURE; 571 572 Status = gBS->InstallMultipleProtocolInterfaces ( 573 &WinNtDevice->Handle, 574 &gEfiDevicePathProtocolGuid, 575 WinNtDevice->DevicePath, 576 &gEfiWinNtIoProtocolGuid, 577 &WinNtDevice->WinNtIo, 578 NULL 579 ); 580 if (EFI_ERROR (Status)) { 581 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable); 582 FreePool (WinNtDevice); 583 } else { 584 // 585 // Open For Child Device 586 // 587 Status = gBS->OpenProtocol ( 588 ControllerHandle, 589 &gEfiWinNtThunkProtocolGuid, 590 (VOID **) &WinNtThunk, 591 This->DriverBindingHandle, 592 WinNtDevice->Handle, 593 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 594 ); 595 } 596 } 597 598 // 599 // Parse Next sub string. This will point to '\0' if we are at the end. 600 // 601 Count++; 602 StartString = SubString; 603 } 604 605 FreePool (TempStr); 606 } 607 608 return EFI_SUCCESS; 609 } 610 611 612 EFI_STATUS 613 EFIAPI 614 WinNtBusDriverBindingStop ( 615 IN EFI_DRIVER_BINDING_PROTOCOL *This, 616 IN EFI_HANDLE ControllerHandle, 617 IN UINTN NumberOfChildren, 618 IN EFI_HANDLE *ChildHandleBuffer 619 ) 620 /*++ 621 622 Routine Description: 623 624 Arguments: 625 626 Returns: 627 628 None 629 630 --*/ 631 // TODO: This - add argument and description to function comment 632 // TODO: ControllerHandle - add argument and description to function comment 633 // TODO: NumberOfChildren - add argument and description to function comment 634 // TODO: ChildHandleBuffer - add argument and description to function comment 635 // TODO: EFI_SUCCESS - add return value to function comment 636 // TODO: EFI_DEVICE_ERROR - add return value to function comment 637 // TODO: EFI_SUCCESS - add return value to function comment 638 { 639 EFI_STATUS Status; 640 UINTN Index; 641 BOOLEAN AllChildrenStopped; 642 EFI_WIN_NT_IO_PROTOCOL *WinNtIo; 643 WIN_NT_BUS_DEVICE *WinNtBusDevice; 644 WIN_NT_IO_DEVICE *WinNtDevice; 645 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; 646 647 // 648 // Complete all outstanding transactions to Controller. 649 // Don't allow any new transaction to Controller to be started. 650 // 651 652 if (NumberOfChildren == 0) { 653 // 654 // Close the bus driver 655 // 656 Status = gBS->OpenProtocol ( 657 ControllerHandle, 658 &gWinNtBusDriverGuid, 659 (VOID **) &WinNtBusDevice, 660 This->DriverBindingHandle, 661 ControllerHandle, 662 EFI_OPEN_PROTOCOL_GET_PROTOCOL 663 ); 664 if (EFI_ERROR (Status)) { 665 return Status; 666 } 667 668 gBS->UninstallMultipleProtocolInterfaces ( 669 ControllerHandle, 670 &gWinNtBusDriverGuid, 671 WinNtBusDevice, 672 NULL 673 ); 674 675 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable); 676 677 FreePool (WinNtBusDevice); 678 679 gBS->CloseProtocol ( 680 ControllerHandle, 681 &gEfiWinNtThunkProtocolGuid, 682 This->DriverBindingHandle, 683 ControllerHandle 684 ); 685 686 gBS->CloseProtocol ( 687 ControllerHandle, 688 &gEfiDevicePathProtocolGuid, 689 This->DriverBindingHandle, 690 ControllerHandle 691 ); 692 return EFI_SUCCESS; 693 } 694 695 AllChildrenStopped = TRUE; 696 697 for (Index = 0; Index < NumberOfChildren; Index++) { 698 699 Status = gBS->OpenProtocol ( 700 ChildHandleBuffer[Index], 701 &gEfiWinNtIoProtocolGuid, 702 (VOID **) &WinNtIo, 703 This->DriverBindingHandle, 704 ControllerHandle, 705 EFI_OPEN_PROTOCOL_GET_PROTOCOL 706 ); 707 if (!EFI_ERROR (Status)) { 708 709 WinNtDevice = WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo); 710 711 Status = gBS->CloseProtocol ( 712 ControllerHandle, 713 &gEfiWinNtThunkProtocolGuid, 714 This->DriverBindingHandle, 715 WinNtDevice->Handle 716 ); 717 718 Status = gBS->UninstallMultipleProtocolInterfaces ( 719 WinNtDevice->Handle, 720 &gEfiDevicePathProtocolGuid, 721 WinNtDevice->DevicePath, 722 &gEfiWinNtIoProtocolGuid, 723 &WinNtDevice->WinNtIo, 724 NULL 725 ); 726 727 if (EFI_ERROR (Status)) { 728 gBS->OpenProtocol ( 729 ControllerHandle, 730 &gEfiWinNtThunkProtocolGuid, 731 (VOID **) &WinNtThunk, 732 This->DriverBindingHandle, 733 WinNtDevice->Handle, 734 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 735 ); 736 } else { 737 // 738 // Close the child handle 739 // 740 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable); 741 FreePool (WinNtDevice); 742 } 743 } 744 745 if (EFI_ERROR (Status)) { 746 AllChildrenStopped = FALSE; 747 } 748 } 749 750 if (!AllChildrenStopped) { 751 return EFI_DEVICE_ERROR; 752 } 753 754 return EFI_SUCCESS; 755 } 756 757 EFI_DEVICE_PATH_PROTOCOL * 758 WinNtBusCreateDevicePath ( 759 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath, 760 IN EFI_GUID *Guid, 761 IN UINT16 InstanceNumber 762 ) 763 /*++ 764 765 Routine Description: 766 Create a device path node using Guid and InstanceNumber and append it to 767 the passed in RootDevicePath 768 769 Arguments: 770 RootDevicePath - Root of the device path to return. 771 772 Guid - GUID to use in vendor device path node. 773 774 InstanceNumber - Instance number to use in the vendor device path. This 775 argument is needed to make sure each device path is unique. 776 777 Returns: 778 779 EFI_DEVICE_PATH_PROTOCOL 780 781 --*/ 782 { 783 WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath; 784 785 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH; 786 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP; 787 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)); 788 789 // 790 // The GUID defines the Class 791 // 792 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID)); 793 794 // 795 // Add an instance number so we can make sure there are no Device Path 796 // duplication. 797 // 798 DevicePath.Instance = InstanceNumber; 799 800 return AppendDevicePathNode ( 801 RootDevicePath, 802 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath 803 ); 804 } 805