1 /** @file
2 *
3 *  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
4 *  Copyright (c) 2014, 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 
16 #include <PiPei.h>
17 
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/HobLib.h>
21 #include <Library/PcdLib.h>
22 #include <libfdt.h>
23 
24 #include <Guid/EarlyPL011BaseAddress.h>
25 #include <Guid/FdtHob.h>
26 
27 EFI_STATUS
28 EFIAPI
PlatformPeim(VOID)29 PlatformPeim (
30   VOID
31   )
32 {
33   VOID               *Base;
34   VOID               *NewBase;
35   UINTN              FdtSize;
36   UINTN              FdtPages;
37   UINT64             *FdtHobData;
38   UINT64             *UartHobData;
39   INT32              Node, Prev;
40   CONST CHAR8        *Compatible;
41   CONST CHAR8        *CompItem;
42   INT32              Len;
43   CONST UINT64       *RegProp;
44   UINT64             UartBase;
45 
46 
47   Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
48   ASSERT (Base != NULL);
49   ASSERT (fdt_check_header (Base) == 0);
50 
51   FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreeAllocationPadding);
52   FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
53   NewBase = AllocatePages (FdtPages);
54   ASSERT (NewBase != NULL);
55   fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
56 
57   FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
58   ASSERT (FdtHobData != NULL);
59   *FdtHobData = (UINTN)NewBase;
60 
61   UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
62   ASSERT (UartHobData != NULL);
63   *UartHobData = 0;
64 
65   //
66   // Look for a UART node
67   //
68   for (Prev = 0;; Prev = Node) {
69     Node = fdt_next_node (Base, Prev, NULL);
70     if (Node < 0) {
71       break;
72     }
73 
74     //
75     // Check for UART node
76     //
77     Compatible = fdt_getprop (Base, Node, "compatible", &Len);
78 
79     //
80     // Iterate over the NULL-separated items in the compatible string
81     //
82     for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
83       CompItem += 1 + AsciiStrLen (CompItem)) {
84 
85       if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
86         RegProp = fdt_getprop (Base, Node, "reg", &Len);
87         ASSERT (Len == 16);
88 
89         UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
90 
91         DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
92 
93         *UartHobData = UartBase;
94         break;
95       }
96     }
97   }
98 
99   BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
100 
101   return EFI_SUCCESS;
102 }
103