+int bootstage_unstash(const void *base, int size)
+{
+ const struct bootstage_hdr *hdr = (struct bootstage_hdr *)base;
+ struct bootstage_data *data = gd->bootstage;
+ const char *ptr = base, *end = ptr + size;
+ struct bootstage_record *rec;
+ uint rec_size;
+ int i;
+
+ if (size == -1)
+ end = (char *)(~(uintptr_t)0);
+
+ if (hdr + 1 > (struct bootstage_hdr *)end) {
+ debug("%s: Not enough space for bootstage hdr\n", __func__);
+ return -EPERM;
+ }
+
+ if (hdr->magic != BOOTSTAGE_MAGIC) {
+ debug("%s: Invalid bootstage magic\n", __func__);
+ return -ENOENT;
+ }
+
+ if (ptr + hdr->size > end) {
+ debug("%s: Bootstage data runs past buffer end\n", __func__);
+ return -ENOSPC;
+ }
+
+ if (hdr->count * sizeof(*rec) > hdr->size) {
+ debug("%s: Bootstage has %d records needing %lu bytes, but "
+ "only %d bytes is available\n", __func__, hdr->count,
+ (ulong)hdr->count * sizeof(*rec), hdr->size);
+ return -ENOSPC;
+ }
+
+ if (hdr->version != BOOTSTAGE_VERSION) {
+ debug("%s: Bootstage data version %#0x unrecognised\n",
+ __func__, hdr->version);
+ return -EINVAL;
+ }
+
+ if (data->rec_count + hdr->count > RECORD_COUNT) {
+ debug("%s: Bootstage has %d records, we have space for %d\n"
+ "Please increase CONFIG_(SPL_)BOOTSTAGE_RECORD_COUNT\n",
+ __func__, hdr->count, RECORD_COUNT - data->rec_count);
+ return -ENOSPC;
+ }
+
+ ptr += sizeof(*hdr);
+
+ /* Read the records */
+ rec_size = hdr->count * sizeof(*data->record);
+ memcpy(data->record + data->rec_count, ptr, rec_size);
+
+ /* Read the name strings */
+ ptr += rec_size;
+ for (rec = data->record + data->next_id, i = 0; i < hdr->count;
+ i++, rec++) {
+ rec->name = ptr;
+
+ /* Assume no data corruption here */
+ ptr += strlen(ptr) + 1;
+ }
+
+ /* Mark the records as read */
+ data->rec_count += hdr->count;
+ debug("Unstashed %d records\n", hdr->count);
+
+ return 0;
+}
+
+int bootstage_get_size(void)
+{
+ return sizeof(struct bootstage_data);
+}
+
+int bootstage_init(bool first)
+{
+ struct bootstage_data *data;
+ int size = sizeof(struct bootstage_data);
+
+ gd->bootstage = (struct bootstage_data *)malloc(size);
+ if (!gd->bootstage)
+ return -ENOMEM;
+ data = gd->bootstage;
+ memset(data, '\0', size);
+ if (first) {
+ data->next_id = BOOTSTAGE_ID_USER;
+ bootstage_add_record(BOOTSTAGE_ID_AWAKE, "reset", 0, 0);
+ }
+
+ return 0;
+}