boot.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  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 loader.
  7. Author:
  8. Evan Green 1-Apr-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 OMAP4_BOOT_USB 0x45
  23. #define OMAP4_BOOT_MMC1 0x05
  24. #define OMAP4_BOOT_MMC2 0x06
  25. #define OMAP4_BOOT_DEVICE_OFFSET 8
  26. //
  27. // Define the "hello" sent over USB indicating to the app on the other side
  28. // that this code is alive.
  29. //
  30. #define OMAP4_USB_BOOT_RESPONSE 0xAABBCCDD
  31. #define OMAP4_MEMORY_DEVICE_DATA_BUFFER 0x80000000
  32. #define OMAP4_MEMORY_DEVICE_DATA_SIZE 2500
  33. //
  34. // ------------------------------------------------------ Data Type Definitions
  35. //
  36. typedef
  37. INT32
  38. (*POMAP4_BOOT_ENTRY_POINT) (
  39. UINT32 BootType,
  40. UINT32 Length
  41. );
  42. /*++
  43. Routine Description:
  44. This routine is the entry point for a booted option.
  45. Arguments:
  46. BootType - Supplies the boot device type.
  47. Length - Supplies the image length.
  48. Return Value:
  49. 0 on success.
  50. Non-zero on failure.
  51. --*/
  52. //
  53. // ----------------------------------------------- Internal Function Prototypes
  54. //
  55. INTN
  56. EfipOmap4LoadFromUsb (
  57. UINT32 *Length
  58. );
  59. INTN
  60. EfipOmap4LoadFromSd (
  61. UINT8 DeviceType,
  62. UINT32 *Length
  63. );
  64. INTN
  65. EfipOmap4BootImage (
  66. UINT32 BootDeviceType,
  67. UINT32 Image,
  68. UINT32 Length
  69. );
  70. UINT32
  71. EfipByteSwap32 (
  72. UINT32 Value
  73. );
  74. //
  75. // -------------------------------------------------------------------- Globals
  76. //
  77. TI_ROM_USB_HANDLE EfiOmap4RomUsbHandle;
  78. TI_ROM_MEM_HANDLE EfiOmap4RomMemHandle;
  79. UINT32 EfiOmap4UsbBootResponse = OMAP4_USB_BOOT_RESPONSE;
  80. BOOLEAN EfiSkipCrc;
  81. //
  82. // ------------------------------------------------------------------ Functions
  83. //
  84. VOID
  85. EfiFirstStageLoader (
  86. UINT8 *Information
  87. )
  88. /*++
  89. Routine Description:
  90. This routine implements the main C routine of the first stage loader. Its
  91. role is to load the primary firmware.
  92. Arguments:
  93. Information - Supplies an optional pointer to information handed off by the
  94. ROM code in the SoC.
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. UINT32 BootDevice;
  100. UINT32 ImageAddress;
  101. UINT32 Length;
  102. INTN Result;
  103. EfipInitializeBoardMux();
  104. EfipSpin(100);
  105. EfipScaleVcores();
  106. EfipInitializePrcm();
  107. EfipInitializeDdr();
  108. EfipInitializeGpmc();
  109. EfipInitializeSerial();
  110. EfipSerialPrintString("Minoca Firmware Loader\n");
  111. if (Information != NULL) {
  112. BootDevice = Information[OMAP4_BOOT_DEVICE_OFFSET];
  113. EfipSerialPrintString("ResetReason ");
  114. EfipSerialPrintHexInteger(Information[0x9]);
  115. EfipSerialPrintString(".\n");
  116. } else {
  117. BootDevice = OMAP4_BOOT_USB;
  118. }
  119. ImageAddress = 0;
  120. switch (BootDevice) {
  121. case OMAP4_BOOT_USB:
  122. EfipSerialPrintString("USB Boot\n");
  123. Result = EfipOmap4LoadFromUsb(&Length);
  124. ImageAddress = OMAP4_USB_BOOT_ADDRESS;
  125. break;
  126. case OMAP4_BOOT_MMC1:
  127. case OMAP4_BOOT_MMC2:
  128. EfipSerialPrintString("SD Boot\n");
  129. Result = EfipOmap4LoadFromSd(BootDevice, &Length);
  130. ImageAddress = OMAP4_SD_BOOT_ADDRESS;
  131. break;
  132. default:
  133. EfipSerialPrintString("Boot type unknown!\n");
  134. Result = -1;
  135. break;
  136. }
  137. if (Result != 0) {
  138. EfipSerialPrintString("Load Error.\n");
  139. } else {
  140. Result = EfipOmap4BootImage(BootDevice, ImageAddress, Length);
  141. }
  142. EfipSerialPrintString("Result: ");
  143. EfipSerialPrintHexInteger(Result);
  144. EfipSerialPrintString(".\nHanging...");
  145. while (TRUE) {
  146. NOTHING;
  147. }
  148. return;
  149. }
  150. //
  151. // --------------------------------------------------------- Internal Functions
  152. //
  153. INTN
  154. EfipOmap4LoadFromUsb (
  155. UINT32 *Length
  156. )
  157. /*++
  158. Routine Description:
  159. This routine loads the boot loader over USB.
  160. Arguments:
  161. Length - Supplies a pointer where the length of the loaded image will be
  162. returned on success.
  163. Return Value:
  164. 0 on success.
  165. Non-zero on failure.
  166. --*/
  167. {
  168. UINT32 ReadLength;
  169. INTN Result;
  170. //
  171. // The processor must be in ARM mode, otherwise enabling interrupts causes
  172. // a reset.
  173. //
  174. EfiEnableInterrupts();
  175. Result = EfipOmap4UsbOpen(&EfiOmap4RomUsbHandle);
  176. if (Result != 0) {
  177. return Result;
  178. }
  179. EfipOmap4UsbWrite(&EfiOmap4RomUsbHandle,
  180. &EfiOmap4UsbBootResponse,
  181. sizeof(EfiOmap4UsbBootResponse));
  182. EfipOmap4UsbRead(&EfiOmap4RomUsbHandle, &ReadLength, sizeof(UINT32));
  183. Result = EfipOmap4UsbRead(&EfiOmap4RomUsbHandle,
  184. (VOID *)OMAP4_USB_BOOT_ADDRESS,
  185. ReadLength);
  186. if (Result != 0) {
  187. return Result;
  188. }
  189. EfipOmap4UsbClose(&EfiOmap4RomUsbHandle);
  190. EfiDisableInterrupts();
  191. *Length = ReadLength;
  192. return 0;
  193. }
  194. INTN
  195. EfipOmap4LoadFromSd (
  196. UINT8 DeviceType,
  197. UINT32 *Length
  198. )
  199. /*++
  200. Routine Description:
  201. This routine loads the boot loader over SD.
  202. Arguments:
  203. DeviceType - Supplies the device type to boot from.
  204. Length - Supplies a pointer where the length of the loaded image will be
  205. returned on success.
  206. Return Value:
  207. 0 on success.
  208. Non-zero on failure.
  209. --*/
  210. {
  211. UINT32 Base;
  212. VOID *DeviceData;
  213. INTN Result;
  214. if (EfipOmap4GetRevision() >= Omap4460RevisionEs10) {
  215. Base = OMAP4460_PUBLIC_API_BASE;
  216. } else {
  217. Base = OMAP4430_PUBLIC_API_BASE;
  218. }
  219. DeviceData = (VOID *)OMAP4_MEMORY_DEVICE_DATA_BUFFER;
  220. EfipInitZeroMemory(DeviceData, OMAP4_MEMORY_DEVICE_DATA_SIZE);
  221. Result = EfipTiMemOpen(DeviceType, Base, DeviceData, &EfiOmap4RomMemHandle);
  222. if (Result != 0) {
  223. return Result;
  224. }
  225. Result = EfipTiLoadFirmwareFromFat(&EfiOmap4RomMemHandle,
  226. PANDA_FIRMWARE_NAME,
  227. (VOID *)OMAP4_SD_BOOT_ADDRESS,
  228. Length);
  229. if (Result != 0) {
  230. return Result;
  231. }
  232. return 0;
  233. }
  234. INTN
  235. EfipOmap4BootImage (
  236. UINT32 BootDeviceType,
  237. UINT32 Image,
  238. UINT32 Length
  239. )
  240. /*++
  241. Routine Description:
  242. This routine boots a loaded image in memory.
  243. Arguments:
  244. BootDeviceType - Supplies the boot device type.
  245. Image - Supplies the address of the image.
  246. Length - Supplies the length of the image in bytes.
  247. Return Value:
  248. 0 on success. Actually, does not return on success.
  249. Non-zero on failure.
  250. --*/
  251. {
  252. UINT32 Crc;
  253. POMAP4_BOOT_ENTRY_POINT EntryPoint;
  254. UINT32 HeaderDataCrc;
  255. UINT32 LoadAddress;
  256. INTN Result;
  257. PUBOOT_HEADER UbootHeader;
  258. //
  259. // Check for the U-Boot header.
  260. //
  261. EfipInitializeCrc32((VOID *)PANDA_BOARD_CRC_TABLE_ADDRESS);
  262. UbootHeader = (PUBOOT_HEADER)(UINTN)Image;
  263. if (EfipByteSwap32(UbootHeader->Magic) == UBOOT_MAGIC) {
  264. LoadAddress = EfipByteSwap32(UbootHeader->DataLoadAddress);
  265. if (LoadAddress != Image + sizeof(UBOOT_HEADER)) {
  266. EfipSerialPrintString("Warning: U-boot load address ");
  267. EfipSerialPrintHexInteger(LoadAddress);
  268. EfipSerialPrintString(" but expected ");
  269. EfipSerialPrintHexInteger(Image + sizeof(UBOOT_HEADER));
  270. EfipSerialPrintString("\n");
  271. }
  272. EntryPoint = (VOID *)EfipByteSwap32(UbootHeader->EntryPoint);
  273. EfipSerialPrintString("Launching ");
  274. EfipSerialPrintString(UbootHeader->ImageName);
  275. EfipSerialPrintString(".\n");
  276. EfiSkipCrc = TRUE;
  277. if (EfiSkipCrc == FALSE) {
  278. Crc = EfipInitCalculateCrc32((VOID *)Image + sizeof(UBOOT_HEADER),
  279. EfipByteSwap32(UbootHeader->DataSize));
  280. HeaderDataCrc = EfipByteSwap32(UbootHeader->DataCrc32);
  281. if (Crc != HeaderDataCrc) {
  282. EfipSerialPrintString("Error: CRC was ");
  283. EfipSerialPrintHexInteger(Crc);
  284. EfipSerialPrintString(", header value was ");
  285. EfipSerialPrintHexInteger(HeaderDataCrc);
  286. EfipSerialPrintString(".\n");
  287. return 0x44;
  288. }
  289. }
  290. } else {
  291. EntryPoint = (POMAP4_BOOT_ENTRY_POINT)Image;
  292. }
  293. //
  294. // Turn on an LED to indicate progress.
  295. //
  296. EfipPandaSetLeds(1, 0);
  297. //
  298. // Not a u-boot header, jump to it directly.
  299. //
  300. EfipSerialPrintString("Jumping to ");
  301. EfipSerialPrintHexInteger((UINT32)EntryPoint);
  302. EfipSerialPrintString("...\n");
  303. Result = EntryPoint(BootDeviceType, Length);
  304. EfipSerialPrintString("Returned ");
  305. EfipSerialPrintHexInteger(Result);
  306. return Result;
  307. }
  308. UINT32
  309. EfipByteSwap32 (
  310. UINT32 Value
  311. )
  312. /*++
  313. Routine Description:
  314. This routine swaps the endianness of the given value.
  315. Arguments:
  316. Value - Supplies the value to convert.
  317. Return Value:
  318. Returns the byte swapped value.
  319. --*/
  320. {
  321. UINT32 Result;
  322. Result = (Value & 0x000000FF) << 24;
  323. Result |= (Value & 0x0000FF00) << 8;
  324. Result |= (Value & 0x00FF0000) >> 8;
  325. Result |= ((Value & 0xFF000000) >> 24) & 0x000000FF;
  326. return Result;
  327. }