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"
94 //#include "PciHostBridge.h"
97 // Define GUID for the Unix Bus Driver
99 static EFI_GUID gUnixBusDriverGuid
= {
100 0x419f582, 0x625, 0x4531, {0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc}
104 // DriverBinding protocol global
106 EFI_DRIVER_BINDING_PROTOCOL gUnixBusDriverBinding
= {
107 UnixBusDriverBindingSupported
,
108 UnixBusDriverBindingStart
,
109 UnixBusDriverBindingStop
,
115 #define UNIX_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(UNIX_PCD_ENTRY))
118 // Table to map UNIX Environment variable to the GUID that should be in
121 static UNIX_PCD_ENTRY mPcdEnvironment
[] = {
122 {PcdToken(PcdUnixConsole
), &gEfiUnixConsoleGuid
},
123 {PcdToken(PcdUnixUga
), &gEfiUnixUgaGuid
},
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
}
141 Status
= gBS
->AllocatePool (
146 if (EFI_ERROR (Status
)) {
156 UnixBusDriverBindingSupported (
157 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
158 IN EFI_HANDLE ControllerHandle
,
159 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
172 // TODO: This - add argument and description to function comment
173 // TODO: ControllerHandle - add argument and description to function comment
174 // TODO: RemainingDevicePath - add argument and description to function comment
175 // TODO: EFI_UNSUPPORTED - add return value to function comment
176 // TODO: EFI_UNSUPPORTED - add return value to function comment
177 // TODO: EFI_SUCCESS - add return value to function comment
178 // TODO: EFI_SUCCESS - add return value to function comment
181 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
182 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
;
186 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
187 // it is a legal Device Path Node for this bus driver's children.
189 if (RemainingDevicePath
!= NULL
) {
190 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
191 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
192 DevicePathNodeLength(RemainingDevicePath
) != sizeof(UNIX_VENDOR_DEVICE_PATH_NODE
)) {
193 return EFI_UNSUPPORTED
;
196 for (Index
= 0; Index
< UNIX_PCD_ARRAY_SIZE
; Index
++) {
197 if (CompareGuid (&((VENDOR_DEVICE_PATH
*) RemainingDevicePath
)->Guid
, mPcdEnvironment
[Index
].DevicePathGuid
)) {
202 if (Index
>= UNIX_PCD_ARRAY_SIZE
) {
203 return EFI_UNSUPPORTED
;
208 // Open the IO Abstraction(s) needed to perform the supported test
210 Status
= gBS
->OpenProtocol (
212 &gEfiDevicePathProtocolGuid
,
213 (VOID
**)&ParentDevicePath
,
214 This
->DriverBindingHandle
,
216 EFI_OPEN_PROTOCOL_BY_DRIVER
218 if (Status
== EFI_ALREADY_STARTED
) {
222 if (EFI_ERROR (Status
)) {
228 &gEfiDevicePathProtocolGuid
,
229 This
->DriverBindingHandle
,
233 Status
= gBS
->OpenProtocol (
235 &gEfiUnixThunkProtocolGuid
,
237 This
->DriverBindingHandle
,
239 EFI_OPEN_PROTOCOL_BY_DRIVER
241 if (Status
== EFI_ALREADY_STARTED
) {
245 if (EFI_ERROR (Status
)) {
250 // Since we call through UnixThunk we need to make sure it's valid
252 Status
= EFI_SUCCESS
;
253 if (UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
254 Status
= EFI_UNSUPPORTED
;
258 // Close the I/O Abstraction(s) used to perform the supported test
262 &gEfiUnixThunkProtocolGuid
,
263 This
->DriverBindingHandle
,
272 UnixBusDriverBindingStart (
273 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
274 IN EFI_HANDLE ControllerHandle
,
275 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
288 // TODO: This - add argument and description to function comment
289 // TODO: ControllerHandle - add argument and description to function comment
290 // TODO: RemainingDevicePath - add argument and description to function comment
291 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
292 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
293 // TODO: EFI_SUCCESS - add return value to function comment
296 EFI_STATUS InstallStatus
;
297 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
;
298 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
299 UNIX_BUS_DEVICE
*UnixBusDevice
;
300 UNIX_IO_DEVICE
*UnixDevice
;
306 UINT16 ComponentName
[MAX_UNIX_ENVIRNMENT_VARIABLE_LENGTH
];
307 UNIX_VENDOR_DEVICE_PATH_NODE
*Node
;
308 BOOLEAN CreateDevice
;
313 Status
= EFI_UNSUPPORTED
;
316 // Grab the protocols we need
318 Status
= gBS
->OpenProtocol (
320 &gEfiDevicePathProtocolGuid
,
321 (VOID
**)&ParentDevicePath
,
322 This
->DriverBindingHandle
,
324 EFI_OPEN_PROTOCOL_BY_DRIVER
326 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
330 Status
= gBS
->OpenProtocol (
332 &gEfiUnixThunkProtocolGuid
,
334 This
->DriverBindingHandle
,
336 EFI_OPEN_PROTOCOL_BY_DRIVER
338 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
342 if (Status
!= EFI_ALREADY_STARTED
) {
343 Status
= gBS
->AllocatePool (
345 sizeof (UNIX_BUS_DEVICE
),
346 (VOID
*) &UnixBusDevice
348 if (EFI_ERROR (Status
)) {
352 UnixBusDevice
->Signature
= UNIX_BUS_DEVICE_SIGNATURE
;
353 UnixBusDevice
->ControllerNameTable
= NULL
;
357 gUnixBusDriverComponentName
.SupportedLanguages
,
358 &UnixBusDevice
->ControllerNameTable
,
359 L
"Unix Bus Controller"
362 Status
= gBS
->InstallMultipleProtocolInterfaces (
368 if (EFI_ERROR (Status
)) {
369 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
370 gBS
->FreePool (UnixBusDevice
);
376 // Loop on the Variable list. Parse each variable to produce a set of handles that
377 // represent virtual hardware devices.
379 InstallStatus
= EFI_NOT_FOUND
;
380 for (Index
= 0; Index
< UNIX_PCD_ARRAY_SIZE
; Index
++) {
381 PcdTempStr
= (VOID
*)LibPcdGetPtr (mPcdEnvironment
[Index
].Token
);
382 ASSERT (PcdTempStr
!= NULL
);
384 TempStrSize
= StrLen (PcdTempStr
);
385 TempStr
= AllocateMemory ((TempStrSize
* sizeof (CHAR16
)) + 1);
386 StrCpy (TempStr
, PcdTempStr
);
388 StartString
= TempStr
;
391 // Parse the envirnment variable into sub strings using '!' as a delimator.
392 // Each substring needs it's own handle to be added to the system. This code
393 // does not understand the sub string. Thats the device drivers job.
396 while (*StartString
!= '\0') {
399 // Find the end of the sub string
401 SubString
= StartString
;
402 while (*SubString
!= '\0' && *SubString
!= '!') {
406 if (*SubString
== '!') {
408 // Replace token with '\0' to make sub strings. If this is the end
409 // of the string SubString will already point to NULL.
416 if (RemainingDevicePath
!= NULL
) {
417 CreateDevice
= FALSE
;
418 Node
= (UNIX_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
419 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
420 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
421 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (UNIX_VENDOR_DEVICE_PATH_NODE
)
423 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, mPcdEnvironment
[Index
].DevicePathGuid
) &&
424 Node
->Instance
== Count
433 // Allocate instance structure, and fill in parent information.
435 UnixDevice
= AllocateMemory (sizeof (UNIX_IO_DEVICE
));
436 if (UnixDevice
== NULL
) {
437 return EFI_OUT_OF_RESOURCES
;
440 UnixDevice
->Handle
= NULL
;
441 UnixDevice
->ControllerHandle
= ControllerHandle
;
442 UnixDevice
->ParentDevicePath
= ParentDevicePath
;
444 UnixDevice
->UnixIo
.UnixThunk
= UnixThunk
;
447 // Plus 2 to account for the NULL at the end of the Unicode string
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
);
455 UnixDevice
->ControllerNameTable
= NULL
;
458 StrCpy(ComponentName
, UnixDevice
->UnixIo
.EnvString
);
460 UnixDevice
->DevicePath
= UnixBusCreateDevicePath (
462 mPcdEnvironment
[Index
].DevicePathGuid
,
465 if (UnixDevice
->DevicePath
== NULL
) {
466 gBS
->FreePool (UnixDevice
);
467 return EFI_OUT_OF_RESOURCES
;
472 gUnixBusDriverComponentName
.SupportedLanguages
,
473 &UnixDevice
->ControllerNameTable
,
477 UnixDevice
->UnixIo
.TypeGuid
= mPcdEnvironment
[Index
].DevicePathGuid
;
478 UnixDevice
->UnixIo
.InstanceNumber
= Count
;
480 UnixDevice
->Signature
= UNIX_IO_DEVICE_SIGNATURE
;
482 Status
= gBS
->InstallMultipleProtocolInterfaces (
484 &gEfiDevicePathProtocolGuid
,
485 UnixDevice
->DevicePath
,
486 &gEfiUnixIoProtocolGuid
,
490 if (EFI_ERROR (Status
)) {
491 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
492 gBS
->FreePool (UnixDevice
);
495 // Open For Child Device
497 Status
= gBS
->OpenProtocol (
499 &gEfiUnixThunkProtocolGuid
,
501 This
->DriverBindingHandle
,
503 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
505 if (!EFI_ERROR (Status
)) {
506 InstallStatus
= EFI_SUCCESS
;
512 // Parse Next sub string. This will point to '\0' if we are at the end.
515 StartString
= SubString
;
518 gBS
->FreePool (TempStr
);
527 UnixBusDriverBindingStop (
528 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
529 IN EFI_HANDLE ControllerHandle
,
530 IN UINTN NumberOfChildren
,
531 IN EFI_HANDLE
*ChildHandleBuffer
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
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
;
561 // Complete all outstanding transactions to Controller.
562 // Don't allow any new transaction to Controller to be started.
565 if (NumberOfChildren
== 0) {
567 // Close the bus driver
569 Status
= gBS
->OpenProtocol (
572 (VOID
**)&UnixBusDevice
,
573 This
->DriverBindingHandle
,
575 EFI_OPEN_PROTOCOL_GET_PROTOCOL
577 if (EFI_ERROR (Status
)) {
581 gBS
->UninstallMultipleProtocolInterfaces (
588 FreeUnicodeStringTable (UnixBusDevice
->ControllerNameTable
);
590 gBS
->FreePool (UnixBusDevice
);
594 &gEfiUnixThunkProtocolGuid
,
595 This
->DriverBindingHandle
,
601 &gEfiDevicePathProtocolGuid
,
602 This
->DriverBindingHandle
,
608 AllChildrenStopped
= TRUE
;
610 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
612 Status
= gBS
->OpenProtocol (
613 ChildHandleBuffer
[Index
],
614 &gEfiUnixIoProtocolGuid
,
616 This
->DriverBindingHandle
,
618 EFI_OPEN_PROTOCOL_GET_PROTOCOL
620 if (!EFI_ERROR (Status
)) {
622 UnixDevice
= UNIX_IO_DEVICE_FROM_THIS (UnixIo
);
624 Status
= gBS
->CloseProtocol (
626 &gEfiUnixThunkProtocolGuid
,
627 This
->DriverBindingHandle
,
631 Status
= gBS
->UninstallMultipleProtocolInterfaces (
633 &gEfiDevicePathProtocolGuid
,
634 UnixDevice
->DevicePath
,
635 &gEfiUnixIoProtocolGuid
,
640 if (EFI_ERROR (Status
)) {
643 &gEfiUnixThunkProtocolGuid
,
644 (VOID
**) &UnixThunk
,
645 This
->DriverBindingHandle
,
647 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
651 // Close the child handle
653 FreeUnicodeStringTable (UnixDevice
->ControllerNameTable
);
654 gBS
->FreePool (UnixDevice
);
658 if (EFI_ERROR (Status
)) {
659 AllChildrenStopped
= FALSE
;
663 if (!AllChildrenStopped
) {
664 return EFI_DEVICE_ERROR
;
670 EFI_DEVICE_PATH_PROTOCOL
*
671 UnixBusCreateDevicePath (
672 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
674 IN UINT16 InstanceNumber
679 Create a device path node using Guid and InstanceNumber and append it to
680 the passed in RootDevicePath
683 RootDevicePath - Root of the device path to return.
685 Guid - GUID to use in vendor device path node.
687 InstanceNumber - Instance number to use in the vendor device path. This
688 argument is needed to make sure each device path is unique.
692 EFI_DEVICE_PATH_PROTOCOL
696 UNIX_VENDOR_DEVICE_PATH_NODE DevicePath
;
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
));
703 // The GUID defines the Class
705 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
708 // Add an instance number so we can make sure there are no Device Path
711 DevicePath
.Instance
= InstanceNumber
;
713 return AppendDevicePathNode (
715 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath