]> Git Repo - J-u-boot.git/blob - cmd/seama.c
Merge patch series "Cumulative fixes and updates for MediaTek ethernet driver"
[J-u-boot.git] / cmd / seama.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2023 Linus Walleij <[email protected]>
4  * Support for the "SEAttle iMAge" SEAMA NAND image format
5  */
6
7 #include <command.h>
8 #include <nand.h>
9
10 /*
11  * All SEAMA data is stored in the flash in "network endianness"
12  * i.e. big endian, which means that it needs to be byte-swapped
13  * on all little endian platforms.
14  *
15  * structure for a SEAMA entity in NAND flash:
16  *
17  * 32 bit SEAMA magic 0x5EA3A417
18  * 16 bit reserved
19  * 16 bit metadata size (following the header)
20  * 32 bit image size
21  * 16 bytes MD5 digest of the image
22  * meta data
23  * ... image data ...
24  *
25  * Then if a new SEAMA magic follows, that is the next image.
26  */
27
28 #define SEAMA_MAGIC             0x5EA3A417
29 #define SEAMA_HDR_NO_META_SZ    28
30 #define SEAMA_MAX_META_SZ       (1024 - SEAMA_HDR_NO_META_SZ)
31
32 struct seama_header {
33         u32 magic;
34         u32 meta_size;
35         u32 image_size;
36         u8 md5[16];
37         u8 metadata[SEAMA_MAX_META_SZ];
38 };
39
40 static struct seama_header shdr;
41
42 static int env_set_val(const char *varname, ulong val)
43 {
44         int ret;
45
46         ret = env_set_hex(varname, val);
47         if (ret)
48                 printf("Failed to %s env var\n", varname);
49
50         return ret;
51 }
52
53 static int do_seama_load_image(struct cmd_tbl *cmdtp, int flag, int argc,
54                                char *const argv[])
55 {
56         struct mtd_info *mtd;
57         uintptr_t load_addr;
58         unsigned long image_index;
59         u32 len;
60         size_t readsz;
61         int ret;
62         u32 *start;
63         u32 *offset;
64         u32 *end;
65         u32 tmp;
66
67         if (argc < 2 || argc > 3)
68                 return CMD_RET_USAGE;
69
70         load_addr = hextoul(argv[1], NULL);
71         if (!load_addr) {
72                 printf("Invalid load address\n");
73                 return CMD_RET_USAGE;
74         }
75
76         /* Can be 0 for first image */
77         image_index = hextoul(argv[2], NULL);
78
79         /* We only support one NAND, the first one */
80         nand_curr_device = 0;
81         mtd = get_nand_dev_by_index(0);
82         if (!mtd) {
83                 printf("NAND Device 0 not available\n");
84                 return CMD_RET_FAILURE;
85         }
86
87 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
88         board_nand_select_device(mtd_to_nand(mtd), 0);
89 #endif
90
91         printf("Loading SEAMA image %lu from %s\n", image_index, mtd->name);
92
93         readsz = sizeof(shdr);
94         offset = 0;
95         ret = nand_read_skip_bad(mtd, 0, &readsz, NULL, mtd->size,
96                                  (u_char *)&shdr);
97         if (ret) {
98                 printf("Read error reading SEAMA header\n");
99                 return CMD_RET_FAILURE;
100         }
101
102         if (shdr.magic != SEAMA_MAGIC) {
103                 printf("Invalid SEAMA image magic: 0x%08x\n", shdr.magic);
104                 return CMD_RET_FAILURE;
105         }
106
107         /* Only the lower 16 bits are valid */
108         shdr.meta_size &= 0xFFFF;
109
110         if (env_set_val("seama_image_size", 0))
111                 return CMD_RET_FAILURE;
112
113         printf("SEMA IMAGE:\n");
114         printf("  metadata size %d\n", shdr.meta_size);
115         printf("  image size %d\n", shdr.image_size);
116         printf("  checksum %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
117                shdr.md5[0], shdr.md5[1], shdr.md5[2], shdr.md5[3],
118                shdr.md5[4], shdr.md5[5], shdr.md5[6], shdr.md5[7],
119                shdr.md5[8], shdr.md5[9], shdr.md5[10], shdr.md5[11],
120                shdr.md5[12], shdr.md5[13], shdr.md5[14], shdr.md5[15]);
121
122         /* TODO: handle metadata if needed */
123
124         len = shdr.image_size;
125         if (env_set_val("seama_image_size", len))
126                 return CMD_RET_FAILURE;
127
128         /* We need to include the header (read full pages) */
129         readsz = shdr.image_size + SEAMA_HDR_NO_META_SZ + shdr.meta_size;
130         ret = nand_read_skip_bad(mtd, 0, &readsz, NULL, mtd->size,
131                                  (u_char *)load_addr);
132         if (ret) {
133                 printf("Read error reading SEAMA main image\n");
134                 return CMD_RET_FAILURE;
135         }
136
137         /* We use a temporary variable tmp to avoid to hairy casts */
138         start = (u32 *)load_addr;
139         tmp = (u32)start;
140         tmp += SEAMA_HDR_NO_META_SZ + shdr.meta_size;
141         offset = (u32 *)tmp;
142         tmp += shdr.image_size;
143         end = (u32 *)tmp;
144
145         printf("Decoding SEAMA image 0x%08x..0x%08x to 0x%08x\n",
146                (u32)offset, (u32)end, (u32)start);
147         for (; start < end; start++, offset++)
148                 *start = be32_to_cpu(*offset);
149
150         return CMD_RET_SUCCESS;
151 }
152
153 U_BOOT_CMD
154         (seama, 3, 1, do_seama_load_image,
155          "Load the SEAMA image and sets envs",
156          "seama <addr> <imageindex>\n"
157 );
This page took 0.031259 seconds and 4 git commands to generate.