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