]> git.proxmox.com Git - mirror_edk2.git/blob - UnixPkg/UnixBusDriverDxe/UnixBusDriver.c
Fix issue with fixing tabs.
[mirror_edk2.git] / UnixPkg / UnixBusDriverDxe / UnixBusDriver.c
1 /*+++
2
3 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
4 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 environment variables for the 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
95 //
96 // Define GUID for the Unix Bus Driver
97 //
98 EFI_GUID gUnixBusDriverGuid = {
99 0x419f582, 0x625, 0x4531, {0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc}
100 };
101
102 //
103 // DriverBinding protocol global
104 //
105 EFI_DRIVER_BINDING_PROTOCOL gUnixBusDriverBinding = {
106 UnixBusDriverBindingSupported,
107 UnixBusDriverBindingStart,
108 UnixBusDriverBindingStop,
109 0xa,
110 NULL,
111 NULL
112 };
113
114 #define UNIX_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(UNIX_PCD_ENTRY))
115
116 //
117 // Table to map UNIX Environment variable to the GUID that should be in
118 // device path.
119 //
120 UNIX_PCD_ENTRY mPcdEnvironment[] = {
121 {PcdToken(PcdUnixConsole), &gEfiUnixConsoleGuid},
122 {PcdToken(PcdUnixUga), &gEfiUnixUgaGuid},
123 {PcdToken(PcdUnixGop), &gEfiUnixGopGuid},
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 {PcdToken(PcdUnixNetworkInterface), &gEfiUnixNetworkGuid}
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 UnixBusDriverBindingSupported (
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 {
174 EFI_STATUS Status;
175 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
176 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
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 //
185 // Check if RemainingDevicePath is the End of Device Path Node,
186 // if yes, go on checking other conditions
187 //
188 if (!IsDevicePathEnd (RemainingDevicePath)) {
189 //
190 // If RemainingDevicePath isn't the End of Device Path Node,
191 // check its validation
192 //
193 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||
194 RemainingDevicePath->SubType != HW_VENDOR_DP ||
195 DevicePathNodeLength(RemainingDevicePath) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE)) {
196 return EFI_UNSUPPORTED;
197 }
198
199 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {
200 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {
201 break;
202 }
203 }
204
205 if (Index >= UNIX_PCD_ARRAY_SIZE) {
206 return EFI_UNSUPPORTED;
207 }
208 }
209 }
210
211 //
212 // Open the IO Abstraction(s) needed to perform the supported test
213 //
214 Status = gBS->OpenProtocol (
215 ControllerHandle,
216 &gEfiUnixThunkProtocolGuid,
217 (VOID **)&UnixThunk,
218 This->DriverBindingHandle,
219 ControllerHandle,
220 EFI_OPEN_PROTOCOL_BY_DRIVER
221 );
222 if (Status == EFI_ALREADY_STARTED) {
223 return EFI_SUCCESS;
224 }
225
226 if (EFI_ERROR (Status)) {
227 return Status;
228 }
229
230 //
231 // Close the I/O Abstraction(s) used to perform the supported test
232 //
233 gBS->CloseProtocol (
234 ControllerHandle,
235 &gEfiUnixThunkProtocolGuid,
236 This->DriverBindingHandle,
237 ControllerHandle
238 );
239
240 //
241 // Open the EFI Device Path protocol needed to perform the supported test
242 //
243 Status = gBS->OpenProtocol (
244 ControllerHandle,
245 &gEfiDevicePathProtocolGuid,
246 (VOID **)&ParentDevicePath,
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 UnixThunk we need to make sure it's valid
261 //
262 Status = EFI_SUCCESS;
263 if (UnixThunk->Signature != EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {
264 Status = EFI_UNSUPPORTED;
265 }
266
267 //
268 // Close protocol, don't use device path protocol in the Support() function
269 //
270 gBS->CloseProtocol (
271 ControllerHandle,
272 &gEfiDevicePathProtocolGuid,
273 This->DriverBindingHandle,
274 ControllerHandle
275 );
276
277 return Status;
278 }
279
280 EFI_STATUS
281 EFIAPI
282 UnixBusDriverBindingStart (
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 {
299 EFI_STATUS Status;
300 EFI_STATUS InstallStatus;
301 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
302 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
303 UNIX_BUS_DEVICE *UnixBusDevice;
304 UNIX_IO_DEVICE *UnixDevice;
305 UINTN Index;
306 CHAR16 *StartString;
307 CHAR16 *SubString;
308 UINT16 Count;
309 UINTN StringSize;
310 UINT16 ComponentName[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH];
311 UNIX_VENDOR_DEVICE_PATH_NODE *Node;
312 BOOLEAN CreateDevice;
313 CHAR16 *TempStr;
314 CHAR16 *PcdTempStr;
315 UINTN TempStrSize;
316
317 Status = EFI_UNSUPPORTED;
318
319 //
320 // Grab the protocols we need
321 //
322 Status = gBS->OpenProtocol (
323 ControllerHandle,
324 &gEfiDevicePathProtocolGuid,
325 (VOID **)&ParentDevicePath,
326 This->DriverBindingHandle,
327 ControllerHandle,
328 EFI_OPEN_PROTOCOL_BY_DRIVER
329 );
330 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
331 return Status;
332 }
333
334 Status = gBS->OpenProtocol (
335 ControllerHandle,
336 &gEfiUnixThunkProtocolGuid,
337 (VOID **)&UnixThunk,
338 This->DriverBindingHandle,
339 ControllerHandle,
340 EFI_OPEN_PROTOCOL_BY_DRIVER
341 );
342 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
343 return Status;
344 }
345
346 if (Status != EFI_ALREADY_STARTED) {
347 Status = gBS->AllocatePool (
348 EfiBootServicesData,
349 sizeof (UNIX_BUS_DEVICE),
350 (VOID *) &UnixBusDevice
351 );
352 if (EFI_ERROR (Status)) {
353 return Status;
354 }
355
356 UnixBusDevice->Signature = UNIX_BUS_DEVICE_SIGNATURE;
357 UnixBusDevice->ControllerNameTable = NULL;
358
359 AddUnicodeString (
360 "eng",
361 gUnixBusDriverComponentName.SupportedLanguages,
362 &UnixBusDevice->ControllerNameTable,
363 L"Unix Bus Controller"
364 );
365
366 Status = gBS->InstallMultipleProtocolInterfaces (
367 &ControllerHandle,
368 &gUnixBusDriverGuid,
369 UnixBusDevice,
370 NULL
371 );
372 if (EFI_ERROR (Status)) {
373 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);
374 gBS->FreePool (UnixBusDevice);
375 return Status;
376 }
377 }
378
379 //
380 // Loop on the Variable list. Parse each variable to produce a set of handles that
381 // represent virtual hardware devices.
382 //
383 InstallStatus = EFI_NOT_FOUND;
384 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {
385 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);
386 ASSERT (PcdTempStr != NULL);
387
388 TempStrSize = StrLen (PcdTempStr);
389 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);
390 StrCpy (TempStr, PcdTempStr);
391
392 StartString = TempStr;
393
394 //
395 // Parse the environment variable into sub strings using '!' as a delimator.
396 // Each substring needs it's own handle to be added to the system. This code
397 // does not understand the sub string. Thats the device drivers job.
398 //
399 Count = 0;
400 while (*StartString != '\0') {
401
402 //
403 // Find the end of the sub string
404 //
405 SubString = StartString;
406 while (*SubString != '\0' && *SubString != '!') {
407 SubString++;
408 }
409
410 if (*SubString == '!') {
411 //
412 // Replace token with '\0' to make sub strings. If this is the end
413 // of the string SubString will already point to NULL.
414 //
415 *SubString = '\0';
416 SubString++;
417 }
418
419 CreateDevice = TRUE;
420 if (RemainingDevicePath != NULL) {
421 CreateDevice = FALSE;
422 //
423 // Check if RemainingDevicePath is the End of Device Path Node,
424 // if yes, don't create any child device
425 //
426 if (!IsDevicePathEnd (RemainingDevicePath)) {
427 //
428 // If RemainingDevicePath isn't the End of Device Path Node,
429 // check its validation
430 //
431 Node = (UNIX_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;
432 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&
433 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&
434 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE)
435 ) {
436 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&
437 Node->Instance == Count
438 ) {
439 CreateDevice = TRUE;
440 }
441 }
442 }
443 }
444
445 if (CreateDevice) {
446 //
447 // Allocate instance structure, and fill in parent information.
448 //
449 UnixDevice = AllocateMemory (sizeof (UNIX_IO_DEVICE));
450 if (UnixDevice == NULL) {
451 return EFI_OUT_OF_RESOURCES;
452 }
453
454 UnixDevice->Handle = NULL;
455 UnixDevice->ControllerHandle = ControllerHandle;
456 UnixDevice->ParentDevicePath = ParentDevicePath;
457
458 UnixDevice->UnixIo.UnixThunk = UnixThunk;
459
460 //
461 // Plus 2 to account for the NULL at the end of the Unicode string
462 //
463 StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);
464 UnixDevice->UnixIo.EnvString = AllocateMemory (StringSize);
465 if (UnixDevice->UnixIo.EnvString != NULL) {
466 CopyMem (UnixDevice->UnixIo.EnvString, StartString, StringSize);
467 }
468
469 UnixDevice->ControllerNameTable = NULL;
470
471 // FIXME: check size
472 StrCpy(ComponentName, UnixDevice->UnixIo.EnvString);
473
474 UnixDevice->DevicePath = UnixBusCreateDevicePath (
475 ParentDevicePath,
476 mPcdEnvironment[Index].DevicePathGuid,
477 Count
478 );
479 if (UnixDevice->DevicePath == NULL) {
480 gBS->FreePool (UnixDevice);
481 return EFI_OUT_OF_RESOURCES;
482 }
483
484 AddUnicodeString (
485 "eng",
486 gUnixBusDriverComponentName.SupportedLanguages,
487 &UnixDevice->ControllerNameTable,
488 ComponentName
489 );
490
491 UnixDevice->UnixIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid;
492 UnixDevice->UnixIo.InstanceNumber = Count;
493
494 UnixDevice->Signature = UNIX_IO_DEVICE_SIGNATURE;
495
496 Status = gBS->InstallMultipleProtocolInterfaces (
497 &UnixDevice->Handle,
498 &gEfiDevicePathProtocolGuid,
499 UnixDevice->DevicePath,
500 &gEfiUnixIoProtocolGuid,
501 &UnixDevice->UnixIo,
502 NULL
503 );
504 if (EFI_ERROR (Status)) {
505 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);
506 gBS->FreePool (UnixDevice);
507 } else {
508 //
509 // Open For Child Device
510 //
511 Status = gBS->OpenProtocol (
512 ControllerHandle,
513 &gEfiUnixThunkProtocolGuid,
514 (VOID **)&UnixThunk,
515 This->DriverBindingHandle,
516 UnixDevice->Handle,
517 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
518 );
519 if (!EFI_ERROR (Status)) {
520 InstallStatus = EFI_SUCCESS;
521 }
522 }
523 }
524
525 //
526 // Parse Next sub string. This will point to '\0' if we are at the end.
527 //
528 Count++;
529 StartString = SubString;
530 }
531
532 gBS->FreePool (TempStr);
533 }
534
535 return EFI_SUCCESS;
536 }
537
538
539 EFI_STATUS
540 EFIAPI
541 UnixBusDriverBindingStop (
542 IN EFI_DRIVER_BINDING_PROTOCOL *This,
543 IN EFI_HANDLE ControllerHandle,
544 IN UINTN NumberOfChildren,
545 IN EFI_HANDLE *ChildHandleBuffer
546 )
547 /*++
548
549 Routine Description:
550
551 Arguments:
552
553 Returns:
554
555 None
556
557 --*/
558 {
559 EFI_STATUS Status;
560 UINTN Index;
561 BOOLEAN AllChildrenStopped;
562 EFI_UNIX_IO_PROTOCOL *UnixIo;
563 UNIX_BUS_DEVICE *UnixBusDevice;
564 UNIX_IO_DEVICE *UnixDevice;
565 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
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 &gUnixBusDriverGuid,
579 (VOID **)&UnixBusDevice,
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 &gUnixBusDriverGuid,
591 UnixBusDevice,
592 NULL
593 );
594
595 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);
596
597 gBS->FreePool (UnixBusDevice);
598
599 gBS->CloseProtocol (
600 ControllerHandle,
601 &gEfiUnixThunkProtocolGuid,
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 &gEfiUnixIoProtocolGuid,
622 (VOID **)&UnixIo,
623 This->DriverBindingHandle,
624 ControllerHandle,
625 EFI_OPEN_PROTOCOL_GET_PROTOCOL
626 );
627 if (!EFI_ERROR (Status)) {
628
629 UnixDevice = UNIX_IO_DEVICE_FROM_THIS (UnixIo);
630
631 Status = gBS->CloseProtocol (
632 ControllerHandle,
633 &gEfiUnixThunkProtocolGuid,
634 This->DriverBindingHandle,
635 UnixDevice->Handle
636 );
637
638 Status = gBS->UninstallMultipleProtocolInterfaces (
639 UnixDevice->Handle,
640 &gEfiDevicePathProtocolGuid,
641 UnixDevice->DevicePath,
642 &gEfiUnixIoProtocolGuid,
643 &UnixDevice->UnixIo,
644 NULL
645 );
646
647 if (EFI_ERROR (Status)) {
648 gBS->OpenProtocol (
649 ControllerHandle,
650 &gEfiUnixThunkProtocolGuid,
651 (VOID **) &UnixThunk,
652 This->DriverBindingHandle,
653 UnixDevice->Handle,
654 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
655 );
656 } else {
657 //
658 // Close the child handle
659 //
660 FreeUnicodeStringTable (UnixDevice->ControllerNameTable);
661 gBS->FreePool (UnixDevice);
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 UnixBusCreateDevicePath (
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 UNIX_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 (UNIX_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 }