]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BdsEntry.c
ArmPlatformPkg/ArmPlatformLib: Move the UEFI memory partionning to MemoryInitPei
[mirror_edk2.git] / ArmPlatformPkg / Bds / BdsEntry.c
CommitLineData
1d5d0ae9 1/** @file
2*
3* Copyright (c) 2011, ARM Limited. All rights reserved.
4*
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
9*
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.
12*
13**/
14
15#include <PiDxe.h>
1d5d0ae9 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>
6111eb85 23#include <Library/BdsLinuxLib.h>
1d5d0ae9 24
25#include <Protocol/Bds.h>
26#include <Protocol/DevicePathToText.h>
27
28#include <Guid/GlobalVariable.h>
29
30#define MAX_CMD_LINE 256
31
32VOID
33EFIAPI
34BdsEntry (
35 IN EFI_BDS_ARCH_PROTOCOL *This
36 );
37
38EFI_HANDLE mBdsImageHandle = NULL;
39EFI_BDS_ARCH_PROTOCOL gBdsProtocol = {
40 BdsEntry,
41};
42
43EFI_STATUS GetEnvironmentVariable (
44 IN CONST CHAR16* VariableName,
45 IN VOID* DefaultValue,
46 IN UINTN DefaultSize,
47 OUT VOID** Value)
48{
49 EFI_STATUS Status;
50 UINTN Size;
51
52 // Try to get the variable size.
53 *Value = NULL;
54 Size = 0;
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,
62 DefaultSize,
63 DefaultValue
64 );
65 *Value = DefaultValue;
66 } else if (Status == EFI_BUFFER_TOO_SMALL) {
67 // Get the environment variable value
68 *Value = AllocatePool (Size);
69 if (*Value == NULL) {
70 return EFI_OUT_OF_RESOURCES;
71 }
72
73 Status = gRT->GetVariable ((CHAR16 *)VariableName, &gEfiGlobalVariableGuid, NULL, &Size, *Value);
74 if (EFI_ERROR (Status)) {
75 FreePool(*Value);
76 return EFI_INVALID_PARAMETER;
77 }
78 } else {
79 *Value = DefaultValue;
80 return Status;
81 }
82
83 return EFI_SUCCESS;
84}
85
86VOID InitializeConsole (
87 VOID
88 )
89{
90 EFI_STATUS Status;
91 UINTN NoHandles;
92 EFI_HANDLE *Buffer;
93
94 //
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
98 //
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);
106
107 gST->StdErr = gST->ConOut;
108
109 FreePool (Buffer);
110 }
111
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);
118
119 FreePool (Buffer);
120 }
121}
122
123EFI_STATUS
124GetHIInputAscii (
125 CHAR8 *CmdLine,
126 UINTN MaxCmdLine
127) {
128 UINTN CmdLineIndex;
129 UINTN WaitIndex;
130 CHAR8 Char;
131 EFI_INPUT_KEY Key;
132 EFI_STATUS Status;
133
134 CmdLine[0] = '\0';
135
136 for (CmdLineIndex = 0; CmdLineIndex < MaxCmdLine; ) {
137 Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);
138 ASSERT_EFI_ERROR (Status);
139
140 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
141 ASSERT_EFI_ERROR (Status);
142
143 Char = (CHAR8)Key.UnicodeChar;
144 if ((Char == '\n') || (Char == '\r') || (Char == 0x7f)) {
145 CmdLine[CmdLineIndex] = '\0';
146 AsciiPrint ("\n");
147 return EFI_SUCCESS;
148 } else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){
149 if (CmdLineIndex != 0) {
150 CmdLineIndex--;
151 AsciiPrint ("\b \b");
152 }
153 } else {
154 CmdLine[CmdLineIndex++] = Char;
155 AsciiPrint ("%c", Char);
156 }
157 }
158
159 return EFI_SUCCESS;
160}
161
162VOID
163ListDevicePaths (
164 IN BOOLEAN AllDrivers
165) {
166 EFI_STATUS Status;
167 UINTN HandleCount;
168 EFI_HANDLE *HandleBuffer;
169 UINTN Index;
170 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol;
171 CHAR16* String;
172 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* EfiDevicePathToTextProtocol;
173
174 if (AllDrivers) {
175 BdsConnectAllDrivers();
176 }
177
178 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&EfiDevicePathToTextProtocol);
179 if (EFI_ERROR (Status)) {
180 AsciiPrint ("Did not find the DevicePathToTextProtocol.\n");
181 return;
182 }
183
184 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &HandleCount, &HandleBuffer);
185 if (EFI_ERROR (Status)) {
186 AsciiPrint ("No device path found\n");
187 return;
188 }
189
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);
194 }
195}
196
197INTN BdsComparefile (
198 IN CHAR16 *DeviceFilePath1,
199 IN CHAR16 *DeviceFilePath2,
200 VOID **FileImage1,VOID **FileImage2,UINTN* FileSize
201 );
202
203/**
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.
218
219 @param This The EFI_BDS_ARCH_PROTOCOL instance.
220
221 @return None.
222
223**/
224VOID
225EFIAPI
226BdsEntry (
227 IN EFI_BDS_ARCH_PROTOCOL *This
228 )
229{
230 EFI_STATUS Status;
231 CHAR8 CmdLine[MAX_CMD_LINE];
232 VOID* DefaultVariableValue;
233 UINTN DefaultVariableSize;
234 CHAR16 *LinuxKernelDP;
235 CHAR8 *LinuxAtag;
236 CHAR16 *FdtDP;
237
238 PERF_END (NULL, "DXE", NULL, 0);
239 PERF_START (NULL, "BDS", NULL, 0);
240
241 InitializeConsole();
242
243 while (1) {
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);
248
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);
253
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);
258
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: ");
266
267 Status = GetHIInputAscii(CmdLine,MAX_CMD_LINE);
268 ASSERT_EFI_ERROR (Status);
269 if (AsciiStrCmp(CmdLine,"1") == 0) {
270 // Start EBL
271 Status = BdsLoadApplication(L"Ebl");
272 if (Status == EFI_NOT_FOUND) {
273 AsciiPrint ("Error: EFI Application not found.\n");
274 } else {
275 AsciiPrint ("Error: Status Code: 0x%X\n",(UINT32)Status);
276 }
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);
284 }
285 } else {
286 AsciiPrint ("Error: Invalid choice.\n");
287 }
288 }
289}
290
291EFI_STATUS
292EFIAPI
293BdsInitialize (
294 IN EFI_HANDLE ImageHandle,
295 IN EFI_SYSTEM_TABLE *SystemTable
296 )
297{
298 EFI_STATUS Status;
299
300 mBdsImageHandle = ImageHandle;
301
302 Status = gBS->InstallMultipleProtocolInterfaces (
303 &mBdsImageHandle,
304 &gEfiBdsArchProtocolGuid, &gBdsProtocol,
305 NULL
306 );
307 ASSERT_EFI_ERROR (Status);
308
309 return Status;
310}