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