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