]> git.proxmox.com Git - mirror_edk2.git/blob - EdkUnixPkg/Dxe/UnixThunk/Bus/UnixBusDriver/UnixBusDriver.c
Add emulated serialIo device driver for EdkUnixPkg
[mirror_edk2.git] / EdkUnixPkg / Dxe / UnixThunk / Bus / UnixBusDriver / UnixBusDriver.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 UnixBusDriver.c
15
16 Abstract:
17
18 This following section documents the envirnoment variables for the Win UNIX
19 build. These variables are used to define the (virtual) hardware
20 configuration of the UNIX 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_UNIX_PHYSICAL_DISKS - maps to drives on your system
26 EFI_UNIX_VIRTUAL_DISKS - maps to a device emulated by a file
27 EFI_UNIX_FILE_SYSTEM - mouts a directory as a file system
28 EFI_UNIX_CONSOLE - make a logical comand line window (only one!)
29 EFI_UNIX_UGA - Builds UGA Windows of Width and Height
30
31 <F>ixed - Fixed disk like a hard drive.
32 <R>emovable - Removable media like a floppy or CD-ROM.
33 Read <O>nly - Write protected device.
34 Read <W>rite - Read write device.
35 <block count> - Decimal number of blocks a device supports.
36 <block size> - Decimal number of bytes per block.
37
38 UNIX envirnonment variable contents. '<' and '>' are not part of the variable,
39 they are just used to make this help more readable. There should be no
40 spaces between the ';'. Extra spaces will break the variable. A '!' is
41 used to seperate multiple devices in a variable.
42
43 EFI_UNIX_VIRTUAL_DISKS =
44 <F | R><O | W>;<block count>;<block size>[!...]
45
46 EFI_UNIX_PHYSICAL_DISKS =
47 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
48
49 Virtual Disks: These devices use a file to emulate a hard disk or removable
50 media device.
51
52 Thus a 20 MB emulated hard drive would look like:
53 EFI_UNIX_VIRTUAL_DISKS=FW;40960;512
54
55 A 1.44MB emulated floppy with a block size of 1024 would look like:
56 EFI_UNIX_VIRTUAL_DISKS=RW;1440;1024
57
58 Physical Disks: These devices use UNIX to open a real device in your system
59
60 Thus a 120 MB floppy would look like:
61 EFI_UNIX_PHYSICAL_DISKS=B:RW;245760;512
62
63 Thus a standard CD-ROM floppy would look like:
64 EFI_UNIX_PHYSICAL_DISKS=Z:RO;307200;2048
65
66 EFI_UNIX_FILE_SYSTEM =
67 <directory path>[!...]
68
69 Mounting the two directories C:\FOO and C:\BAR would look like:
70 EFI_UNIX_FILE_SYSTEM=c:\foo!c:\bar
71
72 EFI_UNIX_CONSOLE =
73 <window title>
74
75 Declaring a text console window with the title "My EFI Console" woild look like:
76 EFI_UNIX_CONSOLE=My EFI Console
77
78 EFI_UNIX_UGA =
79 <width> <height>[!...]
80
81 Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like:
82 Example : EFI_UNIX_UGA=800 600!1024 768
83
84 EFI_UNIX_PASS_THROUGH =
85 <BaseAddress>;<Bus#>;<Device#>;<Function#>
86
87 Declaring a base address of 0xE0000000 (used for PCI Express devices)
88 and having NT32 talk to a device located at bus 0, device 1, function 0:
89 Example : EFI_UNIX_PASS_THROUGH=E000000;0;1;0
90
91 ---*/
92
93 #include "UnixBusDriver.h"
94 //#include "PciHostBridge.h"
95
96 //
97 // Define GUID for the Unix Bus Driver
98 //
99 static EFI_GUID gUnixBusDriverGuid = {
100 0x419f582, 0x625, 0x4531, {0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc}
101 };
102
103 //
104 // DriverBinding protocol global
105 //
106 EFI_DRIVER_BINDING_PROTOCOL gUnixBusDriverBinding = {
107 UnixBusDriverBindingSupported,
108 UnixBusDriverBindingStart,
109 UnixBusDriverBindingStop,
110 0xa,
111 NULL,
112 NULL
113 };
114
115 #define UNIX_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(UNIX_PCD_ENTRY))
116
117 //
118 // Table to map UNIX Environment variable to the GUID that should be in
119 // device path.
120 //
121 static UNIX_PCD_ENTRY mPcdEnvironment[] = {
122 {PcdToken(PcdUnixConsole), &gEfiUnixConsoleGuid},
123 {PcdToken(PcdUnixUga), &gEfiUnixUgaGuid},
124 {PcdToken(PcdUnixFileSystem), &gEfiUnixFileSystemGuid},
125 {PcdToken(PcdUnixSerialPort), &gEfiUnixSerialPortGuid},
126 {PcdToken(PcdUnixVirtualDisk), &gEfiUnixVirtualDisksGuid},
127 {PcdToken(PcdUnixPhysicalDisk), &gEfiUnixPhysicalDisksGuid},
128 {PcdToken(PcdUnixCpuModel), &gEfiUnixCPUModelGuid},
129 {PcdToken(PcdUnixCpuSpeed), &gEfiUnixCPUSpeedGuid},
130 {PcdToken(PcdUnixMemorySize), &gEfiUnixMemoryGuid}
131 };
132
133 VOID *
134 AllocateMemory (
135 IN UINTN Size
136 )
137 {
138 EFI_STATUS Status;
139 VOID *Buffer;
140
141 Status = gBS->AllocatePool (
142 EfiBootServicesData,
143 Size,
144 (VOID *)&Buffer
145 );
146 if (EFI_ERROR (Status)) {
147 ASSERT (FALSE);
148 return NULL;
149 }
150 return Buffer;
151 }
152
153
154 EFI_STATUS
155 EFIAPI
156 UnixBusDriverBindingSupported (
157 IN EFI_DRIVER_BINDING_PROTOCOL *This,
158 IN EFI_HANDLE ControllerHandle,
159 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
160 )
161 /*++
162
163 Routine Description:
164
165 Arguments:
166
167 Returns:
168
169 None
170
171 --*/
172 // TODO: This - add argument and description to function comment
173 // TODO: ControllerHandle - add argument and description to function comment
174 // TODO: RemainingDevicePath - add argument and description to function comment
175 // TODO: EFI_UNSUPPORTED - add return value to function comment
176 // TODO: EFI_UNSUPPORTED - add return value to function comment
177 // TODO: EFI_SUCCESS - add return value to function comment
178 // TODO: EFI_SUCCESS - add return value to function comment
179 {
180 EFI_STATUS Status;
181 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
182 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
183 UINTN Index;
184
185 //
186 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
187 // it is a legal Device Path Node for this bus driver's children.
188 //
189 if (RemainingDevicePath != NULL) {
190 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||
191 RemainingDevicePath->SubType != HW_VENDOR_DP ||
192 DevicePathNodeLength(RemainingDevicePath) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE)) {
193 return EFI_UNSUPPORTED;
194 }
195
196 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {
197 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {
198 break;
199 }
200 }
201
202 if (Index >= UNIX_PCD_ARRAY_SIZE) {
203 return EFI_UNSUPPORTED;
204 }
205 }
206
207 //
208 // Open the IO Abstraction(s) needed to perform the supported test
209 //
210 Status = gBS->OpenProtocol (
211 ControllerHandle,
212 &gEfiDevicePathProtocolGuid,
213 (VOID **)&ParentDevicePath,
214 This->DriverBindingHandle,
215 ControllerHandle,
216 EFI_OPEN_PROTOCOL_BY_DRIVER
217 );
218 if (Status == EFI_ALREADY_STARTED) {
219 return EFI_SUCCESS;
220 }
221
222 if (EFI_ERROR (Status)) {
223 return Status;
224 }
225
226 gBS->CloseProtocol (
227 ControllerHandle,
228 &gEfiDevicePathProtocolGuid,
229 This->DriverBindingHandle,
230 ControllerHandle
231 );
232
233 Status = gBS->OpenProtocol (
234 ControllerHandle,
235 &gEfiUnixThunkProtocolGuid,
236 (VOID **)&UnixThunk,
237 This->DriverBindingHandle,
238 ControllerHandle,
239 EFI_OPEN_PROTOCOL_BY_DRIVER
240 );
241 if (Status == EFI_ALREADY_STARTED) {
242 return EFI_SUCCESS;
243 }
244
245 if (EFI_ERROR (Status)) {
246 return Status;
247 }
248
249 //
250 // Since we call through UnixThunk we need to make sure it's valid
251 //
252 Status = EFI_SUCCESS;
253 if (UnixThunk->Signature != EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {
254 Status = EFI_UNSUPPORTED;
255 }
256
257 //
258 // Close the I/O Abstraction(s) used to perform the supported test
259 //
260 gBS->CloseProtocol (
261 ControllerHandle,
262 &gEfiUnixThunkProtocolGuid,
263 This->DriverBindingHandle,
264 ControllerHandle
265 );
266
267 return Status;
268 }
269
270 EFI_STATUS
271 EFIAPI
272 UnixBusDriverBindingStart (
273 IN EFI_DRIVER_BINDING_PROTOCOL *This,
274 IN EFI_HANDLE ControllerHandle,
275 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
276 )
277 /*++
278
279 Routine Description:
280
281 Arguments:
282
283 Returns:
284
285 None
286
287 --*/
288 // TODO: This - add argument and description to function comment
289 // TODO: ControllerHandle - add argument and description to function comment
290 // TODO: RemainingDevicePath - add argument and description to function comment
291 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
292 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
293 // TODO: EFI_SUCCESS - add return value to function comment
294 {
295 EFI_STATUS Status;
296 EFI_STATUS InstallStatus;
297 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
298 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
299 UNIX_BUS_DEVICE *UnixBusDevice;
300 UNIX_IO_DEVICE *UnixDevice;
301 UINTN Index;
302 CHAR16 *StartString;
303 CHAR16 *SubString;
304 UINT16 Count;
305 UINTN StringSize;
306 UINT16 ComponentName[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH];
307 UNIX_VENDOR_DEVICE_PATH_NODE *Node;
308 BOOLEAN CreateDevice;
309 CHAR16 *TempStr;
310 CHAR16 *PcdTempStr;
311 UINTN TempStrSize;
312
313 Status = EFI_UNSUPPORTED;
314
315 //
316 // Grab the protocols we need
317 //
318 Status = gBS->OpenProtocol (
319 ControllerHandle,
320 &gEfiDevicePathProtocolGuid,
321 (VOID **)&ParentDevicePath,
322 This->DriverBindingHandle,
323 ControllerHandle,
324 EFI_OPEN_PROTOCOL_BY_DRIVER
325 );
326 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
327 return Status;
328 }
329
330 Status = gBS->OpenProtocol (
331 ControllerHandle,
332 &gEfiUnixThunkProtocolGuid,
333 (VOID **)&UnixThunk,
334 This->DriverBindingHandle,
335 ControllerHandle,
336 EFI_OPEN_PROTOCOL_BY_DRIVER
337 );
338 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
339 return Status;
340 }
341
342 if (Status != EFI_ALREADY_STARTED) {
343 Status = gBS->AllocatePool (
344 EfiBootServicesData,
345 sizeof (UNIX_BUS_DEVICE),
346 (VOID *) &UnixBusDevice
347 );
348 if (EFI_ERROR (Status)) {
349 return Status;
350 }
351
352 UnixBusDevice->Signature = UNIX_BUS_DEVICE_SIGNATURE;
353 UnixBusDevice->ControllerNameTable = NULL;
354
355 AddUnicodeString (
356 "eng",
357 gUnixBusDriverComponentName.SupportedLanguages,
358 &UnixBusDevice->ControllerNameTable,
359 L"Unix Bus Controller"
360 );
361
362 Status = gBS->InstallMultipleProtocolInterfaces (
363 &ControllerHandle,
364 &gUnixBusDriverGuid,
365 UnixBusDevice,
366 NULL
367 );
368 if (EFI_ERROR (Status)) {
369 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);
370 gBS->FreePool (UnixBusDevice);
371 return Status;
372 }
373 }
374
375 //
376 // Loop on the Variable list. Parse each variable to produce a set of handles that
377 // represent virtual hardware devices.
378 //
379 InstallStatus = EFI_NOT_FOUND;
380 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {
381 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);
382 ASSERT (PcdTempStr != NULL);
383
384 TempStrSize = StrLen (PcdTempStr);
385 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);
386 StrCpy (TempStr, PcdTempStr);
387
388 StartString = TempStr;
389
390 //
391 // Parse the envirnment variable into sub strings using '!' as a delimator.
392 // Each substring needs it's own handle to be added to the system. This code
393 // does not understand the sub string. Thats the device drivers job.
394 //
395 Count = 0;
396 while (*StartString != '\0') {
397
398 //
399 // Find the end of the sub string
400 //
401 SubString = StartString;
402 while (*SubString != '\0' && *SubString != '!') {
403 SubString++;
404 }
405
406 if (*SubString == '!') {
407 //
408 // Replace token with '\0' to make sub strings. If this is the end
409 // of the string SubString will already point to NULL.
410 //
411 *SubString = '\0';
412 SubString++;
413 }
414
415 CreateDevice = TRUE;
416 if (RemainingDevicePath != NULL) {
417 CreateDevice = FALSE;
418 Node = (UNIX_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;
419 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&
420 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&
421 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE)
422 ) {
423 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&
424 Node->Instance == Count
425 ) {
426 CreateDevice = TRUE;
427 }
428 }
429 }
430
431 if (CreateDevice) {
432 //
433 // Allocate instance structure, and fill in parent information.
434 //
435 UnixDevice = AllocateMemory (sizeof (UNIX_IO_DEVICE));
436 if (UnixDevice == NULL) {
437 return EFI_OUT_OF_RESOURCES;
438 }
439
440 UnixDevice->Handle = NULL;
441 UnixDevice->ControllerHandle = ControllerHandle;
442 UnixDevice->ParentDevicePath = ParentDevicePath;
443
444 UnixDevice->UnixIo.UnixThunk = UnixThunk;
445
446 //
447 // Plus 2 to account for the NULL at the end of the Unicode string
448 //
449 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);
450 UnixDevice->UnixIo.EnvString = AllocateMemory (StringSize);
451 if (UnixDevice->UnixIo.EnvString != NULL) {
452 CopyMem (UnixDevice->UnixIo.EnvString, StartString, StringSize);
453 }
454
455 UnixDevice->ControllerNameTable = NULL;
456
457 // FIXME: check size
458 StrCpy(ComponentName, UnixDevice->UnixIo.EnvString);
459
460 UnixDevice->DevicePath = UnixBusCreateDevicePath (
461 ParentDevicePath,
462 mPcdEnvironment[Index].DevicePathGuid,
463 Count
464 );
465 if (UnixDevice->DevicePath == NULL) {
466 gBS->FreePool (UnixDevice);
467 return EFI_OUT_OF_RESOURCES;
468 }
469
470 AddUnicodeString (
471 "eng",
472 gUnixBusDriverComponentName.SupportedLanguages,
473 &UnixDevice->ControllerNameTable,
474 ComponentName
475 );
476
477 UnixDevice->UnixIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;
478 UnixDevice->UnixIo.InstanceNumber = Count;
479
480 UnixDevice->Signature = UNIX_IO_DEVICE_SIGNATURE;
481
482 Status = gBS->InstallMultipleProtocolInterfaces (
483 &UnixDevice->Handle,
484 &gEfiDevicePathProtocolGuid,
485 UnixDevice->DevicePath,
486 &gEfiUnixIoProtocolGuid,
487 &UnixDevice->UnixIo,
488 NULL
489 );
490 if (EFI_ERROR (Status)) {
491 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);
492 gBS->FreePool (UnixDevice);
493 } else {
494 //
495 // Open For Child Device
496 //
497 Status = gBS->OpenProtocol (
498 ControllerHandle,
499 &gEfiUnixThunkProtocolGuid,
500 (VOID **)&UnixThunk,
501 This->DriverBindingHandle,
502 UnixDevice->Handle,
503 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
504 );
505 if (!EFI_ERROR (Status)) {
506 InstallStatus = EFI_SUCCESS;
507 }
508 }
509 }
510
511 //
512 // Parse Next sub string. This will point to '\0' if we are at the end.
513 //
514 Count++;
515 StartString = SubString;
516 }
517
518 gBS->FreePool (TempStr);
519 }
520
521 return EFI_SUCCESS;
522 }
523
524
525 EFI_STATUS
526 EFIAPI
527 UnixBusDriverBindingStop (
528 IN EFI_DRIVER_BINDING_PROTOCOL *This,
529 IN EFI_HANDLE ControllerHandle,
530 IN UINTN NumberOfChildren,
531 IN EFI_HANDLE *ChildHandleBuffer
532 )
533 /*++
534
535 Routine Description:
536
537 Arguments:
538
539 Returns:
540
541 None
542
543 --*/
544 // TODO: This - add argument and description to function comment
545 // TODO: ControllerHandle - add argument and description to function comment
546 // TODO: NumberOfChildren - add argument and description to function comment
547 // TODO: ChildHandleBuffer - add argument and description to function comment
548 // TODO: EFI_SUCCESS - add return value to function comment
549 // TODO: EFI_DEVICE_ERROR - add return value to function comment
550 // TODO: EFI_SUCCESS - add return value to function comment
551 {
552 EFI_STATUS Status;
553 UINTN Index;
554 BOOLEAN AllChildrenStopped;
555 EFI_UNIX_IO_PROTOCOL *UnixIo;
556 UNIX_BUS_DEVICE *UnixBusDevice;
557 UNIX_IO_DEVICE *UnixDevice;
558 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
559
560 //
561 // Complete all outstanding transactions to Controller.
562 // Don't allow any new transaction to Controller to be started.
563 //
564
565 if (NumberOfChildren == 0) {
566 //
567 // Close the bus driver
568 //
569 Status = gBS->OpenProtocol (
570 ControllerHandle,
571 &gUnixBusDriverGuid,
572 (VOID **)&UnixBusDevice,
573 This->DriverBindingHandle,
574 ControllerHandle,
575 EFI_OPEN_PROTOCOL_GET_PROTOCOL
576 );
577 if (EFI_ERROR (Status)) {
578 return Status;
579 }
580
581 gBS->UninstallMultipleProtocolInterfaces (
582 ControllerHandle,
583 &gUnixBusDriverGuid,
584 UnixBusDevice,
585 NULL
586 );
587
588 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);
589
590 gBS->FreePool (UnixBusDevice);
591
592 gBS->CloseProtocol (
593 ControllerHandle,
594 &gEfiUnixThunkProtocolGuid,
595 This->DriverBindingHandle,
596 ControllerHandle
597 );
598
599 gBS->CloseProtocol (
600 ControllerHandle,
601 &gEfiDevicePathProtocolGuid,
602 This->DriverBindingHandle,
603 ControllerHandle
604 );
605 return EFI_SUCCESS;
606 }
607
608 AllChildrenStopped = TRUE;
609
610 for (Index = 0; Index < NumberOfChildren; Index++) {
611
612 Status = gBS->OpenProtocol (
613 ChildHandleBuffer[Index],
614 &gEfiUnixIoProtocolGuid,
615 (VOID **)&UnixIo,
616 This->DriverBindingHandle,
617 ControllerHandle,
618 EFI_OPEN_PROTOCOL_GET_PROTOCOL
619 );
620 if (!EFI_ERROR (Status)) {
621
622 UnixDevice = UNIX_IO_DEVICE_FROM_THIS (UnixIo);
623
624 Status = gBS->CloseProtocol (
625 ControllerHandle,
626 &gEfiUnixThunkProtocolGuid,
627 This->DriverBindingHandle,
628 UnixDevice->Handle
629 );
630
631 Status = gBS->UninstallMultipleProtocolInterfaces (
632 UnixDevice->Handle,
633 &gEfiDevicePathProtocolGuid,
634 UnixDevice->DevicePath,
635 &gEfiUnixIoProtocolGuid,
636 &UnixDevice->UnixIo,
637 NULL
638 );
639
640 if (EFI_ERROR (Status)) {
641 gBS->OpenProtocol (
642 ControllerHandle,
643 &gEfiUnixThunkProtocolGuid,
644 (VOID **) &UnixThunk,
645 This->DriverBindingHandle,
646 UnixDevice->Handle,
647 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
648 );
649 } else {
650 //
651 // Close the child handle
652 //
653 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);
654 gBS->FreePool (UnixDevice);
655 }
656 }
657
658 if (EFI_ERROR (Status)) {
659 AllChildrenStopped = FALSE;
660 }
661 }
662
663 if (!AllChildrenStopped) {
664 return EFI_DEVICE_ERROR;
665 }
666
667 return EFI_SUCCESS;
668 }
669
670 EFI_DEVICE_PATH_PROTOCOL *
671 UnixBusCreateDevicePath (
672 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,
673 IN EFI_GUID *Guid,
674 IN UINT16 InstanceNumber
675 )
676 /*++
677
678 Routine Description:
679 Create a device path node using Guid and InstanceNumber and append it to
680 the passed in RootDevicePath
681
682 Arguments:
683 RootDevicePath - Root of the device path to return.
684
685 Guid - GUID to use in vendor device path node.
686
687 InstanceNumber - Instance number to use in the vendor device path. This
688 argument is needed to make sure each device path is unique.
689
690 Returns:
691
692 EFI_DEVICE_PATH_PROTOCOL
693
694 --*/
695 {
696 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath;
697
698 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;
699 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;
700 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (UNIX_VENDOR_DEVICE_PATH_NODE));
701
702 //
703 // The GUID defines the Class
704 //
705 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));
706
707 //
708 // Add an instance number so we can make sure there are no Device Path
709 // duplication.
710 //
711 DevicePath.Instance = InstanceNumber;
712
713 return AppendDevicePathNode (
714 RootDevicePath,
715 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath
716 );
717 }