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
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.
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
22 A ! can be used to seperate multiple instances in a variable. Each
23 instance represents a seperate hardware device.
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
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.
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.
43 EFI_UNIX_VIRTUAL_DISKS =
44 <F | R><O | W>;<block count>;<block size>[!...]
46 EFI_UNIX_PHYSICAL_DISKS =
47 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
49 Virtual Disks: These devices use a file to emulate a hard disk or removable
52 Thus a 20 MB emulated hard drive would look like:
53 EFI_UNIX_VIRTUAL_DISKS=FW;40960;512
55 A 1.44MB emulated floppy with a block size of 1024 would look like:
56 EFI_UNIX_VIRTUAL_DISKS=RW;1440;1024
58 Physical Disks: These devices use UNIX to open a real device in your system
60 Thus a 120 MB floppy would look like:
61 EFI_UNIX_PHYSICAL_DISKS=B:RW;245760;512
63 Thus a standard CD-ROM floppy would look like:
64 EFI_UNIX_PHYSICAL_DISKS=Z:RO;307200;2048
66 EFI_UNIX_FILE_SYSTEM =
67 <directory path>[!...]
69 Mounting the two directories C:\FOO and C:\BAR would look like:
70 EFI_UNIX_FILE_SYSTEM=c:\foo!c:\bar
75 Declaring a text console window with the title "My EFI Console" woild look like:
76 EFI_UNIX_CONSOLE=My EFI Console
79 <width> <height>[!...]
81 Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like:
82 Example : EFI_UNIX_UGA=800 600!1024 768
84 EFI_UNIX_PASS_THROUGH =
85 <BaseAddress>;<Bus#>;<Device#>;<Function#>
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
93 #include "UnixBusDriver.h"
96 // Define GUID for the Unix Bus Driver
98 EFI_GUID gUnixBusDriverGuid
= {
99 0x419f582, 0x625, 0x4531, {0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc}
103 // DriverBinding protocol global
105 EFI_DRIVER_BINDING_PROTOCOL gUnixBusDriverBinding
= {
106 UnixBusDriverBindingSupported
,
107 UnixBusDriverBindingStart
,
108 UnixBusDriverBindingStop
,
114 #define UNIX_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(UNIX_PCD_ENTRY))
117 // Table to map UNIX Environment variable to the GUID that should be in
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
}
142 Status
= gBS
->AllocatePool (
147 if (EFI_ERROR (Status
)) {
157 UnixBusDriverBindingSupported (
158 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
159 IN EFI_HANDLE ControllerHandle
,
160 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
175 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
176 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
;
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.
183 if (RemainingDevicePath
!= NULL
) {
185 // Check if RemainingDevicePath is the End of Device Path Node,
186 // if yes, go on checking other conditions
188 if (!IsDevicePathEnd (RemainingDevicePath
)) {
190 // If RemainingDevicePath isn't the End of Device Path Node,
191 // check its validation
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
;
199 for (Index
= 0; Index
< UNIX_PCD_ARRAY_SIZE
; Index
++) {
200 if (CompareGuid (&((VENDOR_DEVICE_PATH
*) RemainingDevicePath
)->Guid
, mPcdEnvironment
[Index
].DevicePathGuid
)) {
205 if (Index
>= UNIX_PCD_ARRAY_SIZE
) {
206 return EFI_UNSUPPORTED
;
212 // Open the IO Abstraction(s) needed to perform the supported test
214 Status
= gBS
->OpenProtocol (
216 &gEfiUnixThunkProtocolGuid
,
218 This
->DriverBindingHandle
,
220 EFI_OPEN_PROTOCOL_BY_DRIVER
222 if (Status
== EFI_ALREADY_STARTED
) {
226 if (EFI_ERROR (Status
)) {
231 // Close the I/O Abstraction(s) used to perform the supported test
235 &gEfiUnixThunkProtocolGuid
,
236 This
->DriverBindingHandle
,
241 // Open the EFI Device Path protocol needed to perform the supported test
243 Status
= gBS
->OpenProtocol (
245 &gEfiDevicePathProtocolGuid
,
246 (VOID
**)&ParentDevicePath
,
247 This
->DriverBindingHandle
,
249 EFI_OPEN_PROTOCOL_BY_DRIVER
251 if (Status
== EFI_ALREADY_STARTED
) {
255 if (EFI_ERROR (Status
)) {
260 // Since we call through UnixThunk we need to make sure it's valid
262 Status
= EFI_SUCCESS
;
263 if (UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
264 Status
= EFI_UNSUPPORTED
;
268 // Close protocol, don't use device path protocol in the Support() function
272 &gEfiDevicePathProtocolGuid
,
273 This
->DriverBindingHandle
,
282 UnixBusDriverBindingStart (
283 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
284 IN EFI_HANDLE ControllerHandle
,
285 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
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
;
310 UINT16 ComponentName
[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH
];
311 UNIX_VENDOR_DEVICE_PATH_NODE
*Node
;
312 BOOLEAN CreateDevice
;
317 Status
= EFI_UNSUPPORTED
;
320 // Grab the protocols we need
322 Status
= gBS
->OpenProtocol (
324 &gEfiDevicePathProtocolGuid
,
325 (VOID
**)&ParentDevicePath
,
326 This
->DriverBindingHandle
,
328 EFI_OPEN_PROTOCOL_BY_DRIVER
330 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
334 Status
= gBS
->OpenProtocol (
336 &gEfiUnixThunkProtocolGuid
,
338 This
->DriverBindingHandle
,
340 EFI_OPEN_PROTOCOL_BY_DRIVER
342 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
346 if (Status
!= EFI_ALREADY_STARTED
) {
347 Status
= gBS
->AllocatePool (
349 sizeof (UNIX_BUS_DEVICE
),
350 (VOID
*) &UnixBusDevice
352 if (EFI_ERROR (Status
)) {
356 UnixBusDevice
->Signature
= UNIX_BUS_DEVICE_SIGNATURE
;
357 UnixBusDevice
->ControllerNameTable
= NULL
;
361 gUnixBusDriverComponentName
.SupportedLanguages
,
362 &UnixBusDevice
->ControllerNameTable
,
363 L
"Unix Bus Controller"
366 Status
= gBS
->InstallMultipleProtocolInterfaces (
372 if (EFI_ERROR (Status
)) {
373 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
374 gBS
->FreePool (UnixBusDevice
);
380 // Loop on the Variable list. Parse each variable to produce a set of handles that
381 // represent virtual hardware devices.
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
);
388 TempStrSize
= StrLen (PcdTempStr
);
389 TempStr
= AllocateMemory ((TempStrSize
* sizeof (CHAR16
)) + 1);
390 StrCpy (TempStr
, PcdTempStr
);
392 StartString
= TempStr
;
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.
400 while (*StartString
!= '\0') {
403 // Find the end of the sub string
405 SubString
= StartString
;
406 while (*SubString
!= '\0' && *SubString
!= '!') {
410 if (*SubString
== '!') {
412 // Replace token with '\0' to make sub strings. If this is the end
413 // of the string SubString will already point to NULL.
420 if (RemainingDevicePath
!= NULL
) {
421 CreateDevice
= FALSE
;
423 // Check if RemainingDevicePath is the End of Device Path Node,
424 // if yes, don't create any child device
426 if (!IsDevicePathEnd (RemainingDevicePath
)) {
428 // If RemainingDevicePath isn't the End of Device Path Node,
429 // check its validation
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
)
436 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, mPcdEnvironment
[Index
].DevicePathGuid
) &&
437 Node
->Instance
== Count
447 // Allocate instance structure, and fill in parent information.
449 UnixDevice
= AllocateMemory (sizeof (UNIX_IO_DEVICE
));
450 if (UnixDevice
== NULL
) {
451 return EFI_OUT_OF_RESOURCES
;
454 UnixDevice
->Handle
= NULL
;
455 UnixDevice
->ControllerHandle
= ControllerHandle
;
456 UnixDevice
->ParentDevicePath
= ParentDevicePath
;
458 UnixDevice
->UnixIo
.UnixThunk
= UnixThunk
;
461 // Plus 2 to account for the NULL at the end of the Unicode string
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
);
469 UnixDevice
->ControllerNameTable
= NULL
;
472 StrCpy(ComponentName
, UnixDevice
->UnixIo
.EnvString
);
474 UnixDevice
->DevicePath
= UnixBusCreateDevicePath (
476 mPcdEnvironment
[Index
].DevicePathGuid
,
479 if (UnixDevice
->DevicePath
== NULL
) {
480 gBS
->FreePool (UnixDevice
);
481 return EFI_OUT_OF_RESOURCES
;
486 gUnixBusDriverComponentName
.SupportedLanguages
,
487 &UnixDevice
->ControllerNameTable
,
491 UnixDevice
->UnixIo
.TypeGuid
= mPcdEnvironment
[Index
].DevicePathGuid
;
492 UnixDevice
->UnixIo
.InstanceNumber
= Count
;
494 UnixDevice
->Signature
= UNIX_IO_DEVICE_SIGNATURE
;
496 Status
= gBS
->InstallMultipleProtocolInterfaces (
498 &gEfiDevicePathProtocolGuid
,
499 UnixDevice
->DevicePath
,
500 &gEfiUnixIoProtocolGuid
,
504 if (EFI_ERROR (Status
)) {
505 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
506 gBS
->FreePool (UnixDevice
);
509 // Open For Child Device
511 Status
= gBS
->OpenProtocol (
513 &gEfiUnixThunkProtocolGuid
,
515 This
->DriverBindingHandle
,
517 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
519 if (!EFI_ERROR (Status
)) {
520 InstallStatus
= EFI_SUCCESS
;
526 // Parse Next sub string. This will point to '\0' if we are at the end.
529 StartString
= SubString
;
532 gBS
->FreePool (TempStr
);
541 UnixBusDriverBindingStop (
542 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
543 IN EFI_HANDLE ControllerHandle
,
544 IN UINTN NumberOfChildren
,
545 IN EFI_HANDLE
*ChildHandleBuffer
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
;
568 // Complete all outstanding transactions to Controller.
569 // Don't allow any new transaction to Controller to be started.
572 if (NumberOfChildren
== 0) {
574 // Close the bus driver
576 Status
= gBS
->OpenProtocol (
579 (VOID
**)&UnixBusDevice
,
580 This
->DriverBindingHandle
,
582 EFI_OPEN_PROTOCOL_GET_PROTOCOL
584 if (EFI_ERROR (Status
)) {
588 gBS
->UninstallMultipleProtocolInterfaces (
595 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
597 gBS
->FreePool (UnixBusDevice
);
601 &gEfiUnixThunkProtocolGuid
,
602 This
->DriverBindingHandle
,
608 &gEfiDevicePathProtocolGuid
,
609 This
->DriverBindingHandle
,
615 AllChildrenStopped
= TRUE
;
617 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
619 Status
= gBS
->OpenProtocol (
620 ChildHandleBuffer
[Index
],
621 &gEfiUnixIoProtocolGuid
,
623 This
->DriverBindingHandle
,
625 EFI_OPEN_PROTOCOL_GET_PROTOCOL
627 if (!EFI_ERROR (Status
)) {
629 UnixDevice
= UNIX_IO_DEVICE_FROM_THIS (UnixIo
);
631 Status
= gBS
->CloseProtocol (
633 &gEfiUnixThunkProtocolGuid
,
634 This
->DriverBindingHandle
,
638 Status
= gBS
->UninstallMultipleProtocolInterfaces (
640 &gEfiDevicePathProtocolGuid
,
641 UnixDevice
->DevicePath
,
642 &gEfiUnixIoProtocolGuid
,
647 if (EFI_ERROR (Status
)) {
650 &gEfiUnixThunkProtocolGuid
,
651 (VOID
**) &UnixThunk
,
652 This
->DriverBindingHandle
,
654 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
658 // Close the child handle
660 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
661 gBS
->FreePool (UnixDevice
);
665 if (EFI_ERROR (Status
)) {
666 AllChildrenStopped
= FALSE
;
670 if (!AllChildrenStopped
) {
671 return EFI_DEVICE_ERROR
;
677 EFI_DEVICE_PATH_PROTOCOL
*
678 UnixBusCreateDevicePath (
679 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
681 IN UINT16 InstanceNumber
686 Create a device path node using Guid and InstanceNumber and append it to
687 the passed in RootDevicePath
690 RootDevicePath - Root of the device path to return.
692 Guid - GUID to use in vendor device path node.
694 InstanceNumber - Instance number to use in the vendor device path. This
695 argument is needed to make sure each device path is unique.
699 EFI_DEVICE_PATH_PROTOCOL
703 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath
;
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
));
710 // The GUID defines the Class
712 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
715 // Add an instance number so we can make sure there are no Device Path
718 DevicePath
.Instance
= InstanceNumber
;
720 return AppendDevicePathNode (
722 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath