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