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