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