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