3 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
4 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 This following section documents the envirnoment variables for the Win NT
20 build. These variables are used to define the (virtual) hardware
21 configuration of the NT environment
23 A ! can be used to seperate multiple instances in a variable. Each
24 instance represents a seperate hardware device.
26 EFI_WIN_NT_PHYSICAL_DISKS - maps to drives on your system
27 EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file
28 EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system
29 EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!)
30 EFI_WIN_NT_GOP - Builds GOP Windows of Width and Height
31 EFI_WIN_NT_SERIAL_PORT - maps physical serial ports
33 <F>ixed - Fixed disk like a hard drive.
34 <R>emovable - Removable media like a floppy or CD-ROM.
35 Read <O>nly - Write protected device.
36 Read <W>rite - Read write device.
37 <block count> - Decimal number of blocks a device supports.
38 <block size> - Decimal number of bytes per block.
40 NT envirnonment variable contents. '<' and '>' are not part of the variable,
41 they are just used to make this help more readable. There should be no
42 spaces between the ';'. Extra spaces will break the variable. A '!' is
43 used to seperate multiple devices in a variable.
45 EFI_WIN_NT_VIRTUAL_DISKS =
46 <F | R><O | W>;<block count>;<block size>[!...]
48 EFI_WIN_NT_PHYSICAL_DISKS =
49 <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
51 Virtual Disks: These devices use a file to emulate a hard disk or removable
54 Thus a 20 MB emulated hard drive would look like:
55 EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512
57 A 1.44MB emulated floppy with a block size of 1024 would look like:
58 EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024
60 Physical Disks: These devices use NT to open a real device in your system
62 Thus a 120 MB floppy would look like:
63 EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512
65 Thus a standard CD-ROM floppy would look like:
66 EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048
68 EFI_WIN_NT_FILE_SYSTEM =
69 <directory path>[!...]
71 Mounting the two directories C:\FOO and C:\BAR would look like:
72 EFI_WIN_NT_FILE_SYSTEM=c:\foo!c:\bar
77 Declaring a text console window with the title "My EFI Console" woild look like:
78 EFI_WIN_NT_CONSOLE=My EFI Console
81 <width> <height>[!...]
83 Declaring a two GOP windows with resolutions of 800x600 and 1024x768 would look like:
84 Example : EFI_WIN_NT_GOP=800 600!1024 768
86 EFI_WIN_NT_SERIAL_PORT =
89 Declaring two serial ports on COM1 and COM2 would look like:
90 Example : EFI_WIN_NT_SERIAL_PORT=COM1!COM2
92 EFI_WIN_NT_PASS_THROUGH =
93 <BaseAddress>;<Bus#>;<Device#>;<Function#>
95 Declaring a base address of 0xE0000000 (used for PCI Express devices)
96 and having NT32 talk to a device located at bus 0, device 1, function 0:
97 Example : EFI_WIN_NT_PASS_THROUGH=E000000;0;1;0
102 // The package level header files this module uses
105 #include <WinNtDxe.h>
107 // The protocols, PPI and GUID defintions for this module
109 #include <Protocol/WinNtThunk.h>
110 #include <Protocol/WinNtIo.h>
111 #include <Protocol/ComponentName.h>
112 #include <Protocol/DriverBinding.h>
113 #include <Protocol/DevicePath.h>
115 // The Library classes this module consumes
117 #include <Library/DebugLib.h>
118 #include <Library/BaseLib.h>
119 #include <Library/UefiDriverEntryPoint.h>
120 #include <Library/UefiLib.h>
121 #include <Library/PcdLib.h>
122 #include <Library/BaseMemoryLib.h>
123 #include <Library/UefiBootServicesTableLib.h>
124 #include <Library/DevicePathLib.h>
125 #include <Library/MemoryAllocationLib.h>
127 #include "WinNtBusDriver.h"
129 extern EFI_GUID gWinNtBusDriverGuid
;
131 // DriverBinding protocol global
133 EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding
= {
134 WinNtBusDriverBindingSupported
,
135 WinNtBusDriverBindingStart
,
136 WinNtBusDriverBindingStop
,
142 #define NT_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(NT_PCD_ENTRY))
145 // Table to map NT Environment variable to the GUID that should be in
148 NT_PCD_ENTRY mPcdEnvironment
[] = {
149 PcdToken(PcdWinNtConsole
), &gEfiWinNtConsoleGuid
,
150 PcdToken(PcdWinNtGop
), &gEfiWinNtGopGuid
,
151 PcdToken(PcdWinNtSerialPort
), &gEfiWinNtSerialPortGuid
,
152 PcdToken(PcdWinNtFileSystem
), &gEfiWinNtFileSystemGuid
,
153 PcdToken(PcdWinNtVirtualDisk
), &gEfiWinNtVirtualDisksGuid
,
154 PcdToken(PcdWinNtPhysicalDisk
), &gEfiWinNtPhysicalDisksGuid
158 The user Entry Point for module WinNtBusDriver. The user code starts with this function.
160 @param[in] ImageHandle The firmware allocated handle for the EFI image.
161 @param[in] SystemTable A pointer to the EFI System Table.
163 @retval EFI_SUCCESS The entry point is executed successfully.
164 @retval other Some error occurs when executing this entry point.
169 InitializeWinNtBusDriver(
170 IN EFI_HANDLE ImageHandle
,
171 IN EFI_SYSTEM_TABLE
*SystemTable
177 // Install driver model protocol(s).
179 Status
= EfiLibInstallDriverBindingComponentName2 (
182 &gWinNtBusDriverBinding
,
184 &gWinNtBusDriverComponentName
,
185 &gWinNtBusDriverComponentName2
187 ASSERT_EFI_ERROR (Status
);
200 Buffer
= AllocatePool (Size
);
201 ASSERT (Buffer
!= NULL
);
209 WinNtBusDriverBindingSupported (
210 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
211 IN EFI_HANDLE ControllerHandle
,
212 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
225 // TODO: This - add argument and description to function comment
226 // TODO: ControllerHandle - add argument and description to function comment
227 // TODO: RemainingDevicePath - add argument and description to function comment
228 // TODO: EFI_UNSUPPORTED - add return value to function comment
229 // TODO: EFI_UNSUPPORTED - add return value to function comment
230 // TODO: EFI_SUCCESS - add return value to function comment
231 // TODO: EFI_SUCCESS - add return value to function comment
234 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
235 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
239 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
240 // it is a legal Device Path Node for this bus driver's children.
242 if (RemainingDevicePath
!= NULL
) {
244 // Check if RemainingDevicePath is the End of Device Path Node,
245 // if yes, go on checking other conditions
247 if (!IsDevicePathEnd (RemainingDevicePath
)) {
249 // If RemainingDevicePath isn't the End of Device Path Node,
250 // check its validation
252 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
253 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
254 DevicePathNodeLength(RemainingDevicePath
) != sizeof(WIN_NT_VENDOR_DEVICE_PATH_NODE
)) {
255 return EFI_UNSUPPORTED
;
258 for (Index
= 0; Index
< NT_PCD_ARRAY_SIZE
; Index
++) {
259 if (CompareGuid (&((VENDOR_DEVICE_PATH
*) RemainingDevicePath
)->Guid
, mPcdEnvironment
[Index
].DevicePathGuid
)) {
264 if (Index
>= NT_PCD_ARRAY_SIZE
) {
265 return EFI_UNSUPPORTED
;
271 // Open the IO Abstraction(s) needed to perform the supported test
273 Status
= gBS
->OpenProtocol (
275 &gEfiWinNtThunkProtocolGuid
,
276 (VOID
**) &WinNtThunk
,
277 This
->DriverBindingHandle
,
279 EFI_OPEN_PROTOCOL_BY_DRIVER
281 if (Status
== EFI_ALREADY_STARTED
) {
285 if (EFI_ERROR (Status
)) {
290 // Close the I/O Abstraction(s) used to perform the supported test
294 &gEfiWinNtThunkProtocolGuid
,
295 This
->DriverBindingHandle
,
300 // Open the EFI Device Path protocol needed to perform the supported test
302 Status
= gBS
->OpenProtocol (
304 &gEfiDevicePathProtocolGuid
,
305 (VOID
**) &ParentDevicePath
,
306 This
->DriverBindingHandle
,
308 EFI_OPEN_PROTOCOL_BY_DRIVER
310 if (Status
== EFI_ALREADY_STARTED
) {
314 if (EFI_ERROR (Status
)) {
319 // Since we call through WinNtThunk we need to make sure it's valid
321 Status
= EFI_SUCCESS
;
322 if (WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
323 Status
= EFI_UNSUPPORTED
;
327 // Close protocol, don't use device path protocol in the Support() function
331 &gEfiDevicePathProtocolGuid
,
332 This
->DriverBindingHandle
,
341 WinNtBusDriverBindingStart (
342 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
343 IN EFI_HANDLE ControllerHandle
,
344 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
357 // TODO: This - add argument and description to function comment
358 // TODO: ControllerHandle - add argument and description to function comment
359 // TODO: RemainingDevicePath - add argument and description to function comment
360 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
361 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
362 // TODO: EFI_SUCCESS - add return value to function comment
365 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
366 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
367 WIN_NT_BUS_DEVICE
*WinNtBusDevice
;
368 WIN_NT_IO_DEVICE
*WinNtDevice
;
374 UINT16 ComponentName
[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH
];
375 WIN_NT_VENDOR_DEVICE_PATH_NODE
*Node
;
376 BOOLEAN CreateDevice
;
381 Status
= EFI_UNSUPPORTED
;
384 // Grab the protocols we need
386 Status
= gBS
->OpenProtocol (
388 &gEfiDevicePathProtocolGuid
,
389 (VOID
**) &ParentDevicePath
,
390 This
->DriverBindingHandle
,
392 EFI_OPEN_PROTOCOL_BY_DRIVER
394 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
398 Status
= gBS
->OpenProtocol (
400 &gEfiWinNtThunkProtocolGuid
,
401 (VOID
**) &WinNtThunk
,
402 This
->DriverBindingHandle
,
404 EFI_OPEN_PROTOCOL_BY_DRIVER
406 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
410 if (Status
!= EFI_ALREADY_STARTED
) {
411 WinNtBusDevice
= AllocatePool (sizeof (WIN_NT_BUS_DEVICE
));
412 if (WinNtBusDevice
== NULL
) {
413 return EFI_OUT_OF_RESOURCES
;
416 WinNtBusDevice
->Signature
= WIN_NT_BUS_DEVICE_SIGNATURE
;
417 WinNtBusDevice
->ControllerNameTable
= NULL
;
421 gWinNtBusDriverComponentName
.SupportedLanguages
,
422 &WinNtBusDevice
->ControllerNameTable
,
423 L
"Windows Bus Controller",
428 gWinNtBusDriverComponentName2
.SupportedLanguages
,
429 &WinNtBusDevice
->ControllerNameTable
,
430 L
"Windows Bus Controller",
435 Status
= gBS
->InstallMultipleProtocolInterfaces (
437 &gWinNtBusDriverGuid
,
441 if (EFI_ERROR (Status
)) {
442 FreeUnicodeStringTable (WinNtBusDevice
->ControllerNameTable
);
443 FreePool (WinNtBusDevice
);
449 // Loop on the Variable list. Parse each variable to produce a set of handles that
450 // represent virtual hardware devices.
452 for (Index
= 0; Index
< NT_PCD_ARRAY_SIZE
; Index
++) {
453 PcdTempStr
= (VOID
*)LibPcdGetPtr (mPcdEnvironment
[Index
].Token
);
454 ASSERT (PcdTempStr
!= NULL
);
456 TempStrSize
= StrLen (PcdTempStr
);
457 TempStr
= AllocateMemory (((TempStrSize
+ 1) * sizeof (CHAR16
)));
458 StrCpy (TempStr
, PcdTempStr
);
460 StartString
= TempStr
;
463 // Parse the envirnment variable into sub strings using '!' as a delimator.
464 // Each substring needs it's own handle to be added to the system. This code
465 // does not understand the sub string. Thats the device drivers job.
468 while (*StartString
!= '\0') {
471 // Find the end of the sub string
473 SubString
= StartString
;
474 while (*SubString
!= '\0' && *SubString
!= '!') {
478 if (*SubString
== '!') {
480 // Replace token with '\0' to make sub strings. If this is the end
481 // of the string SubString will already point to NULL.
488 if (RemainingDevicePath
!= NULL
) {
489 CreateDevice
= FALSE
;
491 // Check if RemainingDevicePath is the End of Device Path Node,
492 // if yes, don't create any child device
494 if (!IsDevicePathEnd (RemainingDevicePath
)) {
496 // If RemainingDevicePath isn't the End of Device Path Node,
497 // check its validation
499 Node
= (WIN_NT_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
500 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
501 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
502 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE
)
504 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, mPcdEnvironment
[Index
].DevicePathGuid
) &&
505 Node
->Instance
== Count
516 // Allocate instance structure, and fill in parent information.
518 WinNtDevice
= AllocateMemory (sizeof (WIN_NT_IO_DEVICE
));
519 if (WinNtDevice
== NULL
) {
520 return EFI_OUT_OF_RESOURCES
;
523 WinNtDevice
->Handle
= NULL
;
524 WinNtDevice
->ControllerHandle
= ControllerHandle
;
525 WinNtDevice
->ParentDevicePath
= ParentDevicePath
;
527 WinNtDevice
->WinNtIo
.WinNtThunk
= WinNtThunk
;
530 // Plus 2 to account for the NULL at the end of the Unicode string
532 StringSize
= (UINTN
) ((UINT8
*) SubString
- (UINT8
*) StartString
) + sizeof (CHAR16
);
533 WinNtDevice
->WinNtIo
.EnvString
= AllocateMemory (StringSize
);
534 if (WinNtDevice
->WinNtIo
.EnvString
!= NULL
) {
535 CopyMem (WinNtDevice
->WinNtIo
.EnvString
, StartString
, StringSize
);
538 WinNtDevice
->ControllerNameTable
= NULL
;
540 WinNtThunk
->SPrintf (ComponentName
, sizeof (ComponentName
), L
"%s", WinNtDevice
->WinNtIo
.EnvString
);
542 WinNtDevice
->DevicePath
= WinNtBusCreateDevicePath (
544 mPcdEnvironment
[Index
].DevicePathGuid
,
547 if (WinNtDevice
->DevicePath
== NULL
) {
548 FreePool (WinNtDevice
);
549 return EFI_OUT_OF_RESOURCES
;
554 gWinNtBusDriverComponentName
.SupportedLanguages
,
555 &WinNtDevice
->ControllerNameTable
,
561 gWinNtBusDriverComponentName2
.SupportedLanguages
,
562 &WinNtDevice
->ControllerNameTable
,
568 WinNtDevice
->WinNtIo
.TypeGuid
= mPcdEnvironment
[Index
].DevicePathGuid
;
569 WinNtDevice
->WinNtIo
.InstanceNumber
= Count
;
571 WinNtDevice
->Signature
= WIN_NT_IO_DEVICE_SIGNATURE
;
573 Status
= gBS
->InstallMultipleProtocolInterfaces (
574 &WinNtDevice
->Handle
,
575 &gEfiDevicePathProtocolGuid
,
576 WinNtDevice
->DevicePath
,
577 &gEfiWinNtIoProtocolGuid
,
578 &WinNtDevice
->WinNtIo
,
581 if (EFI_ERROR (Status
)) {
582 FreeUnicodeStringTable (WinNtDevice
->ControllerNameTable
);
583 FreePool (WinNtDevice
);
586 // Open For Child Device
588 Status
= gBS
->OpenProtocol (
590 &gEfiWinNtThunkProtocolGuid
,
591 (VOID
**) &WinNtThunk
,
592 This
->DriverBindingHandle
,
594 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
600 // Parse Next sub string. This will point to '\0' if we are at the end.
603 StartString
= SubString
;
615 WinNtBusDriverBindingStop (
616 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
617 IN EFI_HANDLE ControllerHandle
,
618 IN UINTN NumberOfChildren
,
619 IN EFI_HANDLE
*ChildHandleBuffer
632 // TODO: This - add argument and description to function comment
633 // TODO: ControllerHandle - add argument and description to function comment
634 // TODO: NumberOfChildren - add argument and description to function comment
635 // TODO: ChildHandleBuffer - add argument and description to function comment
636 // TODO: EFI_SUCCESS - add return value to function comment
637 // TODO: EFI_DEVICE_ERROR - add return value to function comment
638 // TODO: EFI_SUCCESS - add return value to function comment
642 BOOLEAN AllChildrenStopped
;
643 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
644 WIN_NT_BUS_DEVICE
*WinNtBusDevice
;
645 WIN_NT_IO_DEVICE
*WinNtDevice
;
646 EFI_WIN_NT_THUNK_PROTOCOL
*WinNtThunk
;
649 // Complete all outstanding transactions to Controller.
650 // Don't allow any new transaction to Controller to be started.
653 if (NumberOfChildren
== 0) {
655 // Close the bus driver
657 Status
= gBS
->OpenProtocol (
659 &gWinNtBusDriverGuid
,
660 (VOID
**) &WinNtBusDevice
,
661 This
->DriverBindingHandle
,
663 EFI_OPEN_PROTOCOL_GET_PROTOCOL
665 if (EFI_ERROR (Status
)) {
669 gBS
->UninstallMultipleProtocolInterfaces (
671 &gWinNtBusDriverGuid
,
676 FreeUnicodeStringTable (WinNtBusDevice
->ControllerNameTable
);
678 FreePool (WinNtBusDevice
);
682 &gEfiWinNtThunkProtocolGuid
,
683 This
->DriverBindingHandle
,
689 &gEfiDevicePathProtocolGuid
,
690 This
->DriverBindingHandle
,
696 AllChildrenStopped
= TRUE
;
698 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
700 Status
= gBS
->OpenProtocol (
701 ChildHandleBuffer
[Index
],
702 &gEfiWinNtIoProtocolGuid
,
704 This
->DriverBindingHandle
,
706 EFI_OPEN_PROTOCOL_GET_PROTOCOL
708 if (!EFI_ERROR (Status
)) {
710 WinNtDevice
= WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo
);
712 Status
= gBS
->CloseProtocol (
714 &gEfiWinNtThunkProtocolGuid
,
715 This
->DriverBindingHandle
,
719 Status
= gBS
->UninstallMultipleProtocolInterfaces (
721 &gEfiDevicePathProtocolGuid
,
722 WinNtDevice
->DevicePath
,
723 &gEfiWinNtIoProtocolGuid
,
724 &WinNtDevice
->WinNtIo
,
728 if (EFI_ERROR (Status
)) {
731 &gEfiWinNtThunkProtocolGuid
,
732 (VOID
**) &WinNtThunk
,
733 This
->DriverBindingHandle
,
735 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
739 // Close the child handle
741 FreeUnicodeStringTable (WinNtDevice
->ControllerNameTable
);
742 FreePool (WinNtDevice
);
746 if (EFI_ERROR (Status
)) {
747 AllChildrenStopped
= FALSE
;
751 if (!AllChildrenStopped
) {
752 return EFI_DEVICE_ERROR
;
758 EFI_DEVICE_PATH_PROTOCOL
*
759 WinNtBusCreateDevicePath (
760 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
762 IN UINT16 InstanceNumber
767 Create a device path node using Guid and InstanceNumber and append it to
768 the passed in RootDevicePath
771 RootDevicePath - Root of the device path to return.
773 Guid - GUID to use in vendor device path node.
775 InstanceNumber - Instance number to use in the vendor device path. This
776 argument is needed to make sure each device path is unique.
780 EFI_DEVICE_PATH_PROTOCOL
784 WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath
;
786 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
787 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
788 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE
));
791 // The GUID defines the Class
793 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
796 // Add an instance number so we can make sure there are no Device Path
799 DevicePath
.Instance
= InstanceNumber
;
801 return AppendDevicePathNode (
803 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath