--- /dev/null
+/** @file\r
+ The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements \r
+ of the UEFI specification as it is designed to implement an embedded systmes \r
+ propriatary boot scheme.\r
+\r
+ This template assume a DXE driver produces a SerialIo protocol not using the EFI \r
+ driver module and it will attempt to connect a console on top of this.\r
+\r
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "BdsEntry.h"\r
+\r
+\r
+BOOLEAN gConsolePresent = FALSE;\r
+\r
+\r
+EFI_HANDLE mBdsImageHandle = NULL;\r
+EFI_BDS_ARCH_PROTOCOL gBdsProtocol = {\r
+ BdsEntry,\r
+};\r
+\r
+\r
+ \r
+ \r
+/**\r
+ This function uses policy data from the platform to determine what operating \r
+ system or system utility should be loaded and invoked. This function call \r
+ also optionally make the use of user input to determine the operating system \r
+ or system utility to be loaded and invoked. When the DXE Core has dispatched \r
+ all the drivers on the dispatch queue, this function is called. This \r
+ function will attempt to connect the boot devices required to load and invoke \r
+ the selected operating system or system utility. During this process, \r
+ additional firmware volumes may be discovered that may contain addition DXE \r
+ drivers that can be dispatched by the DXE Core. If a boot device cannot be \r
+ fully connected, this function calls the DXE Service Dispatch() to allow the \r
+ DXE drivers from any newly discovered firmware volumes to be dispatched. \r
+ Then the boot device connection can be attempted again. If the same boot \r
+ device connection operation fails twice in a row, then that boot device has \r
+ failed, and should be skipped. This function should never return.\r
+\r
+ @param This The EFI_BDS_ARCH_PROTOCOL instance.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsEntry (\r
+ IN EFI_BDS_ARCH_PROTOCOL *This\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN NoHandles;\r
+ EFI_HANDLE *Buffer;\r
+ EFI_HANDLE FvHandle;\r
+ EFI_HANDLE ImageHandle;\r
+ EFI_HANDLE UsbDeviceHandle;\r
+ EFI_GUID NameGuid;\r
+ UINTN Size;\r
+ UINTN HandleCount;\r
+ UINTN OldHandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ EFI_DEVICE_PATH_PROTOCOL *LoadImageDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *FileSystemDevicePath;\r
+ \r
+ PERF_END (NULL, "DXE", NULL, 0);\r
+ PERF_START (NULL, "BDS", NULL, 0);\r
+\r
+\r
+ //\r
+ // Now do the EFI stuff\r
+ //\r
+ Size = 0x100;\r
+ gST->FirmwareVendor = AllocateRuntimePool (Size);\r
+ ASSERT (gST->FirmwareVendor != NULL);\r
+ \r
+ UnicodeSPrint (gST->FirmwareVendor, Size, L"BeagleBoard EFI %a %a", __DATE__, __TIME__);\r
+\r
+ //\r
+ // Now we need to setup the EFI System Table with information about the console devices.\r
+ // This code is normally in the console spliter driver on platforms that support multiple \r
+ // consoles at the same time\r
+ //\r
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &NoHandles, &Buffer);\r
+ if (!EFI_ERROR (Status)) {\r
+ // Use the first SimpleTextOut we find and update the EFI System Table\r
+ gST->ConsoleOutHandle = Buffer[0];\r
+ gST->StandardErrorHandle = Buffer[0];\r
+ Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextOutProtocolGuid, (VOID **)&gST->ConOut);\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ gST->StdErr = gST->ConOut;\r
+ \r
+ gST->ConOut->OutputString (gST->ConOut, L"BDS: Console Started!!!!\n\r");\r
+ FreePool (Buffer);\r
+ \r
+ gConsolePresent = TRUE;\r
+ } \r
+ \r
+\r
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInProtocolGuid, NULL, &NoHandles, &Buffer);\r
+ if (!EFI_ERROR (Status)) {\r
+ // Use the first SimpleTextIn we find and update the EFI System Table\r
+ gST->ConsoleInHandle = Buffer[0];\r
+ Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextInProtocolGuid, (VOID **)&gST->ConIn);\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ FreePool (Buffer);\r
+ }\r
+\r
+ //\r
+ // We now have EFI Consoles up and running. Print () will work now. DEBUG () and ASSERT () worked \r
+ // prior to this point as they were configured to use a more primative output scheme.\r
+ //\r
+\r
+ //\r
+ //Perform Connect\r
+ //\r
+ HandleCount = 0;\r
+ while (1) {\r
+ OldHandleCount = HandleCount;\r
+ Status = gBS->LocateHandleBuffer (\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ \r
+ if (HandleCount == OldHandleCount) {\r
+ break;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+ }\r
+ }\r
+\r
+ EfiSignalEventReadyToBoot ();\r
+\r
+ //Locate handles for SimpleFileSystem protocol\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ //Get the device path\r
+ FileSystemDevicePath = DevicePathFromHandle(HandleBuffer[Index]);\r
+ if (FileSystemDevicePath == NULL) {\r
+ continue;\r
+ }\r
+\r
+ //Check if UsbIo is on any handles in the device path.\r
+ Status = gBS->LocateDevicePath(&gEfiUsbIoProtocolGuid, &FileSystemDevicePath, &UsbDeviceHandle);\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ //Check if Usb stick has a magic EBL file.\r
+ LoadImageDevicePath = FileDevicePath(HandleBuffer[Index], L"Ebl.efi");\r
+ Status = gBS->LoadImage (TRUE, gImageHandle, LoadImageDevicePath, NULL, 0, &ImageHandle);\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ //Boot to Shell on USB stick.\r
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Normal UEFI behavior is to process Globally Defined Variables as defined in Chapter 3 \r
+ // (Boot Manager) of the UEFI specification. For this embedded system we don't do this.\r
+ //\r
+\r
+ //\r
+ // Search all the FVs for an application with a UI Section of Ebl. A .FDF file can be used\r
+ // to control the names of UI sections in an FV.\r
+ //\r
+ Status = FindApplicationMatchingUiSection (L"Ebl", &FvHandle, &NameGuid);\r
+ if (!EFI_ERROR (Status)) {\r
+\r
+ //Boot to Shell.\r
+ Status = LoadPeCoffSectionFromFv (FvHandle, &NameGuid);\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR, "Boot from Shell failed. Status: %r\n", Status));\r
+ }\r
+ }\r
+\r
+ //\r
+ // EFI does not define the behaviour if all boot attemps fail and the last one returns. \r
+ // So we make a policy choice to reset the system since this BDS does not have a UI.\r
+ //\r
+ gRT->ResetSystem (EfiResetShutdown, Status, 0, NULL);\r
+\r
+ return ;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+BdsInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ mBdsImageHandle = ImageHandle;\r
+\r
+ //\r
+ // Install protocol interface\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mBdsImageHandle,\r
+ &gEfiBdsArchProtocolGuid, &gBdsProtocol,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+\r