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
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 static 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 static 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
) {
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
;
195 for (Index
= 0; Index
< UNIX_PCD_ARRAY_SIZE
; Index
++) {
196 if (CompareGuid (&((VENDOR_DEVICE_PATH
*) RemainingDevicePath
)->Guid
, mPcdEnvironment
[Index
].DevicePathGuid
)) {
201 if (Index
>= UNIX_PCD_ARRAY_SIZE
) {
202 return EFI_UNSUPPORTED
;
207 // Open the IO Abstraction(s) needed to perform the supported test
209 Status
= gBS
->OpenProtocol (
211 &gEfiDevicePathProtocolGuid
,
212 (VOID
**)&ParentDevicePath
,
213 This
->DriverBindingHandle
,
215 EFI_OPEN_PROTOCOL_BY_DRIVER
217 if (Status
== EFI_ALREADY_STARTED
) {
221 if (EFI_ERROR (Status
)) {
227 &gEfiDevicePathProtocolGuid
,
228 This
->DriverBindingHandle
,
232 Status
= gBS
->OpenProtocol (
234 &gEfiUnixThunkProtocolGuid
,
236 This
->DriverBindingHandle
,
238 EFI_OPEN_PROTOCOL_BY_DRIVER
240 if (Status
== EFI_ALREADY_STARTED
) {
244 if (EFI_ERROR (Status
)) {
249 // Since we call through UnixThunk we need to make sure it's valid
251 Status
= EFI_SUCCESS
;
252 if (UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
253 Status
= EFI_UNSUPPORTED
;
257 // Close the I/O Abstraction(s) used to perform the supported test
261 &gEfiUnixThunkProtocolGuid
,
262 This
->DriverBindingHandle
,
271 UnixBusDriverBindingStart (
272 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
273 IN EFI_HANDLE ControllerHandle
,
274 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
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
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
;
305 UINT16 ComponentName
[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH
];
306 UNIX_VENDOR_DEVICE_PATH_NODE
*Node
;
307 BOOLEAN CreateDevice
;
312 Status
= EFI_UNSUPPORTED
;
315 // Grab the protocols we need
317 Status
= gBS
->OpenProtocol (
319 &gEfiDevicePathProtocolGuid
,
320 (VOID
**)&ParentDevicePath
,
321 This
->DriverBindingHandle
,
323 EFI_OPEN_PROTOCOL_BY_DRIVER
325 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
329 Status
= gBS
->OpenProtocol (
331 &gEfiUnixThunkProtocolGuid
,
333 This
->DriverBindingHandle
,
335 EFI_OPEN_PROTOCOL_BY_DRIVER
337 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
341 if (Status
!= EFI_ALREADY_STARTED
) {
342 Status
= gBS
->AllocatePool (
344 sizeof (UNIX_BUS_DEVICE
),
345 (VOID
*) &UnixBusDevice
347 if (EFI_ERROR (Status
)) {
351 UnixBusDevice
->Signature
= UNIX_BUS_DEVICE_SIGNATURE
;
352 UnixBusDevice
->ControllerNameTable
= NULL
;
356 gUnixBusDriverComponentName
.SupportedLanguages
,
357 &UnixBusDevice
->ControllerNameTable
,
358 L
"Unix Bus Controller"
361 Status
= gBS
->InstallMultipleProtocolInterfaces (
367 if (EFI_ERROR (Status
)) {
368 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
369 gBS
->FreePool (UnixBusDevice
);
375 // Loop on the Variable list. Parse each variable to produce a set of handles that
376 // represent virtual hardware devices.
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
);
383 TempStrSize
= StrLen (PcdTempStr
);
384 TempStr
= AllocateMemory ((TempStrSize
* sizeof (CHAR16
)) + 1);
385 StrCpy (TempStr
, PcdTempStr
);
387 StartString
= TempStr
;
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.
395 while (*StartString
!= '\0') {
398 // Find the end of the sub string
400 SubString
= StartString
;
401 while (*SubString
!= '\0' && *SubString
!= '!') {
405 if (*SubString
== '!') {
407 // Replace token with '\0' to make sub strings. If this is the end
408 // of the string SubString will already point to NULL.
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
)
422 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, mPcdEnvironment
[Index
].DevicePathGuid
) &&
423 Node
->Instance
== Count
432 // Allocate instance structure, and fill in parent information.
434 UnixDevice
= AllocateMemory (sizeof (UNIX_IO_DEVICE
));
435 if (UnixDevice
== NULL
) {
436 return EFI_OUT_OF_RESOURCES
;
439 UnixDevice
->Handle
= NULL
;
440 UnixDevice
->ControllerHandle
= ControllerHandle
;
441 UnixDevice
->ParentDevicePath
= ParentDevicePath
;
443 UnixDevice
->UnixIo
.UnixThunk
= UnixThunk
;
446 // Plus 2 to account for the NULL at the end of the Unicode string
448 StringSize
= (UINTN
) ((UINT8
*) SubString
- (UINT8
*) StartString
) + sizeof (CHAR16
);
449 UnixDevice
->UnixIo
.EnvString
= AllocateMemory (StringSize
);
450 if (UnixDevice
->UnixIo
.EnvString
!= NULL
) {
451 CopyMem (UnixDevice
->UnixIo
.EnvString
, StartString
, StringSize
);
454 UnixDevice
->ControllerNameTable
= NULL
;
457 StrCpy(ComponentName
, UnixDevice
->UnixIo
.EnvString
);
459 UnixDevice
->DevicePath
= UnixBusCreateDevicePath (
461 mPcdEnvironment
[Index
].DevicePathGuid
,
464 if (UnixDevice
->DevicePath
== NULL
) {
465 gBS
->FreePool (UnixDevice
);
466 return EFI_OUT_OF_RESOURCES
;
471 gUnixBusDriverComponentName
.SupportedLanguages
,
472 &UnixDevice
->ControllerNameTable
,
476 UnixDevice
->UnixIo
.TypeGuid
= mPcdEnvironment
[Index
].DevicePathGuid
;
477 UnixDevice
->UnixIo
.InstanceNumber
= Count
;
479 UnixDevice
->Signature
= UNIX_IO_DEVICE_SIGNATURE
;
481 Status
= gBS
->InstallMultipleProtocolInterfaces (
483 &gEfiDevicePathProtocolGuid
,
484 UnixDevice
->DevicePath
,
485 &gEfiUnixIoProtocolGuid
,
489 if (EFI_ERROR (Status
)) {
490 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
491 gBS
->FreePool (UnixDevice
);
494 // Open For Child Device
496 Status
= gBS
->OpenProtocol (
498 &gEfiUnixThunkProtocolGuid
,
500 This
->DriverBindingHandle
,
502 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
504 if (!EFI_ERROR (Status
)) {
505 InstallStatus
= EFI_SUCCESS
;
511 // Parse Next sub string. This will point to '\0' if we are at the end.
514 StartString
= SubString
;
517 gBS
->FreePool (TempStr
);
526 UnixBusDriverBindingStop (
527 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
528 IN EFI_HANDLE ControllerHandle
,
529 IN UINTN NumberOfChildren
,
530 IN EFI_HANDLE
*ChildHandleBuffer
543 // TODO: This - add argument and description to function comment
544 // TODO: ControllerHandle - add argument and description to function comment
545 // TODO: NumberOfChildren - add argument and description to function comment
546 // TODO: ChildHandleBuffer - add argument and description to function comment
547 // TODO: EFI_SUCCESS - add return value to function comment
548 // TODO: EFI_DEVICE_ERROR - add return value to function comment
549 // TODO: EFI_SUCCESS - add return value to function comment
553 BOOLEAN AllChildrenStopped
;
554 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
555 UNIX_BUS_DEVICE
*UnixBusDevice
;
556 UNIX_IO_DEVICE
*UnixDevice
;
557 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
;
560 // Complete all outstanding transactions to Controller.
561 // Don't allow any new transaction to Controller to be started.
564 if (NumberOfChildren
== 0) {
566 // Close the bus driver
568 Status
= gBS
->OpenProtocol (
571 (VOID
**)&UnixBusDevice
,
572 This
->DriverBindingHandle
,
574 EFI_OPEN_PROTOCOL_GET_PROTOCOL
576 if (EFI_ERROR (Status
)) {
580 gBS
->UninstallMultipleProtocolInterfaces (
587 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
589 gBS
->FreePool (UnixBusDevice
);
593 &gEfiUnixThunkProtocolGuid
,
594 This
->DriverBindingHandle
,
600 &gEfiDevicePathProtocolGuid
,
601 This
->DriverBindingHandle
,
607 AllChildrenStopped
= TRUE
;
609 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
611 Status
= gBS
->OpenProtocol (
612 ChildHandleBuffer
[Index
],
613 &gEfiUnixIoProtocolGuid
,
615 This
->DriverBindingHandle
,
617 EFI_OPEN_PROTOCOL_GET_PROTOCOL
619 if (!EFI_ERROR (Status
)) {
621 UnixDevice
= UNIX_IO_DEVICE_FROM_THIS (UnixIo
);
623 Status
= gBS
->CloseProtocol (
625 &gEfiUnixThunkProtocolGuid
,
626 This
->DriverBindingHandle
,
630 Status
= gBS
->UninstallMultipleProtocolInterfaces (
632 &gEfiDevicePathProtocolGuid
,
633 UnixDevice
->DevicePath
,
634 &gEfiUnixIoProtocolGuid
,
639 if (EFI_ERROR (Status
)) {
642 &gEfiUnixThunkProtocolGuid
,
643 (VOID
**) &UnixThunk
,
644 This
->DriverBindingHandle
,
646 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
650 // Close the child handle
652 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
653 gBS
->FreePool (UnixDevice
);
657 if (EFI_ERROR (Status
)) {
658 AllChildrenStopped
= FALSE
;
662 if (!AllChildrenStopped
) {
663 return EFI_DEVICE_ERROR
;
669 EFI_DEVICE_PATH_PROTOCOL
*
670 UnixBusCreateDevicePath (
671 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
673 IN UINT16 InstanceNumber
678 Create a device path node using Guid and InstanceNumber and append it to
679 the passed in RootDevicePath
682 RootDevicePath - Root of the device path to return.
684 Guid - GUID to use in vendor device path node.
686 InstanceNumber - Instance number to use in the vendor device path. This
687 argument is needed to make sure each device path is unique.
691 EFI_DEVICE_PATH_PROTOCOL
695 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath
;
697 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
698 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
699 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (UNIX_VENDOR_DEVICE_PATH_NODE
));
702 // The GUID defines the Class
704 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
707 // Add an instance number so we can make sure there are no Device Path
710 DevicePath
.Instance
= InstanceNumber
;
712 return AppendDevicePathNode (
714 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath