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