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