3 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
4 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 This following section documents the envirnoment variables for the Win NT
14 build. These variables are used to define the (virtual) hardware
15 configuration of the NT environment
17 A ! can be used to seperate multiple instances in a variable. Each
18 instance represents a seperate hardware device.
20 EFI_WIN_NT_PHYSICAL_DISKS - maps to drives on your system
21 EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file
22 EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system
23 EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!)
24 EFI_WIN_NT_GOP - Builds GOP Windows of Width and Height
25 EFI_WIN_NT_SERIAL_PORT - maps physical serial ports
27 <F>ixed - Fixed disk like a hard drive.
28 <R>emovable - Removable media like a floppy or CD-ROM.
29 Read <O>nly - Write protected device.
30 Read <W>rite - Read write device.
31 <block count> - Decimal number of blocks a device supports.
32 <block size> - Decimal number of bytes per block.
34 NT envirnonment variable contents. '<' and '>' are not part of the variable,
35 they are just used to make this help more readable. There should be no
36 spaces between the ';'. Extra spaces will break the variable. A '!' is
37 used to seperate multiple devices in a variable.
39 EFI_WIN_NT_VIRTUAL_DISKS =
40 <F | R><O | W>;<block count>;<block size>[!...]
42 EFI_WIN_NT_PHYSICAL_DISKS =
43 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
45 Virtual Disks: These devices use a file to emulate a hard disk or removable
48 Thus a 20 MB emulated hard drive would look like:
49 EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512
51 A 1.44MB emulated floppy with a block size of 1024 would look like:
52 EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024
54 Physical Disks: These devices use NT to open a real device in your system
56 Thus a 120 MB floppy would look like:
57 EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512
59 Thus a standard CD-ROM floppy would look like:
60 EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048
62 EFI_WIN_NT_FILE_SYSTEM =
63 <directory path>[!...]
65 Mounting the two directories C:\FOO and C:\BAR would look like:
66 EFI_WIN_NT_FILE_SYSTEM=c:\foo!c:\bar
71 Declaring a text console window with the title "My EFI Console" woild look like:
72 EFI_WIN_NT_CONSOLE=My EFI Console
75 <width> <height>[!...]
77 Declaring a two GOP windows with resolutions of 800x600 and 1024x768 would look like:
78 Example : EFI_WIN_NT_GOP=800 600!1024 768
80 EFI_WIN_NT_SERIAL_PORT =
83 Declaring two serial ports on COM1 and COM2 would look like:
84 Example : EFI_WIN_NT_SERIAL_PORT=COM1!COM2
86 EFI_WIN_NT_PASS_THROUGH =
87 <BaseAddress>;<Bus#>;<Device#>;<Function#>
89 Declaring a base address of 0xE0000000 (used for PCI Express devices)
90 and having NT32 talk to a device located at bus 0, device 1, function 0:
91 Example : EFI_WIN_NT_PASS_THROUGH=E000000;0;1;0
96 // The package level header files this module uses
101 // The protocols, PPI and GUID defintions for this module
103 #include <Protocol/WinNtThunk.h>
104 #include <Protocol/WinNtIo.h>
105 #include <Protocol/ComponentName.h>
106 #include <Protocol/DriverBinding.h>
107 #include <Protocol/DevicePath.h>
109 // The Library classes this module consumes
111 #include <Library/DebugLib.h>
112 #include <Library/BaseLib.h>
113 #include <Library/UefiDriverEntryPoint.h>
114 #include <Library/UefiLib.h>
115 #include <Library/PcdLib.h>
116 #include <Library/BaseMemoryLib.h>
117 #include <Library/UefiBootServicesTableLib.h>
118 #include <Library/DevicePathLib.h>
119 #include <Library/MemoryAllocationLib.h>
121 #include "WinNtBusDriver.h"
123 extern EFI_GUID gWinNtBusDriverGuid
;
125 // DriverBinding protocol global
127 EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding
= {
128 WinNtBusDriverBindingSupported
,
129 WinNtBusDriverBindingStart
,
130 WinNtBusDriverBindingStop
,
136 #define NT_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(NT_PCD_ENTRY))
139 // Table to map NT Environment variable to the GUID that should be in
142 NT_PCD_ENTRY mPcdEnvironment
[] = {
143 PcdToken(PcdWinNtConsole
), &gEfiWinNtConsoleGuid
,
144 PcdToken(PcdWinNtGop
), &gEfiWinNtGopGuid
,
145 PcdToken(PcdWinNtSerialPort
), &gEfiWinNtSerialPortGuid
,
146 PcdToken(PcdWinNtFileSystem
), &gEfiWinNtFileSystemGuid
,
147 PcdToken(PcdWinNtVirtualDisk
), &gEfiWinNtVirtualDisksGuid
,
148 PcdToken(PcdWinNtPhysicalDisk
), &gEfiWinNtPhysicalDisksGuid
152 The user Entry Point for module WinNtBusDriver. The user code starts with this function.
154 @param[in] ImageHandle The firmware allocated handle for the EFI image.
155 @param[in] SystemTable A pointer to the EFI System Table.
157 @retval EFI_SUCCESS The entry point is executed successfully.
158 @retval other Some error occurs when executing this entry point.
163 InitializeWinNtBusDriver(
164 IN EFI_HANDLE ImageHandle
,
165 IN EFI_SYSTEM_TABLE
*SystemTable
171 // Install driver model protocol(s).
173 Status
= EfiLibInstallDriverBindingComponentName2 (
176 &gWinNtBusDriverBinding
,
178 &gWinNtBusDriverComponentName
,
179 &gWinNtBusDriverComponentName2
181 ASSERT_EFI_ERROR (Status
);
194 Buffer
= AllocatePool (Size
);
195 ASSERT (Buffer
!= NULL
);
203 WinNtBusDriverBindingSupported (
204 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
205 IN EFI_HANDLE ControllerHandle
,
206 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
219 // TODO: This - add argument and description to function comment
220 // TODO: ControllerHandle - add argument and description to function comment
221 // TODO: RemainingDevicePath - add argument and description to function comment
222 // TODO: EFI_UNSUPPORTED - add return value to function comment
223 // TODO: EFI_UNSUPPORTED - add return value to function comment
224 // TODO: EFI_SUCCESS - add return value to function comment
225 // TODO: EFI_SUCCESS - add return value to function comment
228 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
229 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
233 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
234 // it is a legal Device Path Node for this bus driver's children.
236 if (RemainingDevicePath
!= NULL
) {
238 // Check if RemainingDevicePath is the End of Device Path Node,
239 // if yes, go on checking other conditions
241 if (!IsDevicePathEnd (RemainingDevicePath
)) {
243 // If RemainingDevicePath isn't the End of Device Path Node,
244 // check its validation
246 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
247 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
248 DevicePathNodeLength(RemainingDevicePath
) != sizeof(WIN_NT_VENDOR_DEVICE_PATH_NODE
)) {
249 return EFI_UNSUPPORTED
;
252 for (Index
= 0; Index
< NT_PCD_ARRAY_SIZE
; Index
++) {
253 if (CompareGuid (&((VENDOR_DEVICE_PATH
*) RemainingDevicePath
)->Guid
, mPcdEnvironment
[Index
].DevicePathGuid
)) {
258 if (Index
>= NT_PCD_ARRAY_SIZE
) {
259 return EFI_UNSUPPORTED
;
265 // Open the IO Abstraction(s) needed to perform the supported test
267 Status
= gBS
->OpenProtocol (
269 &gEfiWinNtThunkProtocolGuid
,
270 (VOID
**) &WinNtThunk
,
271 This
->DriverBindingHandle
,
273 EFI_OPEN_PROTOCOL_BY_DRIVER
275 if (Status
== EFI_ALREADY_STARTED
) {
279 if (EFI_ERROR (Status
)) {
284 // Close the I/O Abstraction(s) used to perform the supported test
288 &gEfiWinNtThunkProtocolGuid
,
289 This
->DriverBindingHandle
,
294 // Open the EFI Device Path protocol needed to perform the supported test
296 Status
= gBS
->OpenProtocol (
298 &gEfiDevicePathProtocolGuid
,
299 (VOID
**) &ParentDevicePath
,
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_BY_DRIVER
304 if (Status
== EFI_ALREADY_STARTED
) {
308 if (EFI_ERROR (Status
)) {
313 // Since we call through WinNtThunk we need to make sure it's valid
315 Status
= EFI_SUCCESS
;
316 if (WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
317 Status
= EFI_UNSUPPORTED
;
321 // Close protocol, don't use device path protocol in the Support() function
325 &gEfiDevicePathProtocolGuid
,
326 This
->DriverBindingHandle
,
335 WinNtBusDriverBindingStart (
336 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
337 IN EFI_HANDLE ControllerHandle
,
338 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
351 // TODO: This - add argument and description to function comment
352 // TODO: ControllerHandle - add argument and description to function comment
353 // TODO: RemainingDevicePath - add argument and description to function comment
354 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
355 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
356 // TODO: EFI_SUCCESS - add return value to function comment
359 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
360 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
361 WIN_NT_BUS_DEVICE
*WinNtBusDevice
;
362 WIN_NT_IO_DEVICE
*WinNtDevice
;
368 UINT16 ComponentName
[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH
];
369 WIN_NT_VENDOR_DEVICE_PATH_NODE
*Node
;
370 BOOLEAN CreateDevice
;
375 Status
= EFI_UNSUPPORTED
;
378 // Grab the protocols we need
380 Status
= gBS
->OpenProtocol (
382 &gEfiDevicePathProtocolGuid
,
383 (VOID
**) &ParentDevicePath
,
384 This
->DriverBindingHandle
,
386 EFI_OPEN_PROTOCOL_BY_DRIVER
388 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
392 Status
= gBS
->OpenProtocol (
394 &gEfiWinNtThunkProtocolGuid
,
395 (VOID
**) &WinNtThunk
,
396 This
->DriverBindingHandle
,
398 EFI_OPEN_PROTOCOL_BY_DRIVER
400 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
404 if (Status
!= EFI_ALREADY_STARTED
) {
405 WinNtBusDevice
= AllocatePool (sizeof (WIN_NT_BUS_DEVICE
));
406 if (WinNtBusDevice
== NULL
) {
407 return EFI_OUT_OF_RESOURCES
;
410 WinNtBusDevice
->Signature
= WIN_NT_BUS_DEVICE_SIGNATURE
;
411 WinNtBusDevice
->ControllerNameTable
= NULL
;
415 gWinNtBusDriverComponentName
.SupportedLanguages
,
416 &WinNtBusDevice
->ControllerNameTable
,
417 L
"Windows Bus Controller",
422 gWinNtBusDriverComponentName2
.SupportedLanguages
,
423 &WinNtBusDevice
->ControllerNameTable
,
424 L
"Windows Bus Controller",
429 Status
= gBS
->InstallMultipleProtocolInterfaces (
431 &gWinNtBusDriverGuid
,
435 if (EFI_ERROR (Status
)) {
436 FreeUnicodeStringTable (WinNtBusDevice
->ControllerNameTable
);
437 FreePool (WinNtBusDevice
);
443 // Loop on the Variable list. Parse each variable to produce a set of handles that
444 // represent virtual hardware devices.
446 for (Index
= 0; Index
< NT_PCD_ARRAY_SIZE
; Index
++) {
447 PcdTempStr
= (VOID
*)LibPcdGetPtr (mPcdEnvironment
[Index
].Token
);
448 ASSERT (PcdTempStr
!= NULL
);
450 TempStrSize
= StrLen (PcdTempStr
);
451 TempStr
= AllocateMemory (((TempStrSize
+ 1) * sizeof (CHAR16
)));
452 StrCpy (TempStr
, PcdTempStr
);
454 StartString
= TempStr
;
457 // Parse the envirnment variable into sub strings using '!' as a delimator.
458 // Each substring needs it's own handle to be added to the system. This code
459 // does not understand the sub string. Thats the device drivers job.
462 while (*StartString
!= '\0') {
465 // Find the end of the sub string
467 SubString
= StartString
;
468 while (*SubString
!= '\0' && *SubString
!= '!') {
472 if (*SubString
== '!') {
474 // Replace token with '\0' to make sub strings. If this is the end
475 // of the string SubString will already point to NULL.
482 if (RemainingDevicePath
!= NULL
) {
483 CreateDevice
= FALSE
;
485 // Check if RemainingDevicePath is the End of Device Path Node,
486 // if yes, don't create any child device
488 if (!IsDevicePathEnd (RemainingDevicePath
)) {
490 // If RemainingDevicePath isn't the End of Device Path Node,
491 // check its validation
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
510 // Allocate instance structure, and fill in parent information.
512 WinNtDevice
= AllocateMemory (sizeof (WIN_NT_IO_DEVICE
));
513 if (WinNtDevice
== NULL
) {
514 return EFI_OUT_OF_RESOURCES
;
517 WinNtDevice
->Handle
= NULL
;
518 WinNtDevice
->ControllerHandle
= ControllerHandle
;
519 WinNtDevice
->ParentDevicePath
= ParentDevicePath
;
521 WinNtDevice
->WinNtIo
.WinNtThunk
= WinNtThunk
;
524 // Plus 2 to account for the NULL at the end of the Unicode string
526 StringSize
= (UINTN
) ((UINT8
*) SubString
- (UINT8
*) StartString
) + sizeof (CHAR16
);
527 WinNtDevice
->WinNtIo
.EnvString
= AllocateMemory (StringSize
);
528 if (WinNtDevice
->WinNtIo
.EnvString
!= NULL
) {
529 CopyMem (WinNtDevice
->WinNtIo
.EnvString
, StartString
, StringSize
);
532 WinNtDevice
->ControllerNameTable
= NULL
;
534 WinNtThunk
->SPrintf (ComponentName
, sizeof (ComponentName
), L
"%s", WinNtDevice
->WinNtIo
.EnvString
);
536 WinNtDevice
->DevicePath
= WinNtBusCreateDevicePath (
538 mPcdEnvironment
[Index
].DevicePathGuid
,
541 if (WinNtDevice
->DevicePath
== NULL
) {
542 FreePool (WinNtDevice
);
543 return EFI_OUT_OF_RESOURCES
;
548 gWinNtBusDriverComponentName
.SupportedLanguages
,
549 &WinNtDevice
->ControllerNameTable
,
555 gWinNtBusDriverComponentName2
.SupportedLanguages
,
556 &WinNtDevice
->ControllerNameTable
,
562 WinNtDevice
->WinNtIo
.TypeGuid
= mPcdEnvironment
[Index
].DevicePathGuid
;
563 WinNtDevice
->WinNtIo
.InstanceNumber
= Count
;
565 WinNtDevice
->Signature
= WIN_NT_IO_DEVICE_SIGNATURE
;
567 Status
= gBS
->InstallMultipleProtocolInterfaces (
568 &WinNtDevice
->Handle
,
569 &gEfiDevicePathProtocolGuid
,
570 WinNtDevice
->DevicePath
,
571 &gEfiWinNtIoProtocolGuid
,
572 &WinNtDevice
->WinNtIo
,
575 if (EFI_ERROR (Status
)) {
576 FreeUnicodeStringTable (WinNtDevice
->ControllerNameTable
);
577 FreePool (WinNtDevice
);
580 // Open For Child Device
582 Status
= gBS
->OpenProtocol (
584 &gEfiWinNtThunkProtocolGuid
,
585 (VOID
**) &WinNtThunk
,
586 This
->DriverBindingHandle
,
588 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
594 // Parse Next sub string. This will point to '\0' if we are at the end.
597 StartString
= SubString
;
609 WinNtBusDriverBindingStop (
610 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
611 IN EFI_HANDLE ControllerHandle
,
612 IN UINTN NumberOfChildren
,
613 IN EFI_HANDLE
*ChildHandleBuffer
626 // TODO: This - add argument and description to function comment
627 // TODO: ControllerHandle - add argument and description to function comment
628 // TODO: NumberOfChildren - add argument and description to function comment
629 // TODO: ChildHandleBuffer - add argument and description to function comment
630 // TODO: EFI_SUCCESS - add return value to function comment
631 // TODO: EFI_DEVICE_ERROR - add return value to function comment
632 // TODO: EFI_SUCCESS - add return value to function comment
636 BOOLEAN AllChildrenStopped
;
637 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
638 WIN_NT_BUS_DEVICE
*WinNtBusDevice
;
639 WIN_NT_IO_DEVICE
*WinNtDevice
;
640 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
643 // Complete all outstanding transactions to Controller.
644 // Don't allow any new transaction to Controller to be started.
647 if (NumberOfChildren
== 0) {
649 // Close the bus driver
651 Status
= gBS
->OpenProtocol (
653 &gWinNtBusDriverGuid
,
654 (VOID
**) &WinNtBusDevice
,
655 This
->DriverBindingHandle
,
657 EFI_OPEN_PROTOCOL_GET_PROTOCOL
659 if (EFI_ERROR (Status
)) {
663 gBS
->UninstallMultipleProtocolInterfaces (
665 &gWinNtBusDriverGuid
,
670 FreeUnicodeStringTable (WinNtBusDevice
->ControllerNameTable
);
672 FreePool (WinNtBusDevice
);
676 &gEfiWinNtThunkProtocolGuid
,
677 This
->DriverBindingHandle
,
683 &gEfiDevicePathProtocolGuid
,
684 This
->DriverBindingHandle
,
690 AllChildrenStopped
= TRUE
;
692 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
694 Status
= gBS
->OpenProtocol (
695 ChildHandleBuffer
[Index
],
696 &gEfiWinNtIoProtocolGuid
,
698 This
->DriverBindingHandle
,
700 EFI_OPEN_PROTOCOL_GET_PROTOCOL
702 if (!EFI_ERROR (Status
)) {
704 WinNtDevice
= WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo
);
706 Status
= gBS
->CloseProtocol (
708 &gEfiWinNtThunkProtocolGuid
,
709 This
->DriverBindingHandle
,
713 Status
= gBS
->UninstallMultipleProtocolInterfaces (
715 &gEfiDevicePathProtocolGuid
,
716 WinNtDevice
->DevicePath
,
717 &gEfiWinNtIoProtocolGuid
,
718 &WinNtDevice
->WinNtIo
,
722 if (EFI_ERROR (Status
)) {
725 &gEfiWinNtThunkProtocolGuid
,
726 (VOID
**) &WinNtThunk
,
727 This
->DriverBindingHandle
,
729 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
733 // Close the child handle
735 FreeUnicodeStringTable (WinNtDevice
->ControllerNameTable
);
736 FreePool (WinNtDevice
);
740 if (EFI_ERROR (Status
)) {
741 AllChildrenStopped
= FALSE
;
745 if (!AllChildrenStopped
) {
746 return EFI_DEVICE_ERROR
;
752 EFI_DEVICE_PATH_PROTOCOL
*
753 WinNtBusCreateDevicePath (
754 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
756 IN UINT16 InstanceNumber
761 Create a device path node using Guid and InstanceNumber and append it to
762 the passed in RootDevicePath
765 RootDevicePath - Root of the device path to return.
767 Guid - GUID to use in vendor device path node.
769 InstanceNumber - Instance number to use in the vendor device path. This
770 argument is needed to make sure each device path is unique.
774 EFI_DEVICE_PATH_PROTOCOL
778 WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath
;
780 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
781 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
782 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE
));
785 // The GUID defines the Class
787 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
790 // Add an instance number so we can make sure there are no Device Path
793 DevicePath
.Instance
= InstanceNumber
;
795 return AppendDevicePathNode (
797 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath