]> git.proxmox.com Git - mirror_edk2.git/blob - EdkUnixPkg/Dxe/UnixThunk/Bus/UnixBusDriver/UnixBusDriver.c
Change many windows references to unix.
[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 0x10,
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(PcdUnixVirtualDisk), &gEfiUnixVirtualDisksGuid},
126 {PcdToken(PcdUnixPhysicalDisk), &gEfiUnixPhysicalDisksGuid},
127 {PcdToken(PcdUnixCpuModel), &gEfiUnixCPUModelGuid},
128 {PcdToken(PcdUnixCpuSpeed), &gEfiUnixCPUSpeedGuid},
129 {PcdToken(PcdUnixMemorySize), &gEfiUnixMemoryGuid}
130 };
131
132 VOID *
133 AllocateMemory (
134 IN UINTN Size
135 )
136 {
137 EFI_STATUS Status;
138 VOID *Buffer;
139
140 Status = gBS->AllocatePool (
141 EfiBootServicesData,
142 Size,
143 (VOID *)&Buffer
144 );
145 if (EFI_ERROR (Status)) {
146 ASSERT (FALSE);
147 return NULL;
148 }
149 return Buffer;
150 }
151
152
153 EFI_STATUS
154 EFIAPI
155 UnixBusDriverBindingSupported (
156 IN EFI_DRIVER_BINDING_PROTOCOL *This,
157 IN EFI_HANDLE ControllerHandle,
158 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
159 )
160 /*++
161
162 Routine Description:
163
164 Arguments:
165
166 Returns:
167
168 None
169
170 --*/
171 // TODO: This - add argument and description to function comment
172 // TODO: ControllerHandle - add argument and description to function comment
173 // TODO: RemainingDevicePath - add argument and description to function comment
174 // TODO: EFI_UNSUPPORTED - add return value to function comment
175 // TODO: EFI_UNSUPPORTED - add return value to function comment
176 // TODO: EFI_SUCCESS - add return value to function comment
177 // TODO: EFI_SUCCESS - add return value to function comment
178 {
179 EFI_STATUS Status;
180 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
181 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
182 UINTN Index;
183
184 //
185 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
186 // it is a legal Device Path Node for this bus driver's children.
187 //
188 if (RemainingDevicePath != NULL) {
189 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||
190 RemainingDevicePath->SubType != HW_VENDOR_DP ||
191 DevicePathNodeLength(RemainingDevicePath) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE)) {
192 return EFI_UNSUPPORTED;
193 }
194
195 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {
196 if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) {
197 break;
198 }
199 }
200
201 if (Index >= UNIX_PCD_ARRAY_SIZE) {
202 return EFI_UNSUPPORTED;
203 }
204 }
205
206 //
207 // Open the IO Abstraction(s) needed to perform the supported test
208 //
209 Status = gBS->OpenProtocol (
210 ControllerHandle,
211 &gEfiDevicePathProtocolGuid,
212 (VOID **)&ParentDevicePath,
213 This->DriverBindingHandle,
214 ControllerHandle,
215 EFI_OPEN_PROTOCOL_BY_DRIVER
216 );
217 if (Status == EFI_ALREADY_STARTED) {
218 return EFI_SUCCESS;
219 }
220
221 if (EFI_ERROR (Status)) {
222 return Status;
223 }
224
225 gBS->CloseProtocol (
226 ControllerHandle,
227 &gEfiDevicePathProtocolGuid,
228 This->DriverBindingHandle,
229 ControllerHandle
230 );
231
232 Status = gBS->OpenProtocol (
233 ControllerHandle,
234 &gEfiUnixThunkProtocolGuid,
235 (VOID **)&UnixThunk,
236 This->DriverBindingHandle,
237 ControllerHandle,
238 EFI_OPEN_PROTOCOL_BY_DRIVER
239 );
240 if (Status == EFI_ALREADY_STARTED) {
241 return EFI_SUCCESS;
242 }
243
244 if (EFI_ERROR (Status)) {
245 return Status;
246 }
247
248 //
249 // Since we call through UnixThunk we need to make sure it's valid
250 //
251 Status = EFI_SUCCESS;
252 if (UnixThunk->Signature != EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {
253 Status = EFI_UNSUPPORTED;
254 }
255
256 //
257 // Close the I/O Abstraction(s) used to perform the supported test
258 //
259 gBS->CloseProtocol (
260 ControllerHandle,
261 &gEfiUnixThunkProtocolGuid,
262 This->DriverBindingHandle,
263 ControllerHandle
264 );
265
266 return Status;
267 }
268
269 EFI_STATUS
270 EFIAPI
271 UnixBusDriverBindingStart (
272 IN EFI_DRIVER_BINDING_PROTOCOL *This,
273 IN EFI_HANDLE ControllerHandle,
274 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
275 )
276 /*++
277
278 Routine Description:
279
280 Arguments:
281
282 Returns:
283
284 None
285
286 --*/
287 // TODO: This - add argument and description to function comment
288 // TODO: ControllerHandle - add argument and description to function comment
289 // TODO: RemainingDevicePath - add argument and description to function comment
290 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
291 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
292 // TODO: EFI_SUCCESS - add return value to function comment
293 {
294 EFI_STATUS Status;
295 EFI_STATUS InstallStatus;
296 EFI_UNIX_THUNK_PROTOCOL *UnixThunk;
297 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
298 UNIX_BUS_DEVICE *UnixBusDevice;
299 UNIX_IO_DEVICE *UnixDevice;
300 UINTN Index;
301 CHAR16 *StartString;
302 CHAR16 *SubString;
303 UINT16 Count;
304 UINTN StringSize;
305 UINT16 ComponentName[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH];
306 UNIX_VENDOR_DEVICE_PATH_NODE *Node;
307 BOOLEAN CreateDevice;
308 CHAR16 *TempStr;
309 CHAR16 *PcdTempStr;
310 UINTN TempStrSize;
311
312 Status = EFI_UNSUPPORTED;
313
314 //
315 // Grab the protocols we need
316 //
317 Status = gBS->OpenProtocol (
318 ControllerHandle,
319 &gEfiDevicePathProtocolGuid,
320 (VOID **)&ParentDevicePath,
321 This->DriverBindingHandle,
322 ControllerHandle,
323 EFI_OPEN_PROTOCOL_BY_DRIVER
324 );
325 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
326 return Status;
327 }
328
329 Status = gBS->OpenProtocol (
330 ControllerHandle,
331 &gEfiUnixThunkProtocolGuid,
332 (VOID **)&UnixThunk,
333 This->DriverBindingHandle,
334 ControllerHandle,
335 EFI_OPEN_PROTOCOL_BY_DRIVER
336 );
337 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
338 return Status;
339 }
340
341 if (Status != EFI_ALREADY_STARTED) {
342 Status = gBS->AllocatePool (
343 EfiBootServicesData,
344 sizeof (UNIX_BUS_DEVICE),
345 (VOID *) &UnixBusDevice
346 );
347 if (EFI_ERROR (Status)) {
348 return Status;
349 }
350
351 UnixBusDevice->Signature = UNIX_BUS_DEVICE_SIGNATURE;
352 UnixBusDevice->ControllerNameTable = NULL;
353
354 AddUnicodeString (
355 "eng",
356 gUnixBusDriverComponentName.SupportedLanguages,
357 &UnixBusDevice->ControllerNameTable,
358 L"Unix Bus Controller"
359 );
360
361 Status = gBS->InstallMultipleProtocolInterfaces (
362 &ControllerHandle,
363 &gUnixBusDriverGuid,
364 UnixBusDevice,
365 NULL
366 );
367 if (EFI_ERROR (Status)) {
368 FreeUnicodeStringTable (UnixBusDevice->ControllerNameTable);
369 gBS->FreePool (UnixBusDevice);
370 return Status;
371 }
372 }
373
374 //
375 // Loop on the Variable list. Parse each variable to produce a set of handles that
376 // represent virtual hardware devices.
377 //
378 InstallStatus = EFI_NOT_FOUND;
379 for (Index = 0; Index < UNIX_PCD_ARRAY_SIZE; Index++) {
380 PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);
381 ASSERT (PcdTempStr != NULL);
382
383 TempStrSize = StrLen (PcdTempStr);
384 TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1);
385 StrCpy (TempStr, PcdTempStr);
386
387 StartString = TempStr;
388
389 //
390 // Parse the envirnment variable into sub strings using '!' as a delimator.
391 // Each substring needs it's own handle to be added to the system. This code
392 // does not understand the sub string. Thats the device drivers job.
393 //
394 Count = 0;
395 while (*StartString != '\0') {
396
397 //
398 // Find the end of the sub string
399 //
400 SubString = StartString;
401 while (*SubString != '\0' && *SubString != '!') {
402 SubString++;
403 }
404
405 if (*SubString == '!') {
406 //
407 // Replace token with '\0' to make sub strings. If this is the end
408 // of the string SubString will already point to NULL.
409 //
410 *SubString = '\0';
411 SubString++;
412 }
413
414 CreateDevice = TRUE;
415 if (RemainingDevicePath != NULL) {
416 CreateDevice = FALSE;
417 Node = (UNIX_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;
418 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&
419 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&
420 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE)
421 ) {
422 if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&
423 Node->Instance == Count
424 ) {
425 CreateDevice = TRUE;
426 }
427 }
428 }
429
430 if (CreateDevice) {
431
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 }