boot.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. boot.c
  5. Abstract:
  6. This module implements support for the first stage load on TI's AM335x
  7. Author:
  8. Evan Green 17-Dec-2014
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <uefifw.h>
  16. #include <uboot.h>
  17. #include "init.h"
  18. #include "util.h"
  19. //
  20. // ---------------------------------------------------------------- Definitions
  21. //
  22. #define AM335_MEMORY_DEVICE_DATA_BUFFER 0x80000000
  23. #define AM335_MEMORY_DEVICE_DATA_SIZE 2500
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. typedef
  28. INT32
  29. (*PAM335_BOOT_ENTRY_POINT) (
  30. UINT32 BootType,
  31. UINT32 Length
  32. );
  33. /*++
  34. Routine Description:
  35. This routine is the entry point for a booted option.
  36. Arguments:
  37. BootType - Supplies the boot device type.
  38. Length - Supplies the image length.
  39. Return Value:
  40. 0 on success.
  41. Non-zero on failure.
  42. --*/
  43. //
  44. // ----------------------------------------------- Internal Function Prototypes
  45. //
  46. INTN
  47. EfipAm335LoadFromSd (
  48. UINT8 DeviceType,
  49. UINT32 *Length
  50. );
  51. INTN
  52. EfipAm335BootImage (
  53. UINT32 BootDeviceType,
  54. UINT32 Image,
  55. UINT32 Length
  56. );
  57. UINT32
  58. EfipByteSwap32 (
  59. UINT32 Value
  60. );
  61. //
  62. // -------------------------------------------------------------------- Globals
  63. //
  64. //
  65. // Define the device version of the AM335x.
  66. //
  67. UINT32 EfiAm335DeviceVersion;
  68. TI_ROM_MEM_HANDLE EfiAm335RomMemHandle;
  69. BOOLEAN EfiSkipCrc;
  70. //
  71. // ------------------------------------------------------------------ Functions
  72. //
  73. VOID
  74. EfiFirstStageLoader (
  75. PAM335_BOOT_DATA BootData
  76. )
  77. /*++
  78. Routine Description:
  79. This routine implements the main C routine of the first stage loader. Its
  80. role is to load the primary firmware.
  81. Arguments:
  82. BootData - Supplies a pointer to the boot data structure created by the
  83. SoC ROM code.
  84. Return Value:
  85. None.
  86. --*/
  87. {
  88. UINT32 Length;
  89. UINT32 OppIndex;
  90. INTN Result;
  91. //
  92. // Store the device revision, used in a few places.
  93. //
  94. EfiAm335DeviceVersion =
  95. AM3_READ32(AM335_SOC_CONTROL_REGISTERS + AM335_SOC_CONTROL_DEVICE_ID) >>
  96. AM335_SOC_CONTROL_DEVICE_ID_REVISION_SHIFT;
  97. EfipAm335InitializeClocks();
  98. EfipBeagleBoneBlackInitializeLeds();
  99. EfipBeagleBoneBlackSetLeds(0x1);
  100. EfipAm335EnableUart();
  101. EfipInitializeBoardMux();
  102. EfipAm335ConfigureVddOpVoltage();
  103. OppIndex = EfipAm335GetMaxOpp();
  104. EfipAm335SetVdd1Voltage(EfiAm335OppTable[OppIndex].PmicVoltage);
  105. EfipAm335InitializePlls(OppIndex, AM335_DDR_PLL_M_DDR3);
  106. EfipAm335InitializeEmif();
  107. EfipBeagleBoneBlackInitializeDdr3();
  108. EfipSerialPrintString("\r\nMinoca Firmware Loader\r\nBoot Device: ");
  109. EfipSerialPrintHexInteger(BootData->BootDevice);
  110. EfipSerialPrintString("\r\n");
  111. Result = EfipAm335LoadFromSd(BootData->BootDevice, &Length);
  112. if (Result != 0) {
  113. EfipSerialPrintString("Load Error\r\n");
  114. } else {
  115. EfipAm335BootImage(BootData->BootDevice,
  116. AM335_SD_BOOT_ADDRESS,
  117. Length);
  118. }
  119. while (TRUE) {
  120. NOTHING;
  121. }
  122. return;
  123. }
  124. //
  125. // --------------------------------------------------------- Internal Functions
  126. //
  127. INTN
  128. EfipAm335LoadFromSd (
  129. UINT8 DeviceType,
  130. UINT32 *Length
  131. )
  132. /*++
  133. Routine Description:
  134. This routine loads the boot loader over SD.
  135. Arguments:
  136. DeviceType - Supplies the device type to boot from.
  137. Length - Supplies a pointer where the length of the loaded image will be
  138. returned on success.
  139. Return Value:
  140. 0 on success.
  141. Non-zero on failure.
  142. --*/
  143. {
  144. UINT32 Base;
  145. VOID *DeviceData;
  146. INTN Result;
  147. Base = AM335_PUBLIC_API_BASE;
  148. DeviceData = (VOID *)AM335_MEMORY_DEVICE_DATA_BUFFER;
  149. EfipInitZeroMemory(DeviceData, AM335_MEMORY_DEVICE_DATA_SIZE);
  150. Result = EfipTiMemOpen(DeviceType, Base, DeviceData, &EfiAm335RomMemHandle);
  151. if (Result != 0) {
  152. return Result;
  153. }
  154. Result = EfipTiLoadFirmwareFromFat(&EfiAm335RomMemHandle,
  155. AM335_FIRMWARE_NAME,
  156. (VOID *)AM335_SD_BOOT_ADDRESS,
  157. Length);
  158. if (Result != 0) {
  159. return Result;
  160. }
  161. return 0;
  162. }
  163. INTN
  164. EfipAm335BootImage (
  165. UINT32 BootDeviceType,
  166. UINT32 Image,
  167. UINT32 Length
  168. )
  169. /*++
  170. Routine Description:
  171. This routine boots a loaded image in memory.
  172. Arguments:
  173. BootDeviceType - Supplies the boot device type.
  174. Image - Supplies the address of the image.
  175. Length - Supplies the length of the image in bytes.
  176. Return Value:
  177. 0 on success. Actually, does not return on success.
  178. Non-zero on failure.
  179. --*/
  180. {
  181. UINT32 Crc;
  182. PAM335_BOOT_ENTRY_POINT EntryPoint;
  183. UINT32 HeaderDataCrc;
  184. UINT32 LoadAddress;
  185. INTN Result;
  186. PUBOOT_HEADER UbootHeader;
  187. //
  188. // Check for the U-Boot header.
  189. //
  190. EfipInitializeCrc32((VOID *)BEAGLEBONE_CRC_TABLE_ADDRESS);
  191. UbootHeader = (PUBOOT_HEADER)(UINTN)Image;
  192. if (EfipByteSwap32(UbootHeader->Magic) == UBOOT_MAGIC) {
  193. LoadAddress = EfipByteSwap32(UbootHeader->DataLoadAddress);
  194. if (LoadAddress != Image + sizeof(UBOOT_HEADER)) {
  195. EfipSerialPrintString("Warning: U-boot load address ");
  196. EfipSerialPrintHexInteger(LoadAddress);
  197. EfipSerialPrintString(" but expected ");
  198. EfipSerialPrintHexInteger(Image + sizeof(UBOOT_HEADER));
  199. EfipSerialPrintString("\n");
  200. }
  201. EntryPoint = (VOID *)EfipByteSwap32(UbootHeader->EntryPoint);
  202. EfipSerialPrintString("Launching ");
  203. EfipSerialPrintString(UbootHeader->ImageName);
  204. EfipSerialPrintString(".\n");
  205. EfiSkipCrc = TRUE;
  206. if (EfiSkipCrc == FALSE) {
  207. Crc = EfipInitCalculateCrc32((VOID *)Image + sizeof(UBOOT_HEADER),
  208. EfipByteSwap32(UbootHeader->DataSize));
  209. HeaderDataCrc = EfipByteSwap32(UbootHeader->DataCrc32);
  210. if (Crc != HeaderDataCrc) {
  211. EfipSerialPrintString("Error: CRC was ");
  212. EfipSerialPrintHexInteger(Crc);
  213. EfipSerialPrintString(", header value was ");
  214. EfipSerialPrintHexInteger(HeaderDataCrc);
  215. EfipSerialPrintString(".\n");
  216. return 0x44;
  217. }
  218. }
  219. } else {
  220. EntryPoint = (PAM335_BOOT_ENTRY_POINT)Image;
  221. }
  222. //
  223. // Set the LEDs to 2 to indicate transition out of the first stage loader.
  224. //
  225. EfipBeagleBoneBlackSetLeds(0x2);
  226. EfipSerialPrintString("Jumping to ");
  227. EfipSerialPrintHexInteger((UINT32)EntryPoint);
  228. EfipSerialPrintString("...\n");
  229. Result = EntryPoint(BootDeviceType, Length);
  230. EfipSerialPrintString("Returned ");
  231. EfipSerialPrintHexInteger(Result);
  232. return Result;
  233. }
  234. UINT32
  235. EfipByteSwap32 (
  236. UINT32 Value
  237. )
  238. /*++
  239. Routine Description:
  240. This routine swaps the endianness of the given value.
  241. Arguments:
  242. Value - Supplies the value to convert.
  243. Return Value:
  244. Returns the byte swapped value.
  245. --*/
  246. {
  247. UINT32 Result;
  248. Result = (Value & 0x000000FF) << 24;
  249. Result |= (Value & 0x0000FF00) << 8;
  250. Result |= (Value & 0x00FF0000) >> 8;
  251. Result |= ((Value & 0xFF000000) >> 24) & 0x000000FF;
  252. return Result;
  253. }