3 Copyright (c) 2006 - 2009, 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
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 envirnoment variables for the Win 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(PcdUnixFileSystem
), &gEfiUnixFileSystemGuid
},
124 {PcdToken(PcdUnixSerialPort
), &gEfiUnixSerialPortGuid
},
125 {PcdToken(PcdUnixVirtualDisk
), &gEfiUnixVirtualDisksGuid
},
126 {PcdToken(PcdUnixPhysicalDisk
), &gEfiUnixPhysicalDisksGuid
},
127 {PcdToken(PcdUnixCpuModel
), &gEfiUnixCPUModelGuid
},
128 {PcdToken(PcdUnixCpuSpeed
), &gEfiUnixCPUSpeedGuid
},
129 {PcdToken(PcdUnixMemorySize
), &gEfiUnixMemoryGuid
}
140 Status
= gBS
->AllocatePool (
145 if (EFI_ERROR (Status
)) {
155 UnixBusDriverBindingSupported (
156 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
157 IN EFI_HANDLE ControllerHandle
,
158 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
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
180 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
181 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
;
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.
188 if (RemainingDevicePath
!= NULL
) {
190 // Check if RemainingDevicePath is the End of Device Path Node,
191 // if yes, go on checking other conditions
193 if (!IsDevicePathEnd (RemainingDevicePath
)) {
195 // If RemainingDevicePath isn't the End of Device Path Node,
196 // check its validation
198 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
199 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
200 DevicePathNodeLength(RemainingDevicePath
) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE
)) {
201 return EFI_UNSUPPORTED
;
204 for (Index
= 0; Index
< UNIX_PCD_ARRAY_SIZE
; Index
++) {
205 if (CompareGuid (&((VENDOR_DEVICE_PATH
*) RemainingDevicePath
)->Guid
, mPcdEnvironment
[Index
].DevicePathGuid
)) {
210 if (Index
>= UNIX_PCD_ARRAY_SIZE
) {
211 return EFI_UNSUPPORTED
;
217 // Open the IO Abstraction(s) needed to perform the supported test
219 Status
= gBS
->OpenProtocol (
221 &gEfiUnixThunkProtocolGuid
,
223 This
->DriverBindingHandle
,
225 EFI_OPEN_PROTOCOL_BY_DRIVER
227 if (Status
== EFI_ALREADY_STARTED
) {
231 if (EFI_ERROR (Status
)) {
236 // Close the I/O Abstraction(s) used to perform the supported test
240 &gEfiUnixThunkProtocolGuid
,
241 This
->DriverBindingHandle
,
246 // Open the EFI Device Path protocol needed to perform the supported test
248 Status
= gBS
->OpenProtocol (
250 &gEfiDevicePathProtocolGuid
,
251 (VOID
**)&ParentDevicePath
,
252 This
->DriverBindingHandle
,
254 EFI_OPEN_PROTOCOL_BY_DRIVER
256 if (Status
== EFI_ALREADY_STARTED
) {
260 if (EFI_ERROR (Status
)) {
265 // Since we call through UnixThunk we need to make sure it's valid
267 Status
= EFI_SUCCESS
;
268 if (UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
269 Status
= EFI_UNSUPPORTED
;
273 // Close protocol, don't use device path protocol in the Support() function
277 &gEfiDevicePathProtocolGuid
,
278 This
->DriverBindingHandle
,
287 UnixBusDriverBindingStart (
288 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
289 IN EFI_HANDLE ControllerHandle
,
290 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
303 // TODO: This - add argument and description to function comment
304 // TODO: ControllerHandle - add argument and description to function comment
305 // TODO: RemainingDevicePath - add argument and description to function comment
306 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
307 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
308 // TODO: EFI_SUCCESS - add return value to function comment
311 EFI_STATUS InstallStatus
;
312 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
;
313 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
314 UNIX_BUS_DEVICE
*UnixBusDevice
;
315 UNIX_IO_DEVICE
*UnixDevice
;
321 UINT16 ComponentName
[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH
];
322 UNIX_VENDOR_DEVICE_PATH_NODE
*Node
;
323 BOOLEAN CreateDevice
;
328 Status
= EFI_UNSUPPORTED
;
331 // Grab the protocols we need
333 Status
= gBS
->OpenProtocol (
335 &gEfiDevicePathProtocolGuid
,
336 (VOID
**)&ParentDevicePath
,
337 This
->DriverBindingHandle
,
339 EFI_OPEN_PROTOCOL_BY_DRIVER
341 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
345 Status
= gBS
->OpenProtocol (
347 &gEfiUnixThunkProtocolGuid
,
349 This
->DriverBindingHandle
,
351 EFI_OPEN_PROTOCOL_BY_DRIVER
353 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
357 if (Status
!= EFI_ALREADY_STARTED
) {
358 Status
= gBS
->AllocatePool (
360 sizeof (UNIX_BUS_DEVICE
),
361 (VOID
*) &UnixBusDevice
363 if (EFI_ERROR (Status
)) {
367 UnixBusDevice
->Signature
= UNIX_BUS_DEVICE_SIGNATURE
;
368 UnixBusDevice
->ControllerNameTable
= NULL
;
372 gUnixBusDriverComponentName
.SupportedLanguages
,
373 &UnixBusDevice
->ControllerNameTable
,
374 L
"Unix Bus Controller"
377 Status
= gBS
->InstallMultipleProtocolInterfaces (
383 if (EFI_ERROR (Status
)) {
384 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
385 gBS
->FreePool (UnixBusDevice
);
391 // Loop on the Variable list. Parse each variable to produce a set of handles that
392 // represent virtual hardware devices.
394 InstallStatus
= EFI_NOT_FOUND
;
395 for (Index
= 0; Index
< UNIX_PCD_ARRAY_SIZE
; Index
++) {
396 PcdTempStr
= (VOID
*)LibPcdGetPtr (mPcdEnvironment
[Index
].Token
);
397 ASSERT (PcdTempStr
!= NULL
);
399 TempStrSize
= StrLen (PcdTempStr
);
400 TempStr
= AllocateMemory ((TempStrSize
* sizeof (CHAR16
)) + 1);
401 StrCpy (TempStr
, PcdTempStr
);
403 StartString
= TempStr
;
406 // Parse the envirnment variable into sub strings using '!' as a delimator.
407 // Each substring needs it's own handle to be added to the system. This code
408 // does not understand the sub string. Thats the device drivers job.
411 while (*StartString
!= '\0') {
414 // Find the end of the sub string
416 SubString
= StartString
;
417 while (*SubString
!= '\0' && *SubString
!= '!') {
421 if (*SubString
== '!') {
423 // Replace token with '\0' to make sub strings. If this is the end
424 // of the string SubString will already point to NULL.
431 if (RemainingDevicePath
!= NULL
) {
432 CreateDevice
= FALSE
;
434 // Check if RemainingDevicePath is the End of Device Path Node,
435 // if yes, don't create any child device
437 if (!IsDevicePathEnd (RemainingDevicePath
)) {
439 // If RemainingDevicePath isn't the End of Device Path Node,
440 // check its validation
442 Node
= (UNIX_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
443 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
444 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
445 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE
)
447 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, mPcdEnvironment
[Index
].DevicePathGuid
) &&
448 Node
->Instance
== Count
458 // Allocate instance structure, and fill in parent information.
460 UnixDevice
= AllocateMemory (sizeof (UNIX_IO_DEVICE
));
461 if (UnixDevice
== NULL
) {
462 return EFI_OUT_OF_RESOURCES
;
465 UnixDevice
->Handle
= NULL
;
466 UnixDevice
->ControllerHandle
= ControllerHandle
;
467 UnixDevice
->ParentDevicePath
= ParentDevicePath
;
469 UnixDevice
->UnixIo
.UnixThunk
= UnixThunk
;
472 // Plus 2 to account for the NULL at the end of the Unicode string
474 StringSize
= (UINTN
) ((UINT8
*) SubString
- (UINT8
*) StartString
) + sizeof (CHAR16
);
475 UnixDevice
->UnixIo
.EnvString
= AllocateMemory (StringSize
);
476 if (UnixDevice
->UnixIo
.EnvString
!= NULL
) {
477 CopyMem (UnixDevice
->UnixIo
.EnvString
, StartString
, StringSize
);
480 UnixDevice
->ControllerNameTable
= NULL
;
483 StrCpy(ComponentName
, UnixDevice
->UnixIo
.EnvString
);
485 UnixDevice
->DevicePath
= UnixBusCreateDevicePath (
487 mPcdEnvironment
[Index
].DevicePathGuid
,
490 if (UnixDevice
->DevicePath
== NULL
) {
491 gBS
->FreePool (UnixDevice
);
492 return EFI_OUT_OF_RESOURCES
;
497 gUnixBusDriverComponentName
.SupportedLanguages
,
498 &UnixDevice
->ControllerNameTable
,
502 UnixDevice
->UnixIo
.TypeGuid
= mPcdEnvironment
[Index
].DevicePathGuid
;
503 UnixDevice
->UnixIo
.InstanceNumber
= Count
;
505 UnixDevice
->Signature
= UNIX_IO_DEVICE_SIGNATURE
;
507 Status
= gBS
->InstallMultipleProtocolInterfaces (
509 &gEfiDevicePathProtocolGuid
,
510 UnixDevice
->DevicePath
,
511 &gEfiUnixIoProtocolGuid
,
515 if (EFI_ERROR (Status
)) {
516 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
517 gBS
->FreePool (UnixDevice
);
520 // Open For Child Device
522 Status
= gBS
->OpenProtocol (
524 &gEfiUnixThunkProtocolGuid
,
526 This
->DriverBindingHandle
,
528 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
530 if (!EFI_ERROR (Status
)) {
531 InstallStatus
= EFI_SUCCESS
;
537 // Parse Next sub string. This will point to '\0' if we are at the end.
540 StartString
= SubString
;
543 gBS
->FreePool (TempStr
);
552 UnixBusDriverBindingStop (
553 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
554 IN EFI_HANDLE ControllerHandle
,
555 IN UINTN NumberOfChildren
,
556 IN EFI_HANDLE
*ChildHandleBuffer
569 // TODO: This - add argument and description to function comment
570 // TODO: ControllerHandle - add argument and description to function comment
571 // TODO: NumberOfChildren - add argument and description to function comment
572 // TODO: ChildHandleBuffer - add argument and description to function comment
573 // TODO: EFI_SUCCESS - add return value to function comment
574 // TODO: EFI_DEVICE_ERROR - add return value to function comment
575 // TODO: EFI_SUCCESS - add return value to function comment
579 BOOLEAN AllChildrenStopped
;
580 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
581 UNIX_BUS_DEVICE
*UnixBusDevice
;
582 UNIX_IO_DEVICE
*UnixDevice
;
583 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
;
586 // Complete all outstanding transactions to Controller.
587 // Don't allow any new transaction to Controller to be started.
590 if (NumberOfChildren
== 0) {
592 // Close the bus driver
594 Status
= gBS
->OpenProtocol (
597 (VOID
**)&UnixBusDevice
,
598 This
->DriverBindingHandle
,
600 EFI_OPEN_PROTOCOL_GET_PROTOCOL
602 if (EFI_ERROR (Status
)) {
606 gBS
->UninstallMultipleProtocolInterfaces (
613 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
615 gBS
->FreePool (UnixBusDevice
);
619 &gEfiUnixThunkProtocolGuid
,
620 This
->DriverBindingHandle
,
626 &gEfiDevicePathProtocolGuid
,
627 This
->DriverBindingHandle
,
633 AllChildrenStopped
= TRUE
;
635 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
637 Status
= gBS
->OpenProtocol (
638 ChildHandleBuffer
[Index
],
639 &gEfiUnixIoProtocolGuid
,
641 This
->DriverBindingHandle
,
643 EFI_OPEN_PROTOCOL_GET_PROTOCOL
645 if (!EFI_ERROR (Status
)) {
647 UnixDevice
= UNIX_IO_DEVICE_FROM_THIS (UnixIo
);
649 Status
= gBS
->CloseProtocol (
651 &gEfiUnixThunkProtocolGuid
,
652 This
->DriverBindingHandle
,
656 Status
= gBS
->UninstallMultipleProtocolInterfaces (
658 &gEfiDevicePathProtocolGuid
,
659 UnixDevice
->DevicePath
,
660 &gEfiUnixIoProtocolGuid
,
665 if (EFI_ERROR (Status
)) {
668 &gEfiUnixThunkProtocolGuid
,
669 (VOID
**) &UnixThunk
,
670 This
->DriverBindingHandle
,
672 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
676 // Close the child handle
678 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
679 gBS
->FreePool (UnixDevice
);
683 if (EFI_ERROR (Status
)) {
684 AllChildrenStopped
= FALSE
;
688 if (!AllChildrenStopped
) {
689 return EFI_DEVICE_ERROR
;
695 EFI_DEVICE_PATH_PROTOCOL
*
696 UnixBusCreateDevicePath (
697 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
699 IN UINT16 InstanceNumber
704 Create a device path node using Guid and InstanceNumber and append it to
705 the passed in RootDevicePath
708 RootDevicePath - Root of the device path to return.
710 Guid - GUID to use in vendor device path node.
712 InstanceNumber - Instance number to use in the vendor device path. This
713 argument is needed to make sure each device path is unique.
717 EFI_DEVICE_PATH_PROTOCOL
721 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath
;
723 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
724 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
725 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (UNIX_VENDOR_DEVICE_PATH_NODE
));
728 // The GUID defines the Class
730 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
733 // Add an instance number so we can make sure there are no Device Path
736 DevicePath
.Instance
= InstanceNumber
;
738 return AppendDevicePathNode (
740 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath