Platform.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /** @file
  2. Platform PEI driver
  3. Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Glossary:
  6. - Mem - Memory
  7. **/
  8. //
  9. // The package level header files this module uses
  10. //
  11. #include <PiPei.h>
  12. //
  13. // The Library classes this module consumes
  14. //
  15. #include <Library/DebugLib.h>
  16. #include <Library/HobLib.h>
  17. #include <Library/IoLib.h>
  18. #include <Library/MemoryAllocationLib.h>
  19. #include <Library/BaseMemoryLib.h>
  20. #include <Library/PcdLib.h>
  21. #include <Library/PeimEntryPoint.h>
  22. #include <Library/PeiServicesLib.h>
  23. #include <Library/ResourcePublicationLib.h>
  24. #include <Guid/MemoryTypeInformation.h>
  25. #include <Library/QemuFwCfgLib.h>
  26. #include <Library/MmuLib.h>
  27. #include <Guid/FdtHob.h>
  28. #include <libfdt.h>
  29. #include <Ppi/MasterBootMode.h>
  30. #include "Platform.h"
  31. /* TODO */
  32. EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
  33. { EfiReservedMemoryType, 0x004 },
  34. { EfiRuntimeServicesData, 0x024 },
  35. { EfiRuntimeServicesCode, 0x030 },
  36. { EfiBootServicesCode, 0x180 },
  37. { EfiBootServicesData, 0xF00 },
  38. { EfiMaxMemoryType, 0x000 }
  39. };
  40. //
  41. // Module globals
  42. //
  43. CONST EFI_PEI_PPI_DESCRIPTOR mPpiListBootMode = {
  44. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  45. &gEfiPeiMasterBootModePpiGuid,
  46. NULL
  47. };
  48. STATIC EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
  49. /**
  50. Create Reserved type memory range hand off block.
  51. @param MemoryBase memory base address.
  52. @param MemoryLimit memory length.
  53. @return VOID
  54. **/
  55. VOID
  56. AddReservedMemoryBaseSizeHob (
  57. EFI_PHYSICAL_ADDRESS MemoryBase,
  58. UINT64 MemorySize
  59. )
  60. {
  61. BuildResourceDescriptorHob (
  62. EFI_RESOURCE_MEMORY_RESERVED,
  63. EFI_RESOURCE_ATTRIBUTE_PRESENT |
  64. EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
  65. EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
  66. EFI_RESOURCE_ATTRIBUTE_TESTED,
  67. MemoryBase,
  68. MemorySize
  69. );
  70. }
  71. /**
  72. Create system type memory range hand off block.
  73. @param MemoryBase memory base address.
  74. @param MemoryLimit memory length.
  75. @return VOID
  76. **/
  77. VOID
  78. AddMemoryBaseSizeHob (
  79. EFI_PHYSICAL_ADDRESS MemoryBase,
  80. UINT64 MemorySize
  81. )
  82. {
  83. BuildResourceDescriptorHob (
  84. EFI_RESOURCE_SYSTEM_MEMORY,
  85. EFI_RESOURCE_ATTRIBUTE_PRESENT |
  86. EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
  87. EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
  88. EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
  89. EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
  90. EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
  91. EFI_RESOURCE_ATTRIBUTE_TESTED,
  92. MemoryBase,
  93. MemorySize
  94. );
  95. }
  96. /**
  97. Create memory range hand off block.
  98. @param MemoryBase memory base address.
  99. @param MemoryLimit memory length.
  100. @return VOID
  101. **/
  102. VOID
  103. AddMemoryRangeHob (
  104. EFI_PHYSICAL_ADDRESS MemoryBase,
  105. EFI_PHYSICAL_ADDRESS MemoryLimit
  106. )
  107. {
  108. AddMemoryBaseSizeHob (MemoryBase, (UINT64) (MemoryLimit - MemoryBase));
  109. }
  110. /**
  111. Create memory type information hand off block.
  112. @param VOID
  113. @return VOID
  114. **/
  115. VOID
  116. MemMapInitialization (
  117. VOID
  118. )
  119. {
  120. DEBUG ((DEBUG_INFO, "==%a==\n", __func__));
  121. //
  122. // Create Memory Type Information HOB
  123. //
  124. BuildGuidDataHob (
  125. &gEfiMemoryTypeInformationGuid,
  126. mDefaultMemoryTypeInformation,
  127. sizeof (mDefaultMemoryTypeInformation)
  128. );
  129. }
  130. /** Get the UART base address of the console serial-port from the DT.
  131. This function fetches the node referenced in the "stdout-path"
  132. property of the "chosen" node and returns the base address of
  133. the console UART.
  134. @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
  135. @param [out] SerialConsoleAddress If success, contains the base address
  136. of the console serial-port.
  137. @retval EFI_SUCCESS The function completed successfully.
  138. @retval EFI_NOT_FOUND Console serial-port info not found in DT.
  139. @retval EFI_INVALID_PARAMETER Invalid parameter.
  140. **/
  141. STATIC
  142. EFI_STATUS
  143. EFIAPI
  144. GetSerialConsolePortAddress (
  145. IN CONST VOID *Fdt,
  146. OUT UINT64 *SerialConsoleAddress
  147. )
  148. {
  149. CONST CHAR8 *Prop;
  150. INT32 PropSize;
  151. CONST CHAR8 *Path;
  152. INT32 PathLen;
  153. INT32 ChosenNode;
  154. INT32 SerialConsoleNode;
  155. INT32 Len;
  156. CONST CHAR8 *NodeStatus;
  157. CONST UINT64 *RegProperty;
  158. if ((Fdt == NULL) || (fdt_check_header (Fdt) != 0)) {
  159. return EFI_INVALID_PARAMETER;
  160. }
  161. // The "chosen" node resides at the root of the DT. Fetch it.
  162. ChosenNode = fdt_path_offset (Fdt, "/chosen");
  163. if (ChosenNode < 0) {
  164. return EFI_NOT_FOUND;
  165. }
  166. Prop = fdt_getprop (Fdt, ChosenNode, "stdout-path", &PropSize);
  167. if (PropSize < 0) {
  168. return EFI_NOT_FOUND;
  169. }
  170. // Determine the actual path length, as a colon terminates the path.
  171. Path = ScanMem8 (Prop, ':', PropSize);
  172. if (Path == NULL) {
  173. PathLen = AsciiStrLen (Prop);
  174. } else {
  175. PathLen = Path - Prop;
  176. }
  177. // Aliases cannot start with a '/', so it must be the actual path.
  178. if (Prop[0] == '/') {
  179. SerialConsoleNode = fdt_path_offset_namelen (Fdt, Prop, PathLen);
  180. } else {
  181. // Lookup the alias, as this contains the actual path.
  182. Path = fdt_get_alias_namelen (Fdt, Prop, PathLen);
  183. if (Path == NULL) {
  184. return EFI_NOT_FOUND;
  185. }
  186. SerialConsoleNode = fdt_path_offset (Fdt, Path);
  187. }
  188. NodeStatus = fdt_getprop (Fdt, SerialConsoleNode, "status", &Len);
  189. if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
  190. return EFI_NOT_FOUND;
  191. }
  192. RegProperty = fdt_getprop (Fdt, SerialConsoleNode, "reg", &Len);
  193. if (Len != 16) {
  194. return EFI_INVALID_PARAMETER;
  195. }
  196. *SerialConsoleAddress = fdt64_to_cpu (ReadUnaligned64 (RegProperty));
  197. return EFI_SUCCESS;
  198. }
  199. /** Get the Rtc base address from the DT.
  200. This function fetches the node referenced in the "loongson,ls7a-rtc"
  201. property of the "reg" node and returns the base address of
  202. the RTC.
  203. @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
  204. @param [out] RtcBaseAddress If success, contains the base address
  205. of the Rtc.
  206. @retval EFI_SUCCESS The function completed successfully.
  207. @retval EFI_NOT_FOUND RTC info not found in DT.
  208. @retval EFI_INVALID_PARAMETER Invalid parameter.
  209. **/
  210. STATIC
  211. EFI_STATUS
  212. EFIAPI
  213. GetRtcAddress (
  214. IN CONST VOID *Fdt,
  215. OUT UINT64 *RtcBaseAddress
  216. )
  217. {
  218. INT32 Node;
  219. INT32 Prev;
  220. CONST CHAR8 *Type;
  221. INT32 Len;
  222. CONST UINT64 *RegProp;
  223. EFI_STATUS Status;
  224. if ((Fdt == NULL) || (fdt_check_header (Fdt) != 0)) {
  225. return EFI_INVALID_PARAMETER;
  226. }
  227. Status = EFI_NOT_FOUND;
  228. for (Prev = 0;; Prev = Node) {
  229. Node = fdt_next_node (Fdt, Prev, NULL);
  230. if (Node < 0) {
  231. break;
  232. }
  233. //
  234. // Check for memory node
  235. //
  236. Type = fdt_getprop (Fdt, Node, "compatible", &Len);
  237. if ((Type)
  238. && (AsciiStrnCmp (Type, "loongson,ls7a-rtc", Len) == 0))
  239. {
  240. //
  241. // Get the 'reg' property of this node. For now, we will assume
  242. // two 8 byte quantities for base and size, respectively.
  243. //
  244. RegProp = fdt_getprop (Fdt, Node, "reg", &Len);
  245. if ((RegProp != 0)
  246. && (Len == (2 * sizeof (UINT64))))
  247. {
  248. *RtcBaseAddress = SwapBytes64 (RegProp[0]);
  249. Status = RETURN_SUCCESS;
  250. DEBUG ((DEBUG_INFO, "%a Len %d RtcBase %llx\n",__func__, Len, *RtcBaseAddress));
  251. break;
  252. } else {
  253. DEBUG ((DEBUG_ERROR, "%a: Failed to parse FDT rtc node\n",
  254. __FUNCTION__));
  255. break;
  256. }
  257. }
  258. }
  259. return Status;
  260. }
  261. /**
  262. Misc Initialization.
  263. @param VOID
  264. @return VOID
  265. **/
  266. VOID
  267. MiscInitialization (
  268. VOID
  269. )
  270. {
  271. DEBUG ((DEBUG_INFO, "==%a==\n", __func__));
  272. //
  273. // Creat CPU HOBs.
  274. //
  275. BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
  276. }
  277. /**
  278. add fdt hand off block.
  279. @param VOID
  280. @return VOID
  281. **/
  282. VOID
  283. AddFdtHob (VOID)
  284. {
  285. VOID *Base;
  286. VOID *NewBase;
  287. UINTN FdtSize;
  288. UINTN FdtPages;
  289. UINT64 *FdtHobData;
  290. UINT64 *UartHobData;
  291. UINT64 SerialConsoleAddress;
  292. UINT64 RtcBaseAddress;
  293. RETURN_STATUS Status;
  294. Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeBase);
  295. ASSERT (Base != NULL);
  296. Status = GetSerialConsolePortAddress (Base, &SerialConsoleAddress);
  297. if (RETURN_ERROR (Status)) {
  298. return;
  299. }
  300. UartHobData = BuildGuidHob (&gEarly16550UartBaseAddressGuid, sizeof *UartHobData);
  301. ASSERT (UartHobData != NULL);
  302. *UartHobData = SerialConsoleAddress;
  303. Status = GetRtcAddress(Base, &RtcBaseAddress);
  304. if (RETURN_ERROR (Status)) {
  305. return;
  306. }
  307. Status = PcdSet64S (PcdRtcBaseAddress, RtcBaseAddress);
  308. if (RETURN_ERROR (Status)) {
  309. return;
  310. }
  311. FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreePadding);
  312. FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
  313. NewBase = AllocatePages (FdtPages);
  314. ASSERT (NewBase != NULL);
  315. fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
  316. FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
  317. ASSERT (FdtHobData != NULL);
  318. *FdtHobData = (UINTN)NewBase;
  319. }
  320. /**
  321. Fetch the size of system memory from QEMU.
  322. @param VOID
  323. @return VOID
  324. **/
  325. VOID
  326. SystemMemorySizeInitialization (
  327. VOID
  328. )
  329. {
  330. UINT64 RamSize;
  331. RETURN_STATUS PcdStatus;
  332. QemuFwCfgSelectItem (QemuFwCfgItemRamSize);
  333. RamSize= QemuFwCfgRead64 ();
  334. DEBUG ((DEBUG_INFO, "%a: QEMU reports %dM system memory\n", __FUNCTION__,
  335. RamSize/1024/1024));
  336. //
  337. // If the fw_cfg key or fw_cfg entirely is unavailable, no change to PCD.
  338. //
  339. if (RamSize == 0) {
  340. return;
  341. }
  342. //
  343. // Otherwise, set RamSize to PCD.
  344. //
  345. PcdStatus = PcdSet64S (PcdRamSize, RamSize);
  346. ASSERT_RETURN_ERROR (PcdStatus);
  347. }
  348. /**
  349. Perform Platform PEI initialization.
  350. @param FileHandle Handle of the file being invoked.
  351. @param PeiServices Describes the list of possible PEI Services.
  352. @return EFI_SUCCESS The PEIM initialized successfully.
  353. **/
  354. EFI_STATUS
  355. EFIAPI
  356. InitializePlatform (
  357. IN EFI_PEI_FILE_HANDLE FileHandle,
  358. IN CONST EFI_PEI_SERVICES **PeiServices
  359. )
  360. {
  361. EFI_STATUS Status;
  362. DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
  363. Status = PeiServicesSetBootMode (mBootMode);
  364. ASSERT_EFI_ERROR (Status);
  365. Status = PeiServicesInstallPpi (&mPpiListBootMode);
  366. ASSERT_EFI_ERROR (Status);
  367. SystemMemorySizeInitialization ();
  368. PublishPeiMemory ();
  369. PeiFvInitialization ();
  370. InitializeRamRegions ();
  371. MemMapInitialization ();
  372. MiscInitialization ();
  373. AddFdtHob ();
  374. ConfigureMmu ();
  375. return EFI_SUCCESS;
  376. }