FdtUpdateLib.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /** @file
  2. *
  3. * Copyright (c) 2016, Hisilicon Limited. All rights reserved.
  4. * Copyright (c) 2016, Linaro Limited. All rights reserved.
  5. *
  6. * This program and the accompanying materials
  7. * are licensed and made available under the terms and conditions of the BSD License
  8. * which accompanies this distribution. The full text of the license may be found at
  9. * http://opensource.org/licenses/bsd-license.php
  10. *
  11. * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  13. *
  14. **/
  15. #include <Uefi.h>
  16. #include <Library/ArmArchTimer.h>
  17. #include <Library/BaseLib.h>
  18. #include <libfdt.h>
  19. #include <Library/IoLib.h>
  20. #include <Library/DebugLib.h>
  21. #include <Library/UefiBootServicesTableLib.h>
  22. #include <Library/FdtUpdateLib.h>
  23. #include <PlatformArch.h>
  24. #include <Library/PcdLib.h>
  25. #include <Library/PlatformSysCtrlLib.h>
  26. #include <Library/MemoryAllocationLib.h>
  27. #include <Protocol/HisiBoardNicProtocol.h>
  28. #include <Library/UefiRuntimeServicesTableLib.h>
  29. #include <Library/OemMiscLib.h>
  30. typedef union AA_DAW
  31. {
  32. /* Define the struct bits */
  33. struct
  34. {
  35. unsigned int sysdaw_id : 7 ; /* [6:0] */
  36. unsigned int interleave_en : 1 ; /* [7] */
  37. unsigned int sysdaw_size : 4 ; /* [11:8] */
  38. unsigned int reserved : 4 ; /* [15:12] */
  39. unsigned int sysdaw_addr : 16 ; /* [31:16] */
  40. } bits;
  41. /* Define an unsigned member */
  42. unsigned int u32;
  43. } AA_DAW_U;
  44. MAC_ADDRESS gMacAddress[1];
  45. CHAR8 *EthName[8]=
  46. {
  47. "ethernet@0","ethernet@1",
  48. "ethernet@2","ethernet@3",
  49. "ethernet@4","ethernet@5",
  50. "ethernet@6","ethernet@7"
  51. };
  52. UINT8 DawNum[4] = {0, 0, 0, 0};
  53. PHY_MEM_REGION *NodemRegion[4] = {NULL, NULL, NULL, NULL};
  54. UINTN NumaPages[4] = {0, 0, 0, 0};
  55. CHAR8 *NumaNodeName[4]=
  56. {
  57. "p0-ta","p0-tc",
  58. "p1-ta","p1-tc",
  59. };
  60. STATIC
  61. BOOLEAN
  62. IsMemMapRegion (
  63. IN EFI_MEMORY_TYPE MemoryType
  64. )
  65. {
  66. switch(MemoryType)
  67. {
  68. case EfiRuntimeServicesCode:
  69. case EfiRuntimeServicesData:
  70. case EfiConventionalMemory:
  71. case EfiACPIReclaimMemory:
  72. case EfiACPIMemoryNVS:
  73. case EfiLoaderCode:
  74. case EfiLoaderData:
  75. case EfiBootServicesCode:
  76. case EfiBootServicesData:
  77. case EfiPalCode:
  78. return TRUE;
  79. default:
  80. return FALSE;
  81. }
  82. }
  83. EFI_STATUS
  84. GetMacAddress (UINT32 Port)
  85. {
  86. EFI_MAC_ADDRESS Mac;
  87. EFI_STATUS Status;
  88. HISI_BOARD_NIC_PROTOCOL *OemNic = NULL;
  89. Status = gBS->LocateProtocol(&gHisiBoardNicProtocolGuid, NULL, (VOID **)&OemNic);
  90. if(EFI_ERROR(Status))
  91. {
  92. DEBUG((EFI_D_ERROR, "[%a]:[%dL] LocateProtocol failed %r\n", __FUNCTION__, __LINE__, Status));
  93. return Status;
  94. }
  95. Status = OemNic->GetMac(&Mac, Port);
  96. if(EFI_ERROR(Status))
  97. {
  98. DEBUG((EFI_D_ERROR, "[%a]:[%dL] GetMac failed %r\n", __FUNCTION__, __LINE__, Status));
  99. return Status;
  100. }
  101. gMacAddress[0].data0=Mac.Addr[0];
  102. gMacAddress[0].data1=Mac.Addr[1];
  103. gMacAddress[0].data2=Mac.Addr[2];
  104. gMacAddress[0].data3=Mac.Addr[3];
  105. gMacAddress[0].data4=Mac.Addr[4];
  106. gMacAddress[0].data5=Mac.Addr[5];
  107. DEBUG((EFI_D_INFO, "Port%d:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
  108. Port,gMacAddress[0].data0,gMacAddress[0].data1,gMacAddress[0].data2,
  109. gMacAddress[0].data3,gMacAddress[0].data4,gMacAddress[0].data5));
  110. return EFI_SUCCESS;
  111. }
  112. STATIC
  113. EFI_STATUS
  114. DelPhyhandleUpdateMacAddress(IN VOID* Fdt)
  115. {
  116. UINT8 port;
  117. INTN ethernetnode;
  118. INTN node;
  119. INTN Error;
  120. struct fdt_property *m_prop;
  121. int m_oldlen;
  122. EFI_STATUS Status = EFI_SUCCESS;
  123. EFI_STATUS GetMacStatus = EFI_SUCCESS;
  124. node = fdt_subnode_offset(Fdt, 0, "soc");
  125. if (node < 0)
  126. {
  127. DEBUG ((EFI_D_ERROR, "can not find soc root node\n"));
  128. return EFI_INVALID_PARAMETER;
  129. }
  130. else
  131. {
  132. for( port=0; port<8; port++ )
  133. {
  134. GetMacStatus= GetMacAddress(port);
  135. ethernetnode = fdt_subnode_offset(Fdt, node,EthName[port]);
  136. if(!EFI_ERROR(GetMacStatus))
  137. {
  138. if (ethernetnode < 0)
  139. {
  140. DEBUG ((EFI_D_WARN, "Can not find ethernet@%d node\n",port));
  141. DEBUG ((EFI_D_WARN, "Suppose port %d is not enabled.\n", port));
  142. continue;
  143. }
  144. m_prop = fdt_get_property_w(Fdt, ethernetnode, "local-mac-address", &m_oldlen);
  145. if(m_prop)
  146. {
  147. Error = fdt_delprop(Fdt, ethernetnode, "local-mac-address");
  148. if (Error)
  149. {
  150. DEBUG ((EFI_D_ERROR, "ERROR:fdt_delprop() Local-mac-address: %a\n", fdt_strerror (Error)));
  151. Status = EFI_INVALID_PARAMETER;
  152. }
  153. Error = fdt_setprop(Fdt, ethernetnode, "local-mac-address",gMacAddress,sizeof(MAC_ADDRESS));
  154. if (Error)
  155. {
  156. DEBUG ((EFI_D_ERROR, "ERROR:fdt_setprop():local-mac-address %a\n", fdt_strerror (Error)));
  157. Status = EFI_INVALID_PARAMETER;
  158. }
  159. }
  160. }
  161. }
  162. }
  163. return Status;
  164. }
  165. STATIC
  166. EFI_STATUS
  167. UpdateRefClk (IN VOID* Fdt)
  168. {
  169. INTN node;
  170. INTN Error;
  171. struct fdt_property *m_prop;
  172. int m_oldlen;
  173. UINTN ArchTimerFreq = 0;
  174. UINT32 Data;
  175. CONST CHAR8 *Property = "clock-frequency";
  176. ArmArchTimerReadReg (CntFrq, &ArchTimerFreq);
  177. if (!ArchTimerFreq) {
  178. DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Get timer frequency failed!\n", __FUNCTION__, __LINE__));
  179. return EFI_INVALID_PARAMETER;
  180. }
  181. node = fdt_subnode_offset(Fdt, 0, "soc");
  182. if (node < 0) {
  183. DEBUG ((DEBUG_ERROR, "can not find soc node\n"));
  184. return EFI_INVALID_PARAMETER;
  185. }
  186. node = fdt_subnode_offset(Fdt, node, "refclk");
  187. if (node < 0) {
  188. DEBUG ((DEBUG_ERROR, "can not find refclk node\n"));
  189. return EFI_INVALID_PARAMETER;
  190. }
  191. m_prop = fdt_get_property_w(Fdt, node, Property, &m_oldlen);
  192. if(!m_prop) {
  193. DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Can't find property %a\n", __FUNCTION__, __LINE__, Property));
  194. return EFI_INVALID_PARAMETER;
  195. }
  196. Error = fdt_delprop(Fdt, node, Property);
  197. if (Error) {
  198. DEBUG ((DEBUG_ERROR, "ERROR: fdt_delprop() %a: %a\n", Property, fdt_strerror (Error)));
  199. return EFI_INVALID_PARAMETER;
  200. }
  201. // UINT32 is enough for refclk data length
  202. Data = (UINT32) ArchTimerFreq;
  203. Data = cpu_to_fdt32 (Data);
  204. Error = fdt_setprop(Fdt, node, Property, &Data, sizeof(Data));
  205. if (Error) {
  206. DEBUG ((DEBUG_ERROR, "ERROR:fdt_setprop() %a: %a\n", Property, fdt_strerror (Error)));
  207. return EFI_INVALID_PARAMETER;
  208. }
  209. DEBUG ((DEBUG_INFO, "Update refclk successfully.\n"));
  210. return EFI_SUCCESS;
  211. }
  212. INTN
  213. GetMemoryNode(VOID* Fdt)
  214. {
  215. INTN node;
  216. int m_oldlen;
  217. struct fdt_property *m_prop;
  218. INTN Error = 0;
  219. node = fdt_subnode_offset(Fdt, 0, "memory");
  220. if (node < 0)
  221. {
  222. // Create the memory node
  223. node = fdt_add_subnode(Fdt, 0, "memory");
  224. if(node < 0)
  225. {
  226. DEBUG((EFI_D_ERROR, "[%a]:[%dL] fdt add subnode error\n", __FUNCTION__, __LINE__));
  227. return node;
  228. }
  229. }
  230. //find the memory node property
  231. m_prop = fdt_get_property_w(Fdt, node, "memory", &m_oldlen);
  232. if(m_prop)
  233. {
  234. Error = fdt_delprop(Fdt, node, "reg");
  235. if (Error)
  236. {
  237. DEBUG ((EFI_D_ERROR, "ERROR:fdt_delprop(): %a\n", fdt_strerror (Error)));
  238. node = -1;
  239. return node;
  240. }
  241. }
  242. return node;
  243. }
  244. EFI_STATUS UpdateMemoryNode(VOID* Fdt)
  245. {
  246. INTN Error = 0;
  247. EFI_STATUS Status = EFI_SUCCESS;
  248. UINT32 Index = 0;
  249. UINT32 MemIndex;
  250. INTN node;
  251. EFI_MEMORY_DESCRIPTOR *MemoryMap;
  252. EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;
  253. EFI_MEMORY_DESCRIPTOR *MemoryMapPtrCurrent;
  254. UINTN MemoryMapSize;
  255. UINTN Pages0 = 0;
  256. UINTN Pages1 = 0;
  257. UINTN MapKey;
  258. UINTN DescriptorSize;
  259. UINT32 DescriptorVersion;
  260. PHY_MEM_REGION *mRegion;
  261. UINTN MemoryMapLastEndAddress ;
  262. UINTN MemoryMapcontinuousStartAddress ;
  263. UINTN MemoryMapCurrentStartAddress;
  264. BOOLEAN FindMemoryRegionFlag = FALSE;
  265. node = GetMemoryNode(Fdt);
  266. if (node < 0)
  267. {
  268. DEBUG((EFI_D_ERROR, "Can not find memory node\n"));
  269. return EFI_NOT_FOUND;
  270. }
  271. MemoryMap = NULL;
  272. MemoryMapSize = 0;
  273. MemIndex = 0;
  274. Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);
  275. if (Status == EFI_BUFFER_TOO_SMALL)
  276. {
  277. // The UEFI specification advises to allocate more memory for the MemoryMap buffer between successive
  278. // calls to GetMemoryMap(), since allocation of the new buffer may potentially increase memory map size.
  279. Pages0 = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
  280. MemoryMap = AllocatePages (Pages0);
  281. if (MemoryMap == NULL)
  282. {
  283. Status = EFI_OUT_OF_RESOURCES;
  284. return Status;
  285. }
  286. Status = gBS->GetMemoryMap (&MemoryMapSize, MemoryMap, &MapKey, &DescriptorSize, &DescriptorVersion);
  287. if (EFI_ERROR(Status))
  288. {
  289. DEBUG ((EFI_D_ERROR, "FdtUpdateLib GetMemoryMap Error\n"));
  290. FreePages (MemoryMap, Pages0);
  291. return Status;
  292. }
  293. }
  294. else
  295. {
  296. DEBUG ((EFI_D_ERROR, "FdtUpdateLib GetmemoryMap Status: %r\n",Status));
  297. return EFI_ABORTED;
  298. }
  299. mRegion = NULL;
  300. Pages1 = EFI_SIZE_TO_PAGES (sizeof(PHY_MEM_REGION) *( MemoryMapSize / DescriptorSize));
  301. mRegion = (PHY_MEM_REGION*)AllocatePool(Pages1);
  302. if (mRegion == NULL)
  303. {
  304. Status = EFI_OUT_OF_RESOURCES;
  305. FreePages (MemoryMap, Pages0);
  306. return Status;
  307. }
  308. MemoryMapPtr = MemoryMap;
  309. MemoryMapPtrCurrent = MemoryMapPtr;
  310. MemoryMapLastEndAddress = 0;
  311. MemoryMapcontinuousStartAddress = 0;
  312. MemoryMapCurrentStartAddress = 0;
  313. for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++)
  314. {
  315. MemoryMapPtrCurrent = (EFI_MEMORY_DESCRIPTOR*)((UINTN)MemoryMapPtr + Index*DescriptorSize);
  316. MemoryMapCurrentStartAddress = (UINTN)MemoryMapPtrCurrent->PhysicalStart;
  317. if (!IsMemMapRegion ((EFI_MEMORY_TYPE)MemoryMapPtrCurrent->Type))
  318. {
  319. continue;
  320. }
  321. else
  322. {
  323. FindMemoryRegionFlag = TRUE;
  324. if(MemoryMapCurrentStartAddress != MemoryMapLastEndAddress)
  325. {
  326. mRegion[MemIndex].BaseHigh= cpu_to_fdt32(MemoryMapcontinuousStartAddress>>32);
  327. mRegion[MemIndex].BaseLow=cpu_to_fdt32(MemoryMapcontinuousStartAddress);
  328. mRegion[MemIndex].LengthHigh= cpu_to_fdt32((MemoryMapLastEndAddress-MemoryMapcontinuousStartAddress)>>32);
  329. mRegion[MemIndex].LengthLow=cpu_to_fdt32(MemoryMapLastEndAddress-MemoryMapcontinuousStartAddress);
  330. MemIndex+=1;
  331. MemoryMapcontinuousStartAddress=MemoryMapCurrentStartAddress;
  332. }
  333. }
  334. MemoryMapLastEndAddress = (UINTN)(MemoryMapPtrCurrent->PhysicalStart + MemoryMapPtrCurrent->NumberOfPages * EFI_PAGE_SIZE);
  335. }
  336. if (FindMemoryRegionFlag)
  337. {
  338. mRegion[MemIndex].BaseHigh = cpu_to_fdt32(MemoryMapcontinuousStartAddress>>32);
  339. mRegion[MemIndex].BaseLow = cpu_to_fdt32(MemoryMapcontinuousStartAddress);
  340. mRegion[MemIndex].LengthHigh = cpu_to_fdt32((MemoryMapLastEndAddress-MemoryMapcontinuousStartAddress)>>32);
  341. mRegion[MemIndex].LengthLow = cpu_to_fdt32(MemoryMapLastEndAddress-MemoryMapcontinuousStartAddress);
  342. }
  343. Error = fdt_setprop(Fdt, node, "reg",mRegion,sizeof(PHY_MEM_REGION) *(MemIndex+1));
  344. FreePool (mRegion);
  345. FreePages (MemoryMap, Pages0);
  346. if (Error)
  347. {
  348. DEBUG ((EFI_D_ERROR, "ERROR:fdt_setprop(): %a\n", fdt_strerror (Error)));
  349. Status = EFI_INVALID_PARAMETER;
  350. return Status;
  351. }
  352. return Status;
  353. }
  354. EFI_STATUS
  355. UpdateNumaNode(VOID* Fdt)
  356. {
  357. //TODO: Need to update numa node
  358. return EFI_SUCCESS;
  359. }
  360. /*
  361. * Entry point for fdtupdate lib.
  362. */
  363. EFI_STATUS EFIFdtUpdate(UINTN FdtFileAddr)
  364. {
  365. INTN Error;
  366. VOID* Fdt;
  367. UINT32 Size;
  368. UINTN NewFdtBlobSize;
  369. UINTN NewFdtBlobBase;
  370. EFI_STATUS Status = EFI_SUCCESS;
  371. EFI_STATUS UpdateNumaStatus = EFI_SUCCESS;
  372. Error = fdt_check_header ((VOID*)(FdtFileAddr));
  373. if (0 != Error)
  374. {
  375. DEBUG ((EFI_D_ERROR,"ERROR: Device Tree header not valid (%a)\n", fdt_strerror(Error)));
  376. return EFI_INVALID_PARAMETER;
  377. }
  378. Size = (UINTN)fdt_totalsize ((VOID*)(UINTN)(FdtFileAddr));
  379. NewFdtBlobSize = Size + ADD_FILE_LENGTH;
  380. Fdt = (VOID*)(UINTN)FdtFileAddr;
  381. Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(NewFdtBlobSize), &NewFdtBlobBase);
  382. if (EFI_ERROR (Status))
  383. {
  384. return EFI_OUT_OF_RESOURCES;
  385. }
  386. Error = fdt_open_into(Fdt,(VOID*)(UINTN)(NewFdtBlobBase), (NewFdtBlobSize));
  387. if (Error) {
  388. DEBUG ((EFI_D_ERROR, "ERROR:fdt_open_into(): %a\n", fdt_strerror (Error)));
  389. Status = EFI_INVALID_PARAMETER;
  390. goto EXIT;
  391. }
  392. Fdt = (VOID*)(UINTN)NewFdtBlobBase;
  393. Status = DelPhyhandleUpdateMacAddress(Fdt);
  394. if (EFI_ERROR (Status))
  395. {
  396. DEBUG ((EFI_D_ERROR, "DelPhyhandleUpdateMacAddress fail:\n"));
  397. Status = EFI_SUCCESS;
  398. }
  399. Status = UpdateRefClk (Fdt);
  400. if (EFI_ERROR (Status)) {
  401. DEBUG ((DEBUG_ERROR, "UpdateiRefClk fail.\n"));
  402. }
  403. Status = UpdateMemoryNode(Fdt);
  404. if (EFI_ERROR (Status))
  405. {
  406. DEBUG ((EFI_D_ERROR, "UpdateMemoryNode Error\n"));
  407. goto EXIT;
  408. }
  409. UpdateNumaStatus = UpdateNumaNode(Fdt);
  410. if (EFI_ERROR (UpdateNumaStatus))
  411. {
  412. DEBUG ((EFI_D_ERROR, "Update NumaNode fail\n"));
  413. }
  414. gBS->CopyMem(((VOID*)(UINTN)(FdtFileAddr)),((VOID*)(UINTN)(NewFdtBlobBase)),NewFdtBlobSize);
  415. EXIT:
  416. gBS->FreePages(NewFdtBlobBase,EFI_SIZE_TO_PAGES(NewFdtBlobSize));
  417. return Status;
  418. }