Enable dynamic PCD for windowBusDriver
[mirror_edk2.git] / Nt32Pkg / WinNtBusDriverDxe / WinNtBusDriver.c
1 /*+++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. 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_UGA - Builds UGA 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_UGA =
80 <width> <height>[!...]
81
82 Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like:
83 Example : EFI_WIN_NT_UGA=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 static 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 PcdToken(PcdWinNtCpuModel), &gEfiWinNtCPUModelGuid,
155 PcdToken(PcdWinNtCpuSpeed), &gEfiWinNtCPUSpeedGuid,
156 PcdToken(PcdWinNtMemorySize), &gEfiWinNtMemoryGuid
157 };
158
159 /**
160 The user Entry Point for module WinNtBusDriver. The user code starts with this function.
161
162 @param[in] ImageHandle The firmware allocated handle for the EFI image.
163 @param[in] SystemTable A pointer to the EFI System Table.
164
165 @retval EFI_SUCCESS The entry point is executed successfully.
166 @retval other Some error occurs when executing this entry point.
167
168 **/
169 EFI_STATUS
170 EFIAPI
171 InitializeWinNtBusDriver(
172 IN EFI_HANDLE ImageHandle,
173 IN EFI_SYSTEM_TABLE *SystemTable
174 )
175 {
176 EFI_STATUS Status;
177
178 //
179 // Install driver model protocol(s).
180 //
181 Status = EfiLibInstallAllDriverProtocols (
182 ImageHandle,
183 SystemTable,
184 &gWinNtBusDriverBinding,
185 ImageHandle,
186 &gWinNtBusDriverComponentName,
187 NULL,
188 NULL
189 );
190 ASSERT_EFI_ERROR (Status);
191
192
193 return Status;
194 }
195
196 VOID *
197 AllocateMemory (
198 IN UINTN Size
199 )
200 {
201 VOID *Buffer;
202
203 Buffer = AllocatePool (Size);
204 ASSERT (Buffer != NULL);
205
206 return Buffer;
207 }
208
209
210 EFI_STATUS
211 EFIAPI
212 WinNtBusDriverBindingSupported (
213 IN EFI_DRIVER_BINDING_PROTOCOL *This,
214 IN EFI_HANDLE ControllerHandle,
215 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
216 )
217 /*++
218
219 Routine Description:
220
221 Arguments:
222
223 Returns:
224
225 None
226
227 --*/
228 // TODO: This - add argument and description to function comment
229 // TODO: ControllerHandle - add argument and description to function comment
230 // TODO: RemainingDevicePath - add argument and description to function comment
231 // TODO: EFI_UNSUPPORTED - add return value to function comment
232 // TODO: EFI_UNSUPPORTED - add return value to function comment
233 // TODO: EFI_SUCCESS - add return value to function comment
234 // TODO: EFI_SUCCESS - add return value to function comment
235 {
236 EFI_STATUS Status;
237 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
238 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;
239 UINTN Index;
240
241 //
242 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
243 // it is a legal Device Path Node for this bus driver's children.
244 //
245 if (RemainingDevicePath != NULL) {
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 // Open the IO Abstraction(s) needed to perform the supported test
265 //
266 Status = gBS->OpenProtocol (
267 ControllerHandle,
268 &gEfiDevicePathProtocolGuid,
269 &ParentDevicePath,
270 This->DriverBindingHandle,
271 ControllerHandle,
272 EFI_OPEN_PROTOCOL_BY_DRIVER
273 );
274 if (Status == EFI_ALREADY_STARTED) {
275 return EFI_SUCCESS;
276 }
277
278 if (EFI_ERROR (Status)) {
279 return Status;
280 }
281
282 gBS->CloseProtocol (
283 ControllerHandle,
284 &gEfiDevicePathProtocolGuid,
285 This->DriverBindingHandle,
286 ControllerHandle
287 );
288
289 Status = gBS->OpenProtocol (
290 ControllerHandle,
291 &gEfiWinNtThunkProtocolGuid,
292 &WinNtThunk,
293 This->DriverBindingHandle,
294 ControllerHandle,
295 EFI_OPEN_PROTOCOL_BY_DRIVER
296 );
297 if (Status == EFI_ALREADY_STARTED) {
298 return EFI_SUCCESS;
299 }
300
301 if (EFI_ERROR (Status)) {
302 return Status;
303 }
304
305 //
306 // Since we call through WinNtThunk we need to make sure it's valid
307 //
308 Status = EFI_SUCCESS;
309 if (WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) {
310 Status = EFI_UNSUPPORTED;
311 }
312
313 //
314 // Close the I/O Abstraction(s) used to perform the supported test
315 //
316 gBS->CloseProtocol (
317 ControllerHandle,
318 &gEfiWinNtThunkProtocolGuid,
319 This->DriverBindingHandle,
320 ControllerHandle
321 );
322
323 return Status;
324 }
325
326 EFI_STATUS
327 EFIAPI
328 WinNtBusDriverBindingStart (
329 IN EFI_DRIVER_BINDING_PROTOCOL *This,
330 IN EFI_HANDLE ControllerHandle,
331 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
332 )
333 /*++
334
335 Routine Description:
336
337 Arguments:
338
339 Returns:
340
341 None
342
343 --*/
344 // TODO: This - add argument and description to function comment
345 // TODO: ControllerHandle - add argument and description to function comment
346 // TODO: RemainingDevicePath - add argument and description to function comment
347 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
348 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
349 // TODO: EFI_SUCCESS - add return value to function comment
350 {
351 EFI_STATUS Status;
352 EFI_STATUS InstallStatus;
353 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;
354 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
355 WIN_NT_BUS_DEVICE *WinNtBusDevice;
356 WIN_NT_IO_DEVICE *WinNtDevice;
357 UINTN Index;
358 CHAR16 *StartString;
359 CHAR16 *SubString;
360 UINT16 Count;
361 UINTN StringSize;
362 UINT16 ComponentName[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH];
363 WIN_NT_VENDOR_DEVICE_PATH_NODE *Node;
364 BOOLEAN CreateDevice;
365 CHAR16 *TempStr;
366 CHAR16 *PcdTempStr;
367 UINTN TempStrSize;
368
369 Status = EFI_UNSUPPORTED;
370
371 //
372 // Grab the protocols we need
373 //
374 Status = gBS->OpenProtocol (
375 ControllerHandle,
376 &gEfiDevicePathProtocolGuid,
377 &ParentDevicePath,
378 This->DriverBindingHandle,
379 ControllerHandle,
380 EFI_OPEN_PROTOCOL_BY_DRIVER
381 );
382 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
383 return Status;
384 }
385
386 Status = gBS->OpenProtocol (
387 ControllerHandle,
388 &gEfiWinNtThunkProtocolGuid,
389 &WinNtThunk,
390 This->DriverBindingHandle,
391 ControllerHandle,
392 EFI_OPEN_PROTOCOL_BY_DRIVER
393 );
394 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
395 return Status;
396 }
397
398 if (Status != EFI_ALREADY_STARTED) {
399 WinNtBusDevice = AllocatePool (sizeof (WIN_NT_BUS_DEVICE));
400 if (WinNtBusDevice == NULL) {
401 return EFI_OUT_OF_RESOURCES;
402 }
403
404 WinNtBusDevice->Signature = WIN_NT_BUS_DEVICE_SIGNATURE;
405 WinNtBusDevice->ControllerNameTable = NULL;
406
407 AddUnicodeString (
408 "eng",
409 gWinNtBusDriverComponentName.SupportedLanguages,
410 &WinNtBusDevice->ControllerNameTable,
411 L"Windows Bus Controller"
412 );
413
414 Status = gBS->InstallMultipleProtocolInterfaces (
415 &ControllerHandle,
416 &gWinNtBusDriverGuid,
417 WinNtBusDevice,
418 NULL
419 );
420 if (EFI_ERROR (Status)) {
421 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);
422 FreePool (WinNtBusDevice);
423 return Status;
424 }
425 }
426
427 //
428 // Loop on the Variable list. Parse each variable to produce a set of handles that
429 // represent virtual hardware devices.
430 //
431 InstallStatus = EFI_NOT_FOUND;
432 for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) {
433 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);
434 ASSERT (PcdTempStr != NULL);
435
436 TempStrSize = StrLen (PcdTempStr);
437 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);
438 StrCpy (TempStr, PcdTempStr);
439
440 StartString = TempStr;
441
442 //
443 // Parse the envirnment variable into sub strings using '!' as a delimator.
444 // Each substring needs it's own handle to be added to the system. This code
445 // does not understand the sub string. Thats the device drivers job.
446 //
447 Count = 0;
448 while (*StartString != '\0') {
449
450 //
451 // Find the end of the sub string
452 //
453 SubString = StartString;
454 while (*SubString != '\0' && *SubString != '!') {
455 SubString++;
456 }
457
458 if (*SubString == '!') {
459 //
460 // Replace token with '\0' to make sub strings. If this is the end
461 // of the string SubString will already point to NULL.
462 //
463 *SubString = '\0';
464 SubString++;
465 }
466
467 CreateDevice = TRUE;
468 if (RemainingDevicePath != NULL) {
469 CreateDevice = FALSE;
470 Node = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;
471 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&
472 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&
473 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)
474 ) {
475 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&
476 Node->Instance == Count
477 ) {
478 CreateDevice = TRUE;
479 }
480 }
481 }
482
483 if (CreateDevice) {
484
485 //
486 // Allocate instance structure, and fill in parent information.
487 //
488 WinNtDevice = AllocateMemory (sizeof (WIN_NT_IO_DEVICE));
489 if (WinNtDevice == NULL) {
490 return EFI_OUT_OF_RESOURCES;
491 }
492
493 WinNtDevice->Handle = NULL;
494 WinNtDevice->ControllerHandle = ControllerHandle;
495 WinNtDevice->ParentDevicePath = ParentDevicePath;
496
497 WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk;
498
499 //
500 // Plus 2 to account for the NULL at the end of the Unicode string
501 //
502 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);
503 WinNtDevice->WinNtIo.EnvString = AllocateMemory (StringSize);
504 if (WinNtDevice->WinNtIo.EnvString != NULL) {
505 CopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize);
506 }
507
508 WinNtDevice->ControllerNameTable = NULL;
509
510 WinNtThunk->SPrintf (ComponentName, sizeof (ComponentName), L"%s", WinNtDevice->WinNtIo.EnvString);
511
512 WinNtDevice->DevicePath = WinNtBusCreateDevicePath (
513 ParentDevicePath,
514 mPcdEnvironment[Index].DevicePathGuid,
515 Count
516 );
517 if (WinNtDevice->DevicePath == NULL) {
518 FreePool (WinNtDevice);
519 return EFI_OUT_OF_RESOURCES;
520 }
521
522 AddUnicodeString (
523 "eng",
524 gWinNtBusDriverComponentName.SupportedLanguages,
525 &WinNtDevice->ControllerNameTable,
526 ComponentName
527 );
528
529 WinNtDevice->WinNtIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;
530 WinNtDevice->WinNtIo.InstanceNumber = Count;
531
532 WinNtDevice->Signature = WIN_NT_IO_DEVICE_SIGNATURE;
533
534 Status = gBS->InstallMultipleProtocolInterfaces (
535 &WinNtDevice->Handle,
536 &gEfiDevicePathProtocolGuid,
537 WinNtDevice->DevicePath,
538 &gEfiWinNtIoProtocolGuid,
539 &WinNtDevice->WinNtIo,
540 NULL
541 );
542 if (EFI_ERROR (Status)) {
543 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable);
544 FreePool (WinNtDevice);
545 } else {
546 //
547 // Open For Child Device
548 //
549 Status = gBS->OpenProtocol (
550 ControllerHandle,
551 &gEfiWinNtThunkProtocolGuid,
552 &WinNtThunk,
553 This->DriverBindingHandle,
554 WinNtDevice->Handle,
555 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
556 );
557 if (!EFI_ERROR (Status)) {
558 InstallStatus = EFI_SUCCESS;
559 }
560 }
561 }
562
563 //
564 // Parse Next sub string. This will point to '\0' if we are at the end.
565 //
566 Count++;
567 StartString = SubString;
568 }
569
570 FreePool (TempStr);
571 }
572
573 return EFI_SUCCESS;
574 }
575
576
577 EFI_STATUS
578 EFIAPI
579 WinNtBusDriverBindingStop (
580 IN EFI_DRIVER_BINDING_PROTOCOL *This,
581 IN EFI_HANDLE ControllerHandle,
582 IN UINTN NumberOfChildren,
583 IN EFI_HANDLE *ChildHandleBuffer
584 )
585 /*++
586
587 Routine Description:
588
589 Arguments:
590
591 Returns:
592
593 None
594
595 --*/
596 // TODO: This - add argument and description to function comment
597 // TODO: ControllerHandle - add argument and description to function comment
598 // TODO: NumberOfChildren - add argument and description to function comment
599 // TODO: ChildHandleBuffer - add argument and description to function comment
600 // TODO: EFI_SUCCESS - add return value to function comment
601 // TODO: EFI_DEVICE_ERROR - add return value to function comment
602 // TODO: EFI_SUCCESS - add return value to function comment
603 {
604 EFI_STATUS Status;
605 UINTN Index;
606 BOOLEAN AllChildrenStopped;
607 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
608 WIN_NT_BUS_DEVICE *WinNtBusDevice;
609 WIN_NT_IO_DEVICE *WinNtDevice;
610 EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk;
611
612 //
613 // Complete all outstanding transactions to Controller.
614 // Don't allow any new transaction to Controller to be started.
615 //
616
617 if (NumberOfChildren == 0) {
618 //
619 // Close the bus driver
620 //
621 Status = gBS->OpenProtocol (
622 ControllerHandle,
623 &gWinNtBusDriverGuid,
624 &WinNtBusDevice,
625 This->DriverBindingHandle,
626 ControllerHandle,
627 EFI_OPEN_PROTOCOL_GET_PROTOCOL
628 );
629 if (EFI_ERROR (Status)) {
630 return Status;
631 }
632
633 gBS->UninstallMultipleProtocolInterfaces (
634 ControllerHandle,
635 &gWinNtBusDriverGuid,
636 WinNtBusDevice,
637 NULL
638 );
639
640 FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);
641
642 FreePool (WinNtBusDevice);
643
644 gBS->CloseProtocol (
645 ControllerHandle,
646 &gEfiWinNtThunkProtocolGuid,
647 This->DriverBindingHandle,
648 ControllerHandle
649 );
650
651 gBS->CloseProtocol (
652 ControllerHandle,
653 &gEfiDevicePathProtocolGuid,
654 This->DriverBindingHandle,
655 ControllerHandle
656 );
657 return EFI_SUCCESS;
658 }
659
660 AllChildrenStopped = TRUE;
661
662 for (Index = 0; Index < NumberOfChildren; Index++) {
663
664 Status = gBS->OpenProtocol (
665 ChildHandleBuffer[Index],
666 &gEfiWinNtIoProtocolGuid,
667 &WinNtIo,
668 This->DriverBindingHandle,
669 ControllerHandle,
670 EFI_OPEN_PROTOCOL_GET_PROTOCOL
671 );
672 if (!EFI_ERROR (Status)) {
673
674 WinNtDevice = WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo);
675
676 Status = gBS->CloseProtocol (
677 ControllerHandle,
678 &gEfiWinNtThunkProtocolGuid,
679 This->DriverBindingHandle,
680 WinNtDevice->Handle
681 );
682
683 Status = gBS->UninstallMultipleProtocolInterfaces (
684 WinNtDevice->Handle,
685 &gEfiDevicePathProtocolGuid,
686 WinNtDevice->DevicePath,
687 &gEfiWinNtIoProtocolGuid,
688 &WinNtDevice->WinNtIo,
689 NULL
690 );
691
692 if (EFI_ERROR (Status)) {
693 gBS->OpenProtocol (
694 ControllerHandle,
695 &gEfiWinNtThunkProtocolGuid,
696 (VOID **) &WinNtThunk,
697 This->DriverBindingHandle,
698 WinNtDevice->Handle,
699 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
700 );
701 } else {
702 //
703 // Close the child handle
704 //
705 FreeUnicodeStringTable (WinNtDevice->ControllerNameTable);
706 FreePool (WinNtDevice);
707 }
708 }
709
710 if (EFI_ERROR (Status)) {
711 AllChildrenStopped = FALSE;
712 }
713 }
714
715 if (!AllChildrenStopped) {
716 return EFI_DEVICE_ERROR;
717 }
718
719 return EFI_SUCCESS;
720 }
721
722 EFI_DEVICE_PATH_PROTOCOL *
723 WinNtBusCreateDevicePath (
724 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,
725 IN EFI_GUID *Guid,
726 IN UINT16 InstanceNumber
727 )
728 /*++
729
730 Routine Description:
731 Create a device path node using Guid and InstanceNumber and append it to
732 the passed in RootDevicePath
733
734 Arguments:
735 RootDevicePath - Root of the device path to return.
736
737 Guid - GUID to use in vendor device path node.
738
739 InstanceNumber - Instance number to use in the vendor device path. This
740 argument is needed to make sure each device path is unique.
741
742 Returns:
743
744 EFI_DEVICE_PATH_PROTOCOL
745
746 --*/
747 {
748 WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath;
749
750 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;
751 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;
752 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE));
753
754 //
755 // The GUID defines the Class
756 //
757 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));
758
759 //
760 // Add an instance number so we can make sure there are no Device Path
761 // duplication.
762 //
763 DevicePath.Instance = InstanceNumber;
764
765 return AppendDevicePathNode (
766 RootDevicePath,
767 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath
768 );
769 }