Merge tag 'u-boot-imx-20200107' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
[oweals/u-boot.git] / arch / x86 / lib / fsp2 / fsp_support.c
1 // SPDX-License-Identifier: Intel
2 /*
3  * Copyright 2019 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <spi_flash.h>
10 #include <asm/fsp/fsp_support.h>
11 #include <asm/fsp2/fsp_internal.h>
12
13 /* The amount of the FSP header to probe to obtain what we need */
14 #define PROBE_BUF_SIZE 0x180
15
16 int fsp_get_header(ulong offset, ulong size, bool use_spi_flash,
17                    struct fsp_header **fspp)
18 {
19         static efi_guid_t guid = FSP_HEADER_GUID;
20         struct fv_ext_header *exhdr;
21         struct fsp_header *fsp;
22         struct ffs_file_header *file_hdr;
23         struct fv_header *fv;
24         struct raw_section *raw;
25         void *ptr, *base;
26         u8 buf[PROBE_BUF_SIZE];
27         struct udevice *dev;
28         int ret;
29
30         /*
31          * There are quite a very steps to work through all the headers in this
32          * file and the structs have similar names. Turn on debugging if needed
33          * to understand what is going wrong.
34          *
35          * You are in a maze of twisty little headers all alike.
36          */
37         debug("offset=%x buf=%x\n", (uint)offset, (uint)buf);
38         if (use_spi_flash) {
39                 ret = uclass_first_device_err(UCLASS_SPI_FLASH, &dev);
40                 if (ret)
41                         return log_msg_ret("Cannot find flash device", ret);
42                 ret = spi_flash_read_dm(dev, offset, PROBE_BUF_SIZE, buf);
43                 if (ret)
44                         return log_msg_ret("Cannot read flash", ret);
45         } else {
46                 memcpy(buf, (void *)offset, PROBE_BUF_SIZE);
47         }
48
49         /* Initalise the FSP base */
50         ptr = buf;
51         fv = ptr;
52
53         /* Check the FV signature, _FVH */
54         debug("offset=%x sign=%x\n", (uint)offset, (uint)fv->sign);
55         if (fv->sign != EFI_FVH_SIGNATURE)
56                 return log_msg_ret("Base FV signature", -EINVAL);
57
58         /* Go to the end of the FV header and align the address */
59         debug("fv->ext_hdr_off = %x\n", fv->ext_hdr_off);
60         ptr += fv->ext_hdr_off;
61         exhdr = ptr;
62         ptr += ALIGN(exhdr->ext_hdr_size, 8);
63         debug("ptr=%x\n", ptr - (void *)buf);
64
65         /* Check the FFS GUID */
66         file_hdr = ptr;
67         if (memcmp(&file_hdr->name, &guid, sizeof(guid)))
68                 return log_msg_ret("Base FFS GUID", -ENXIO);
69         /* Add the FFS header size to find the raw section header */
70         ptr = file_hdr + 1;
71
72         raw = ptr;
73         debug("raw->type = %x\n", raw->type);
74         if (raw->type != EFI_SECTION_RAW)
75                 return log_msg_ret("Section type not RAW", -ENOEXEC);
76
77         /* Add the raw section header size to find the FSP header */
78         ptr = raw + 1;
79         fsp = ptr;
80
81         /* Check the FSPH header */
82         debug("fsp %x\n", (uint)fsp);
83         if (fsp->sign != EFI_FSPH_SIGNATURE)
84                 return log_msg_ret("Base FSPH signature", -EACCES);
85
86         base = (void *)fsp->img_base;
87         debug("Image base %x\n", (uint)base);
88         debug("Image addr %x\n", (uint)fsp->fsp_mem_init);
89         if (use_spi_flash) {
90                 ret = spi_flash_read_dm(dev, offset, size, base);
91                 if (ret)
92                         return log_msg_ret("Could not read FPS-M", ret);
93         } else {
94                 memcpy(base, (void *)offset, size);
95         }
96         ptr = base + (ptr - (void *)buf);
97         *fspp = ptr;
98
99         return 0;
100 }
101
102 u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase)
103 {
104         fsp_notify_f notify;
105         struct fsp_notify_params params;
106         struct fsp_notify_params *params_ptr;
107         u32 status;
108
109         if (!fsp_hdr)
110                 fsp_hdr = gd->arch.fsp_s_hdr;
111
112         if (!fsp_hdr)
113                 return log_msg_ret("no FSP", -ENOENT);
114
115         notify = (fsp_notify_f)(fsp_hdr->img_base + fsp_hdr->fsp_notify);
116         params.phase = phase;
117         params_ptr = &params;
118
119         /*
120          * Use ASM code to ensure correct parameter is on the stack for
121          * FspNotify as U-Boot is using different ABI from FSP
122          */
123         asm volatile (
124                 "pushl  %1;"            /* push notify phase */
125                 "call   *%%eax;"        /* call FspNotify */
126                 "addl   $4, %%esp;"     /* clean up the stack */
127                 : "=a"(status) : "m"(params_ptr), "a"(notify), "m"(*params_ptr)
128         );
129
130         return status;
131 }