blob: 932f7edb67def00e968a404768816a5114cecefe [file] [log] [blame]
klu2420fc8e2007-06-27 05:46:08 +00001/*+++
2
3Copyright (c) 2006 - 2007, Intel Corporation
4All rights reserved. This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution. The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13
14 WinNtBusDriver.c
15
16Abstract:
17
18This following section documents the envirnoment variables for the Win NT
19build. These variables are used to define the (virtual) hardware
20configuration of the NT environment
21
22A ! can be used to seperate multiple instances in a variable. Each
23instance represents a seperate hardware device.
24
25EFI_WIN_NT_PHYSICAL_DISKS - maps to drives on your system
26EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file
27EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system
28EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!)
29EFI_WIN_NT_UGA - Builds UGA Windows of Width and Height
30EFI_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
128extern EFI_GUID gWinNtBusDriverGuid;
129//
130// DriverBinding protocol global
131//
132EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding = {
133 WinNtBusDriverBindingSupported,
134 WinNtBusDriverBindingStart,
135 WinNtBusDriverBindingStop,
136 0xa,
137 NULL,
138 NULL
139};
140
klu2cba90122007-07-10 08:57:25 +0000141#define NT_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(NT_PCD_ENTRY))
klu2420fc8e2007-06-27 05:46:08 +0000142
143//
144// Table to map NT Environment variable to the GUID that should be in
145// device path.
146//
klu2cba90122007-07-10 08:57:25 +0000147static NT_PCD_ENTRY mPcdEnvironment[] = {
148 PcdToken(PcdWinNtConsole), &gEfiWinNtConsoleGuid,
149 PcdToken(PcdWinNtGop), &gEfiWinNtGopGuid,
150 PcdToken(PcdWinNtSerialPort), &gEfiWinNtSerialPortGuid,
151 PcdToken(PcdWinNtFileSystem), &gEfiWinNtFileSystemGuid,
152 PcdToken(PcdWinNtVirtualDisk), &gEfiWinNtVirtualDisksGuid,
AJFISHb397fbb2007-07-26 21:33:37 +0000153 PcdToken(PcdWinNtPhysicalDisk), &gEfiWinNtPhysicalDisksGuid
klu2420fc8e2007-06-27 05:46:08 +0000154};
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**/
166EFI_STATUS
167EFIAPI
168InitializeWinNtBusDriver(
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 //
qhuang8e1107a72007-09-29 11:20:23 +0000178 Status = EfiLibInstallDriverBindingComponentName2 (
klu2420fc8e2007-06-27 05:46:08 +0000179 ImageHandle,
180 SystemTable,
181 &gWinNtBusDriverBinding,
182 ImageHandle,
183 &gWinNtBusDriverComponentName,
qhuang8e1107a72007-09-29 11:20:23 +0000184 &gWinNtBusDriverComponentName2
klu2420fc8e2007-06-27 05:46:08 +0000185 );
186 ASSERT_EFI_ERROR (Status);
187
188
189 return Status;
190}
191
192VOID *
193AllocateMemory (
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
206EFI_STATUS
207EFIAPI
208WinNtBusDriverBindingSupported (
209 IN EFI_DRIVER_BINDING_PROTOCOL *This,
210 IN EFI_HANDLE ControllerHandle,
211 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
212 )
213/*++
214
215Routine Description:
216
217Arguments:
218
219Returns:
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
322EFI_STATUS
323EFIAPI
324WinNtBusDriverBindingStart (
325 IN EFI_DRIVER_BINDING_PROTOCOL *This,
326 IN EFI_HANDLE ControllerHandle,
327 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
328 )
329/*++
330
331Routine Description:
332
333Arguments:
334
335Returns:
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
qhuang8e1107a72007-09-29 11:20:23 +0000403 AddUnicodeString2 (
klu2420fc8e2007-06-27 05:46:08 +0000404 "eng",
405 gWinNtBusDriverComponentName.SupportedLanguages,
406 &WinNtBusDevice->ControllerNameTable,
qhuang8e1107a72007-09-29 11:20:23 +0000407 L"Windows Bus Controller",
408 TRUE
klu2420fc8e2007-06-27 05:46:08 +0000409 );
qhuang8e1107a72007-09-29 11:20:23 +0000410 AddUnicodeString2 (
411 "en",
412 gWinNtBusDriverComponentName2.SupportedLanguages,
413 &WinNtBusDevice->ControllerNameTable,
414 L"Windows Bus Controller",
415 FALSE
416 );
417
klu2420fc8e2007-06-27 05:46:08 +0000418
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++) {
klu2cba90122007-07-10 08:57:25 +0000438 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);
klu2420fc8e2007-06-27 05:46:08 +0000439 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
qhuang8e1107a72007-09-29 11:20:23 +0000527 AddUnicodeString2 (
klu2420fc8e2007-06-27 05:46:08 +0000528 "eng",
529 gWinNtBusDriverComponentName.SupportedLanguages,
530 &WinNtDevice->ControllerNameTable,
qhuang8e1107a72007-09-29 11:20:23 +0000531 ComponentName,
532 TRUE
klu2420fc8e2007-06-27 05:46:08 +0000533 );
qhuang8e1107a72007-09-29 11:20:23 +0000534 AddUnicodeString2 (
535 "en",
536 gWinNtBusDriverComponentName2.SupportedLanguages,
537 &WinNtDevice->ControllerNameTable,
538 ComponentName,
539 FALSE
540 );
541
klu2420fc8e2007-06-27 05:46:08 +0000542
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
591EFI_STATUS
592EFIAPI
593WinNtBusDriverBindingStop (
594 IN EFI_DRIVER_BINDING_PROTOCOL *This,
595 IN EFI_HANDLE ControllerHandle,
596 IN UINTN NumberOfChildren,
597 IN EFI_HANDLE *ChildHandleBuffer
598 )
599/*++
600
601Routine Description:
602
603Arguments:
604
605Returns:
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
736EFI_DEVICE_PATH_PROTOCOL *
737WinNtBusCreateDevicePath (
738 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,
739 IN EFI_GUID *Guid,
740 IN UINT16 InstanceNumber
741 )
742/*++
743
744Routine Description:
745 Create a device path node using Guid and InstanceNumber and append it to
746 the passed in RootDevicePath
747
748Arguments:
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
756Returns:
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}