common: Drop image.h from common header
[oweals/u-boot.git] / arch / x86 / lib / mrccache.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * From coreboot src/southbridge/intel/bd82x6x/mrccache.c
4  *
5  * Copyright (C) 2014 Google Inc.
6  * Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com>
7  */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <fdtdec.h>
13 #include <malloc.h>
14 #include <net.h>
15 #include <spi.h>
16 #include <spi_flash.h>
17 #include <asm/mrccache.h>
18 #include <dm/device-internal.h>
19 #include <dm/uclass-internal.h>
20
21 DECLARE_GLOBAL_DATA_PTR;
22
23 static uint mrc_block_size(uint data_size)
24 {
25         uint mrc_size = sizeof(struct mrc_data_container) + data_size;
26
27         return ALIGN(mrc_size, MRC_DATA_ALIGN);
28 }
29
30 static struct mrc_data_container *next_mrc_block(
31         struct mrc_data_container *cache)
32 {
33         /* MRC data blocks are aligned within the region */
34         u8 *region_ptr = (u8 *)cache;
35
36         region_ptr += mrc_block_size(cache->data_size);
37
38         return (struct mrc_data_container *)region_ptr;
39 }
40
41 static int is_mrc_cache(struct mrc_data_container *cache)
42 {
43         return cache && (cache->signature == MRC_DATA_SIGNATURE);
44 }
45
46 struct mrc_data_container *mrccache_find_current(struct mrc_region *entry)
47 {
48         struct mrc_data_container *cache, *next;
49         ulong base_addr, end_addr;
50         uint id;
51
52         base_addr = entry->base + entry->offset;
53         end_addr = base_addr + entry->length;
54         cache = NULL;
55
56         /* Search for the last filled entry in the region */
57         for (id = 0, next = (struct mrc_data_container *)base_addr;
58              is_mrc_cache(next);
59              id++) {
60                 cache = next;
61                 next = next_mrc_block(next);
62                 if ((ulong)next >= end_addr)
63                         break;
64         }
65
66         if (id-- == 0) {
67                 debug("%s: No valid MRC cache found.\n", __func__);
68                 return NULL;
69         }
70
71         /* Verify checksum */
72         if (cache->checksum != compute_ip_checksum(cache->data,
73                                                    cache->data_size)) {
74                 printf("%s: MRC cache checksum mismatch\n", __func__);
75                 return NULL;
76         }
77
78         debug("%s: picked entry %u from cache block\n", __func__, id);
79
80         return cache;
81 }
82
83 /**
84  * find_next_mrc_cache() - get next cache entry
85  *
86  * This moves to the next cache entry in the region, making sure it has enough
87  * space to hold data of size @data_size.
88  *
89  * @entry:      MRC cache flash area
90  * @cache:      Entry to start from
91  * @data_size:  Required data size of the new entry. Note that we assume that
92  *      all cache entries are the same size
93  *
94  * @return next cache entry if found, NULL if we got to the end
95  */
96 static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
97                 struct mrc_data_container *prev, int data_size)
98 {
99         struct mrc_data_container *cache;
100         ulong base_addr, end_addr;
101
102         base_addr = entry->base + entry->offset;
103         end_addr = base_addr + entry->length;
104
105         /*
106          * We assume that all cache entries are the same size, but let's use
107          * data_size here for clarity.
108          */
109         cache = next_mrc_block(prev);
110         if ((ulong)cache + mrc_block_size(data_size) > end_addr) {
111                 /* Crossed the boundary */
112                 cache = NULL;
113                 debug("%s: no available entries found\n", __func__);
114         } else {
115                 debug("%s: picked next entry from cache block at %p\n",
116                       __func__, cache);
117         }
118
119         return cache;
120 }
121
122 /**
123  * mrccache_update() - update the MRC cache with a new record
124  *
125  * This writes a new record to the end of the MRC cache region. If the new
126  * record is the same as the latest record then the write is skipped
127  *
128  * @sf:         SPI flash to write to
129  * @entry:      Position and size of MRC cache in SPI flash
130  * @cur:        Record to write
131  * @return 0 if updated, -EEXIST if the record is the same as the latest
132  * record, -EINVAL if the record is not valid, other error if SPI write failed
133  */
134 static int mrccache_update(struct udevice *sf, struct mrc_region *entry,
135                            struct mrc_data_container *cur)
136 {
137         struct mrc_data_container *cache;
138         ulong offset;
139         ulong base_addr;
140         int ret;
141
142         if (!is_mrc_cache(cur)) {
143                 debug("%s: Cache data not valid\n", __func__);
144                 return -EINVAL;
145         }
146
147         /* Find the last used block */
148         base_addr = entry->base + entry->offset;
149         debug("Updating MRC cache data\n");
150         cache = mrccache_find_current(entry);
151         if (cache && (cache->data_size == cur->data_size) &&
152             (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) {
153                 debug("MRC data in flash is up to date. No update\n");
154                 return -EEXIST;
155         }
156
157         /* Move to the next block, which will be the first unused block */
158         if (cache)
159                 cache = find_next_mrc_cache(entry, cache, cur->data_size);
160
161         /*
162          * If we have got to the end, erase the entire mrc-cache area and start
163          * again at block 0.
164          */
165         if (!cache) {
166                 debug("Erasing the MRC cache region of %x bytes at %x\n",
167                       entry->length, entry->offset);
168
169                 ret = spi_flash_erase_dm(sf, entry->offset, entry->length);
170                 if (ret) {
171                         debug("Failed to erase flash region\n");
172                         return ret;
173                 }
174                 cache = (struct mrc_data_container *)base_addr;
175         }
176
177         /* Write the data out */
178         offset = (ulong)cache - base_addr + entry->offset;
179         debug("Write MRC cache update to flash at %lx\n", offset);
180         ret = spi_flash_write_dm(sf, offset, cur->data_size + sizeof(*cur),
181                                  cur);
182         if (ret) {
183                 debug("Failed to write to SPI flash\n");
184                 return log_msg_ret("Cannot update mrccache", ret);
185         }
186
187         return 0;
188 }
189
190 static void mrccache_setup(struct mrc_output *mrc, void *data)
191 {
192         struct mrc_data_container *cache = data;
193         u16 checksum;
194
195         cache->signature = MRC_DATA_SIGNATURE;
196         cache->data_size = mrc->len;
197         checksum = compute_ip_checksum(mrc->buf, cache->data_size);
198         debug("Saving %d bytes for MRC output data, checksum %04x\n",
199               cache->data_size, checksum);
200         cache->checksum = checksum;
201         cache->reserved = 0;
202         memcpy(cache->data, mrc->buf, cache->data_size);
203
204         mrc->cache = cache;
205 }
206
207 int mrccache_reserve(void)
208 {
209         int i;
210
211         for (i = 0; i < MRC_TYPE_COUNT; i++) {
212                 struct mrc_output *mrc = &gd->arch.mrc[i];
213
214                 if (!mrc->len)
215                         continue;
216
217                 /* adjust stack pointer to store pure cache data plus header */
218                 gd->start_addr_sp -= (mrc->len + MRC_DATA_HEADER_SIZE);
219                 mrccache_setup(mrc, (void *)gd->start_addr_sp);
220
221                 gd->start_addr_sp &= ~0xf;
222         }
223
224         return 0;
225 }
226
227 int mrccache_get_region(enum mrc_type_t type, struct udevice **devp,
228                         struct mrc_region *entry)
229 {
230         struct udevice *dev;
231         ofnode mrc_node;
232         ulong map_base;
233         uint map_size;
234         uint offset;
235         u32 reg[2];
236         int ret;
237
238         /*
239          * Find the flash chip within the SPI controller node. Avoid probing
240          * the device here since it may put it into a strange state where the
241          * memory map cannot be read.
242          */
243         ret = uclass_find_first_device(UCLASS_SPI_FLASH, &dev);
244         if (!ret && !dev)
245                 ret = -ENODEV;
246         if (ret)
247                 return log_msg_ret("Cannot find SPI flash\n", ret);
248         ret = dm_spi_get_mmap(dev, &map_base, &map_size, &offset);
249         if (!ret) {
250                 entry->base = map_base;
251         } else {
252                 ret = dev_read_u32_array(dev, "memory-map", reg, 2);
253                 if (ret)
254                         return log_msg_ret("Cannot find memory map\n", ret);
255                 entry->base = reg[0];
256         }
257
258         /* Find the place where we put the MRC cache */
259         mrc_node = dev_read_subnode(dev, type == MRC_TYPE_NORMAL ?
260                                     "rw-mrc-cache" : "rw-var-mrc-cache");
261         if (!ofnode_valid(mrc_node))
262                 return log_msg_ret("Cannot find node", -EPERM);
263
264         ret = ofnode_read_u32_array(mrc_node, "reg", reg, 2);
265         if (ret)
266                 return log_msg_ret("Cannot find address", ret);
267         entry->offset = reg[0];
268         entry->length = reg[1];
269
270         if (devp)
271                 *devp = dev;
272         debug("MRC cache type %d in '%s', offset %x, len %x, base %x\n",
273               type, dev->name, entry->offset, entry->length, entry->base);
274
275         return 0;
276 }
277
278 static int mrccache_save_type(enum mrc_type_t type)
279 {
280         struct mrc_data_container *cache;
281         struct mrc_output *mrc;
282         struct mrc_region entry;
283         struct udevice *sf;
284         int ret;
285
286         mrc = &gd->arch.mrc[type];
287         if (!mrc->len)
288                 return 0;
289         log_debug("Saving %#x bytes of MRC output data type %d to SPI flash\n",
290                   mrc->len, type);
291         ret = mrccache_get_region(type, &sf, &entry);
292         if (ret)
293                 return log_msg_ret("Cannot get region", ret);
294         ret = device_probe(sf);
295         if (ret)
296                 return log_msg_ret("Cannot probe device", ret);
297         cache = mrc->cache;
298
299         ret = mrccache_update(sf, &entry, cache);
300         if (!ret)
301                 debug("Saved MRC data with checksum %04x\n", cache->checksum);
302         else if (ret == -EEXIST)
303                 debug("MRC data is the same as last time, skipping save\n");
304
305         return 0;
306 }
307
308 int mrccache_save(void)
309 {
310         int i;
311
312         for (i = 0; i < MRC_TYPE_COUNT; i++) {
313                 int ret;
314
315                 ret = mrccache_save_type(i);
316                 if (ret)
317                         return ret;
318         }
319
320         return 0;
321 }
322
323 int mrccache_spl_save(void)
324 {
325         int i;
326
327         for (i = 0; i < MRC_TYPE_COUNT; i++) {
328                 struct mrc_output *mrc = &gd->arch.mrc[i];
329                 void *data;
330                 int size;
331
332                 size = mrc->len + MRC_DATA_HEADER_SIZE;
333                 data = malloc(size);
334                 if (!data)
335                         return log_msg_ret("Allocate MRC cache block", -ENOMEM);
336                 mrccache_setup(mrc, data);
337         }
338
339         return mrccache_save();
340 }