3 Copyright (c) 2006 - 2007, 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 NT
19 build. These variables are used to define the (virtual) hardware
20 configuration of the NT environment
22 A ! can be used to seperate multiple instances in a variable. Each
23 instance represents a seperate hardware device.
25 EFI_WIN_NT_PHYSICAL_DISKS - maps to drives on your system
26 EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file
27 EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system
28 EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!)
29 EFI_WIN_NT_UGA - Builds UGA Windows of Width and Height
30 EFI_WIN_NT_SERIAL_PORT - maps physical serial ports
32 <F>ixed - Fixed disk like a hard drive.
33 <R>emovable - Removable media like a floppy or CD-ROM.
34 Read <O>nly - Write protected device.
35 Read <W>rite - Read write device.
36 <block count> - Decimal number of blocks a device supports.
37 <block size> - Decimal number of bytes per block.
39 NT envirnonment variable contents. '<' and '>' are not part of the variable,
40 they are just used to make this help more readable. There should be no
41 spaces between the ';'. Extra spaces will break the variable. A '!' is
42 used to seperate multiple devices in a variable.
44 EFI_WIN_NT_VIRTUAL_DISKS =
45 <F | R><O | W>;<block count>;<block size>[!...]
47 EFI_WIN_NT_PHYSICAL_DISKS =
48 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
50 Virtual Disks: These devices use a file to emulate a hard disk or removable
53 Thus a 20 MB emulated hard drive would look like:
54 EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512
56 A 1.44MB emulated floppy with a block size of 1024 would look like:
57 EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024
59 Physical Disks: These devices use NT to open a real device in your system
61 Thus a 120 MB floppy would look like:
62 EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512
64 Thus a standard CD-ROM floppy would look like:
65 EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048
67 EFI_WIN_NT_FILE_SYSTEM =
68 <directory path>[!...]
70 Mounting the two directories C:\FOO and C:\BAR would look like:
71 EFI_WIN_NT_FILE_SYSTEM=c:\foo!c:\bar
76 Declaring a text console window with the title "My EFI Console" woild look like:
77 EFI_WIN_NT_CONSOLE=My EFI Console
80 <width> <height>[!...]
82 Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like:
83 Example : EFI_WIN_NT_UGA=800 600!1024 768
85 EFI_WIN_NT_SERIAL_PORT =
88 Declaring two serial ports on COM1 and COM2 would look like:
89 Example : EFI_WIN_NT_SERIAL_PORT=COM1!COM2
91 EFI_WIN_NT_PASS_THROUGH =
92 <BaseAddress>;<Bus#>;<Device#>;<Function#>
94 Declaring a base address of 0xE0000000 (used for PCI Express devices)
95 and having NT32 talk to a device located at bus 0, device 1, function 0:
96 Example : EFI_WIN_NT_PASS_THROUGH=E000000;0;1;0
101 // The package level header files this module uses
104 #include <WinNtDxe.h>
106 // The protocols, PPI and GUID defintions for this module
108 #include <Protocol/WinNtThunk.h>
109 #include <Protocol/WinNtIo.h>
110 #include <Protocol/ComponentName.h>
111 #include <Protocol/DriverBinding.h>
112 #include <Protocol/DevicePath.h>
114 // The Library classes this module consumes
116 #include <Library/DebugLib.h>
117 #include <Library/BaseLib.h>
118 #include <Library/UefiDriverEntryPoint.h>
119 #include <Library/UefiLib.h>
120 #include <Library/PcdLib.h>
121 #include <Library/BaseMemoryLib.h>
122 #include <Library/UefiBootServicesTableLib.h>
123 #include <Library/DevicePathLib.h>
124 #include <Library/MemoryAllocationLib.h>
126 #include "WinNtBusDriver.h"
128 extern EFI_GUID gWinNtBusDriverGuid
;
130 // DriverBinding protocol global
132 EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding
= {
133 WinNtBusDriverBindingSupported
,
134 WinNtBusDriverBindingStart
,
135 WinNtBusDriverBindingStop
,
141 #define NT_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(NT_ENVIRONMENT_VARIABLE_ENTRY))
144 // BUGBUG: Because currently the new build tools does not support dynamic PCD
145 // following dynamic PCd will be hard code. After tools ready, we should
146 // use dynmanic PCD AQAP.
150 // Table to map NT Environment variable to the GUID that should be in
153 //static NT_PCD_ENTRY mPcdEnvironment[] = {
154 // PcdToken(PcdWinNtConsole), &gEfiWinNtConsoleGuid,
155 // PcdToken(PcdWinNtGop), &gEfiWinNtGopGuid,
156 // PcdToken(PcdWinNtSerialPort), &gEfiWinNtSerialPortGuid,
157 // PcdToken(PcdWinNtFileSystem), &gEfiWinNtFileSystemGuid,
158 // PcdToken(PcdWinNtVirtualDisk), &gEfiWinNtVirtualDisksGuid,
159 // PcdToken(PcdWinNtPhysicalDisk), &gEfiWinNtPhysicalDisksGuid,
160 // PcdToken(PcdWinNtCpuModel), &gEfiWinNtCPUModelGuid,
161 // PcdToken(PcdWinNtCpuSpeed), &gEfiWinNtCPUSpeedGuid,
162 // PcdToken(PcdWinNtMemorySize), &gEfiWinNtMemoryGuid
166 EFI_GUID
*DevicePathGuid
;
167 } NT_ENVIRONMENT_VARIABLE_ENTRY
;
169 static NT_ENVIRONMENT_VARIABLE_ENTRY mPcdEnvironment
[] = {
170 L
"Bus Driver Console Window", &gEfiWinNtConsoleGuid
,
171 L
"UGA Window 1!UGA Window 2", &gEfiWinNtGopGuid
,
172 L
"COM1!COM2", &gEfiWinNtSerialPortGuid
,
173 L
".!..\\..\\..\\..\\EdkShellBinPkg\\bin\\ia32\\Apps", &gEfiWinNtFileSystemGuid
,
174 L
"FW;40960;512", &gEfiWinNtVirtualDisksGuid
,
175 L
"E:RW;245760;512", &gEfiWinNtPhysicalDisksGuid
,
176 L
"Intel(R) Processor Model", &gEfiWinNtCPUModelGuid
,
177 L
"3000", &gEfiWinNtCPUSpeedGuid
,
178 L
"64!64", &gEfiWinNtMemoryGuid
182 The user Entry Point for module WinNtBusDriver. The user code starts with this function.
184 @param[in] ImageHandle The firmware allocated handle for the EFI image.
185 @param[in] SystemTable A pointer to the EFI System Table.
187 @retval EFI_SUCCESS The entry point is executed successfully.
188 @retval other Some error occurs when executing this entry point.
193 InitializeWinNtBusDriver(
194 IN EFI_HANDLE ImageHandle
,
195 IN EFI_SYSTEM_TABLE
*SystemTable
201 // Install driver model protocol(s).
203 Status
= EfiLibInstallAllDriverProtocols (
206 &gWinNtBusDriverBinding
,
208 &gWinNtBusDriverComponentName
,
212 ASSERT_EFI_ERROR (Status
);
225 Buffer
= AllocatePool (Size
);
226 ASSERT (Buffer
!= NULL
);
234 WinNtBusDriverBindingSupported (
235 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
236 IN EFI_HANDLE ControllerHandle
,
237 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
250 // TODO: This - add argument and description to function comment
251 // TODO: ControllerHandle - add argument and description to function comment
252 // TODO: RemainingDevicePath - add argument and description to function comment
253 // TODO: EFI_UNSUPPORTED - add return value to function comment
254 // TODO: EFI_UNSUPPORTED - add return value to function comment
255 // TODO: EFI_SUCCESS - add return value to function comment
256 // TODO: EFI_SUCCESS - add return value to function comment
259 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
260 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
264 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
265 // it is a legal Device Path Node for this bus driver's children.
267 if (RemainingDevicePath
!= NULL
) {
268 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
269 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
270 DevicePathNodeLength(RemainingDevicePath
) != sizeof(WIN_NT_VENDOR_DEVICE_PATH_NODE
)) {
271 return EFI_UNSUPPORTED
;
274 for (Index
= 0; Index
< NT_PCD_ARRAY_SIZE
; Index
++) {
275 if (CompareGuid (&((VENDOR_DEVICE_PATH
*) RemainingDevicePath
)->Guid
, mPcdEnvironment
[Index
].DevicePathGuid
)) {
280 if (Index
>= NT_PCD_ARRAY_SIZE
) {
281 return EFI_UNSUPPORTED
;
286 // Open the IO Abstraction(s) needed to perform the supported test
288 Status
= gBS
->OpenProtocol (
290 &gEfiDevicePathProtocolGuid
,
292 This
->DriverBindingHandle
,
294 EFI_OPEN_PROTOCOL_BY_DRIVER
296 if (Status
== EFI_ALREADY_STARTED
) {
300 if (EFI_ERROR (Status
)) {
306 &gEfiDevicePathProtocolGuid
,
307 This
->DriverBindingHandle
,
311 Status
= gBS
->OpenProtocol (
313 &gEfiWinNtThunkProtocolGuid
,
315 This
->DriverBindingHandle
,
317 EFI_OPEN_PROTOCOL_BY_DRIVER
319 if (Status
== EFI_ALREADY_STARTED
) {
323 if (EFI_ERROR (Status
)) {
328 // Since we call through WinNtThunk we need to make sure it's valid
330 Status
= EFI_SUCCESS
;
331 if (WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
332 Status
= EFI_UNSUPPORTED
;
336 // Close the I/O Abstraction(s) used to perform the supported test
340 &gEfiWinNtThunkProtocolGuid
,
341 This
->DriverBindingHandle
,
350 WinNtBusDriverBindingStart (
351 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
352 IN EFI_HANDLE ControllerHandle
,
353 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
366 // TODO: This - add argument and description to function comment
367 // TODO: ControllerHandle - add argument and description to function comment
368 // TODO: RemainingDevicePath - add argument and description to function comment
369 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
370 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
371 // TODO: EFI_SUCCESS - add return value to function comment
374 EFI_STATUS InstallStatus
;
375 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
376 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
377 WIN_NT_BUS_DEVICE
*WinNtBusDevice
;
378 WIN_NT_IO_DEVICE
*WinNtDevice
;
384 UINT16 ComponentName
[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH
];
385 WIN_NT_VENDOR_DEVICE_PATH_NODE
*Node
;
386 BOOLEAN CreateDevice
;
391 Status
= EFI_UNSUPPORTED
;
394 // Grab the protocols we need
396 Status
= gBS
->OpenProtocol (
398 &gEfiDevicePathProtocolGuid
,
400 This
->DriverBindingHandle
,
402 EFI_OPEN_PROTOCOL_BY_DRIVER
404 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
408 Status
= gBS
->OpenProtocol (
410 &gEfiWinNtThunkProtocolGuid
,
412 This
->DriverBindingHandle
,
414 EFI_OPEN_PROTOCOL_BY_DRIVER
416 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
420 if (Status
!= EFI_ALREADY_STARTED
) {
421 WinNtBusDevice
= AllocatePool (sizeof (WIN_NT_BUS_DEVICE
));
422 if (WinNtBusDevice
== NULL
) {
423 return EFI_OUT_OF_RESOURCES
;
426 WinNtBusDevice
->Signature
= WIN_NT_BUS_DEVICE_SIGNATURE
;
427 WinNtBusDevice
->ControllerNameTable
= NULL
;
431 gWinNtBusDriverComponentName
.SupportedLanguages
,
432 &WinNtBusDevice
->ControllerNameTable
,
433 L
"Windows Bus Controller"
436 Status
= gBS
->InstallMultipleProtocolInterfaces (
438 &gWinNtBusDriverGuid
,
442 if (EFI_ERROR (Status
)) {
443 FreeUnicodeStringTable (WinNtBusDevice
->ControllerNameTable
);
444 FreePool (WinNtBusDevice
);
450 // Loop on the Variable list. Parse each variable to produce a set of handles that
451 // represent virtual hardware devices.
453 InstallStatus
= EFI_NOT_FOUND
;
454 for (Index
= 0; Index
< NT_PCD_ARRAY_SIZE
; Index
++) {
455 //PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);
456 PcdTempStr
= mPcdEnvironment
[Index
].Variable
;
457 ASSERT (PcdTempStr
!= NULL
);
459 TempStrSize
= StrLen (PcdTempStr
);
460 TempStr
= AllocateMemory ((TempStrSize
* sizeof (CHAR16
)) + 1);
461 StrCpy (TempStr
, PcdTempStr
);
463 StartString
= TempStr
;
466 // Parse the envirnment variable into sub strings using '!' as a delimator.
467 // Each substring needs it's own handle to be added to the system. This code
468 // does not understand the sub string. Thats the device drivers job.
471 while (*StartString
!= '\0') {
474 // Find the end of the sub string
476 SubString
= StartString
;
477 while (*SubString
!= '\0' && *SubString
!= '!') {
481 if (*SubString
== '!') {
483 // Replace token with '\0' to make sub strings. If this is the end
484 // of the string SubString will already point to NULL.
491 if (RemainingDevicePath
!= NULL
) {
492 CreateDevice
= FALSE
;
493 Node
= (WIN_NT_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
494 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
495 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
496 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE
)
498 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, mPcdEnvironment
[Index
].DevicePathGuid
) &&
499 Node
->Instance
== Count
509 // Allocate instance structure, and fill in parent information.
511 WinNtDevice
= AllocateMemory (sizeof (WIN_NT_IO_DEVICE
));
512 if (WinNtDevice
== NULL
) {
513 return EFI_OUT_OF_RESOURCES
;
516 WinNtDevice
->Handle
= NULL
;
517 WinNtDevice
->ControllerHandle
= ControllerHandle
;
518 WinNtDevice
->ParentDevicePath
= ParentDevicePath
;
520 WinNtDevice
->WinNtIo
.WinNtThunk
= WinNtThunk
;
523 // Plus 2 to account for the NULL at the end of the Unicode string
525 StringSize
= (UINTN
) ((UINT8
*) SubString
- (UINT8
*) StartString
) + sizeof (CHAR16
);
526 WinNtDevice
->WinNtIo
.EnvString
= AllocateMemory (StringSize
);
527 if (WinNtDevice
->WinNtIo
.EnvString
!= NULL
) {
528 CopyMem (WinNtDevice
->WinNtIo
.EnvString
, StartString
, StringSize
);
531 WinNtDevice
->ControllerNameTable
= NULL
;
533 WinNtThunk
->SPrintf (ComponentName
, sizeof (ComponentName
), L
"%s", WinNtDevice
->WinNtIo
.EnvString
);
535 WinNtDevice
->DevicePath
= WinNtBusCreateDevicePath (
537 mPcdEnvironment
[Index
].DevicePathGuid
,
540 if (WinNtDevice
->DevicePath
== NULL
) {
541 FreePool (WinNtDevice
);
542 return EFI_OUT_OF_RESOURCES
;
547 gWinNtBusDriverComponentName
.SupportedLanguages
,
548 &WinNtDevice
->ControllerNameTable
,
552 WinNtDevice
->WinNtIo
.TypeGuid
= mPcdEnvironment
[Index
].DevicePathGuid
;
553 WinNtDevice
->WinNtIo
.InstanceNumber
= Count
;
555 WinNtDevice
->Signature
= WIN_NT_IO_DEVICE_SIGNATURE
;
557 Status
= gBS
->InstallMultipleProtocolInterfaces (
558 &WinNtDevice
->Handle
,
559 &gEfiDevicePathProtocolGuid
,
560 WinNtDevice
->DevicePath
,
561 &gEfiWinNtIoProtocolGuid
,
562 &WinNtDevice
->WinNtIo
,
565 if (EFI_ERROR (Status
)) {
566 FreeUnicodeStringTable (WinNtDevice
->ControllerNameTable
);
567 FreePool (WinNtDevice
);
570 // Open For Child Device
572 Status
= gBS
->OpenProtocol (
574 &gEfiWinNtThunkProtocolGuid
,
576 This
->DriverBindingHandle
,
578 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
580 if (!EFI_ERROR (Status
)) {
581 InstallStatus
= EFI_SUCCESS
;
587 // Parse Next sub string. This will point to '\0' if we are at the end.
590 StartString
= SubString
;
602 WinNtBusDriverBindingStop (
603 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
604 IN EFI_HANDLE ControllerHandle
,
605 IN UINTN NumberOfChildren
,
606 IN EFI_HANDLE
*ChildHandleBuffer
619 // TODO: This - add argument and description to function comment
620 // TODO: ControllerHandle - add argument and description to function comment
621 // TODO: NumberOfChildren - add argument and description to function comment
622 // TODO: ChildHandleBuffer - add argument and description to function comment
623 // TODO: EFI_SUCCESS - add return value to function comment
624 // TODO: EFI_DEVICE_ERROR - add return value to function comment
625 // TODO: EFI_SUCCESS - add return value to function comment
629 BOOLEAN AllChildrenStopped
;
630 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
631 WIN_NT_BUS_DEVICE
*WinNtBusDevice
;
632 WIN_NT_IO_DEVICE
*WinNtDevice
;
633 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
636 // Complete all outstanding transactions to Controller.
637 // Don't allow any new transaction to Controller to be started.
640 if (NumberOfChildren
== 0) {
642 // Close the bus driver
644 Status
= gBS
->OpenProtocol (
646 &gWinNtBusDriverGuid
,
648 This
->DriverBindingHandle
,
650 EFI_OPEN_PROTOCOL_GET_PROTOCOL
652 if (EFI_ERROR (Status
)) {
656 gBS
->UninstallMultipleProtocolInterfaces (
658 &gWinNtBusDriverGuid
,
663 FreeUnicodeStringTable (WinNtBusDevice
->ControllerNameTable
);
665 FreePool (WinNtBusDevice
);
669 &gEfiWinNtThunkProtocolGuid
,
670 This
->DriverBindingHandle
,
676 &gEfiDevicePathProtocolGuid
,
677 This
->DriverBindingHandle
,
683 AllChildrenStopped
= TRUE
;
685 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
687 Status
= gBS
->OpenProtocol (
688 ChildHandleBuffer
[Index
],
689 &gEfiWinNtIoProtocolGuid
,
691 This
->DriverBindingHandle
,
693 EFI_OPEN_PROTOCOL_GET_PROTOCOL
695 if (!EFI_ERROR (Status
)) {
697 WinNtDevice
= WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo
);
699 Status
= gBS
->CloseProtocol (
701 &gEfiWinNtThunkProtocolGuid
,
702 This
->DriverBindingHandle
,
706 Status
= gBS
->UninstallMultipleProtocolInterfaces (
708 &gEfiDevicePathProtocolGuid
,
709 WinNtDevice
->DevicePath
,
710 &gEfiWinNtIoProtocolGuid
,
711 &WinNtDevice
->WinNtIo
,
715 if (EFI_ERROR (Status
)) {
718 &gEfiWinNtThunkProtocolGuid
,
719 (VOID
**) &WinNtThunk
,
720 This
->DriverBindingHandle
,
722 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
726 // Close the child handle
728 FreeUnicodeStringTable (WinNtDevice
->ControllerNameTable
);
729 FreePool (WinNtDevice
);
733 if (EFI_ERROR (Status
)) {
734 AllChildrenStopped
= FALSE
;
738 if (!AllChildrenStopped
) {
739 return EFI_DEVICE_ERROR
;
745 EFI_DEVICE_PATH_PROTOCOL
*
746 WinNtBusCreateDevicePath (
747 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
749 IN UINT16 InstanceNumber
754 Create a device path node using Guid and InstanceNumber and append it to
755 the passed in RootDevicePath
758 RootDevicePath - Root of the device path to return.
760 Guid - GUID to use in vendor device path node.
762 InstanceNumber - Instance number to use in the vendor device path. This
763 argument is needed to make sure each device path is unique.
767 EFI_DEVICE_PATH_PROTOCOL
771 WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath
;
773 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
774 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
775 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE
));
778 // The GUID defines the Class
780 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
783 // Add an instance number so we can make sure there are no Device Path
786 DevicePath
.Instance
= InstanceNumber
;
788 return AppendDevicePathNode (
790 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath