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