3 * Copyright (c) 2011, ARM Limited. All rights reserved.
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.
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/UefiLib.h>
20 #include <Library/PerformanceLib.h>
21 #include <Library/UefiRuntimeServicesTableLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/BdsLinuxLib.h>
25 #include <Protocol/Bds.h>
26 #include <Protocol/DevicePathToText.h>
28 #include <Guid/GlobalVariable.h>
30 #define MAX_CMD_LINE 256
35 IN EFI_BDS_ARCH_PROTOCOL
*This
38 EFI_HANDLE mBdsImageHandle
= NULL
;
39 EFI_BDS_ARCH_PROTOCOL gBdsProtocol
= {
43 EFI_STATUS
GetEnvironmentVariable (
44 IN CONST CHAR16
* VariableName
,
45 IN VOID
* DefaultValue
,
52 // Try to get the variable size.
55 Status
= gRT
->GetVariable ((CHAR16
*) VariableName
, &gEfiGlobalVariableGuid
, NULL
, &Size
, *Value
);
56 if (Status
== EFI_NOT_FOUND
) {
57 // If the environment variable does not exist yet then set it with the default value
58 Status
= gRT
->SetVariable (
59 (CHAR16
*)VariableName
,
60 &gEfiGlobalVariableGuid
,
61 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
65 *Value
= DefaultValue
;
66 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
67 // Get the environment variable value
68 *Value
= AllocatePool (Size
);
70 return EFI_OUT_OF_RESOURCES
;
73 Status
= gRT
->GetVariable ((CHAR16
*)VariableName
, &gEfiGlobalVariableGuid
, NULL
, &Size
, *Value
);
74 if (EFI_ERROR (Status
)) {
76 return EFI_INVALID_PARAMETER
;
79 *Value
= DefaultValue
;
86 VOID
InitializeConsole (
95 // Now we need to setup the EFI System Table with information about the console devices.
96 // This code is normally in the console spliter driver on platforms that support multiple
97 // consoles at the same time
99 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiSimpleTextOutProtocolGuid
, NULL
, &NoHandles
, &Buffer
);
100 if (!EFI_ERROR (Status
)) {
101 // Use the first SimpleTextOut we find and update the EFI System Table
102 gST
->ConsoleOutHandle
= Buffer
[0];
103 gST
->StandardErrorHandle
= Buffer
[0];
104 Status
= gBS
->HandleProtocol (Buffer
[0], &gEfiSimpleTextOutProtocolGuid
, (VOID
**)&gST
->ConOut
);
105 ASSERT_EFI_ERROR (Status
);
107 gST
->StdErr
= gST
->ConOut
;
112 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiSimpleTextInProtocolGuid
, NULL
, &NoHandles
, &Buffer
);
113 if (!EFI_ERROR (Status
)) {
114 // Use the first SimpleTextIn we find and update the EFI System Table
115 gST
->ConsoleInHandle
= Buffer
[0];
116 Status
= gBS
->HandleProtocol (Buffer
[0], &gEfiSimpleTextInProtocolGuid
, (VOID
**)&gST
->ConIn
);
117 ASSERT_EFI_ERROR (Status
);
136 for (CmdLineIndex
= 0; CmdLineIndex
< MaxCmdLine
; ) {
137 Status
= gBS
->WaitForEvent (1, &gST
->ConIn
->WaitForKey
, &WaitIndex
);
138 ASSERT_EFI_ERROR (Status
);
140 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
141 ASSERT_EFI_ERROR (Status
);
143 Char
= (CHAR8
)Key
.UnicodeChar
;
144 if ((Char
== '\n') || (Char
== '\r') || (Char
== 0x7f)) {
145 CmdLine
[CmdLineIndex
] = '\0';
148 } else if ((Char
== '\b') || (Key
.ScanCode
== SCAN_LEFT
) || (Key
.ScanCode
== SCAN_DELETE
)){
149 if (CmdLineIndex
!= 0) {
151 AsciiPrint ("\b \b");
154 CmdLine
[CmdLineIndex
++] = Char
;
155 AsciiPrint ("%c", Char
);
164 IN BOOLEAN AllDrivers
168 EFI_HANDLE
*HandleBuffer
;
170 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
172 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* EfiDevicePathToTextProtocol
;
175 BdsConnectAllDrivers();
178 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&EfiDevicePathToTextProtocol
);
179 if (EFI_ERROR (Status
)) {
180 AsciiPrint ("Did not find the DevicePathToTextProtocol.\n");
184 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDevicePathProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
185 if (EFI_ERROR (Status
)) {
186 AsciiPrint ("No device path found\n");
190 for (Index
= 0; Index
< HandleCount
; Index
++) {
191 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
192 String
= EfiDevicePathToTextProtocol
->ConvertDevicePathToText(DevicePathProtocol
,TRUE
,TRUE
);
193 Print (L
"\t- [%d] %s\n",Index
, String
);
197 INTN
BdsComparefile (
198 IN CHAR16
*DeviceFilePath1
,
199 IN CHAR16
*DeviceFilePath2
,
200 VOID
**FileImage1
,VOID
**FileImage2
,UINTN
* FileSize
204 This function uses policy data from the platform to determine what operating
205 system or system utility should be loaded and invoked. This function call
206 also optionally make the use of user input to determine the operating system
207 or system utility to be loaded and invoked. When the DXE Core has dispatched
208 all the drivers on the dispatch queue, this function is called. This
209 function will attempt to connect the boot devices required to load and invoke
210 the selected operating system or system utility. During this process,
211 additional firmware volumes may be discovered that may contain addition DXE
212 drivers that can be dispatched by the DXE Core. If a boot device cannot be
213 fully connected, this function calls the DXE Service Dispatch() to allow the
214 DXE drivers from any newly discovered firmware volumes to be dispatched.
215 Then the boot device connection can be attempted again. If the same boot
216 device connection operation fails twice in a row, then that boot device has
217 failed, and should be skipped. This function should never return.
219 @param This The EFI_BDS_ARCH_PROTOCOL instance.
227 IN EFI_BDS_ARCH_PROTOCOL
*This
231 CHAR8 CmdLine
[MAX_CMD_LINE
];
232 VOID
* DefaultVariableValue
;
233 UINTN DefaultVariableSize
;
234 CHAR16
*LinuxKernelDP
;
238 PERF_END (NULL
, "DXE", NULL
, 0);
239 PERF_START (NULL
, "BDS", NULL
, 0);
244 // Get the Linux Kernel Device Path from Environment Variable
245 DefaultVariableValue
= (VOID
*)PcdGetPtr(PcdLinuxKernelDP
);
246 DefaultVariableSize
= StrSize((CHAR16
*)DefaultVariableValue
);
247 GetEnvironmentVariable(L
"LinuxKernelDP",DefaultVariableValue
,DefaultVariableSize
,(VOID
**)&LinuxKernelDP
);
249 // Get the Linux ATAG from Environment Variable
250 DefaultVariableValue
= (VOID
*)PcdGetPtr(PcdLinuxAtag
);
251 DefaultVariableSize
= AsciiStrSize((CHAR8
*)DefaultVariableValue
);
252 GetEnvironmentVariable(L
"LinuxAtag",DefaultVariableValue
,DefaultVariableSize
,(VOID
**)&LinuxAtag
);
254 // Get the FDT Device Path from Environment Variable
255 DefaultVariableValue
= (VOID
*)PcdGetPtr(PcdFdtDP
);
256 DefaultVariableSize
= StrSize((CHAR16
*)DefaultVariableValue
);
257 GetEnvironmentVariable(L
"FdtDP",DefaultVariableValue
,DefaultVariableSize
,(VOID
**)&FdtDP
);
259 AsciiPrint ("1. Start EBL\n\r");
260 AsciiPrint ("2. List Device Paths of all the drivers\n");
261 AsciiPrint ("3. Start Linux\n");
262 Print (L
"\t- Kernel: %s\n", LinuxKernelDP
);
263 AsciiPrint ("\t- Atag: %a\n", LinuxAtag
);
264 Print (L
"\t- Fdt: %s\n", FdtDP
);
265 AsciiPrint ("Choice: ");
267 Status
= GetHIInputAscii(CmdLine
,MAX_CMD_LINE
);
268 ASSERT_EFI_ERROR (Status
);
269 if (AsciiStrCmp(CmdLine
,"1") == 0) {
271 Status
= BdsLoadApplication(L
"Ebl");
272 if (Status
== EFI_NOT_FOUND
) {
273 AsciiPrint ("Error: EFI Application not found.\n");
275 AsciiPrint ("Error: Status Code: 0x%X\n",(UINT32
)Status
);
277 } else if (AsciiStrCmp(CmdLine
,"2") == 0) {
278 ListDevicePaths (TRUE
);
279 } else if (AsciiStrCmp(CmdLine
,"3") == 0) {
280 // Start Linux Kernel
281 Status
= BdsBootLinux(LinuxKernelDP
,LinuxAtag
,FdtDP
);
282 if (EFI_ERROR(Status
)) {
283 AsciiPrint ("Error: Fail to start Linux (0x%X)\n",(UINT32
)Status
);
286 AsciiPrint ("Error: Invalid choice.\n");
294 IN EFI_HANDLE ImageHandle
,
295 IN EFI_SYSTEM_TABLE
*SystemTable
300 mBdsImageHandle
= ImageHandle
;
302 Status
= gBS
->InstallMultipleProtocolInterfaces (
304 &gEfiBdsArchProtocolGuid
, &gBdsProtocol
,
307 ASSERT_EFI_ERROR (Status
);