2 * TI OMAP3 boot ROM emulation. Based on information in the OMAP34xx 3.1
3 * Technical Reference Manual from Texas Instruments.
5 * Copyright (C) 2009 Nokia Corporation
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "qemu-char.h"
29 /* list of supported NAND devices according to the OMAP34xx TRM */
34 } omap3_boot_nand_devices[] = {
35 {0xe6, 512, 64}, {0x33, 512, 128}, {0x73, 512, 128},
36 {0x43, 512, 128}, {0x53, 512, 128}, {0x35, 512, 256},
37 {0x75, 512, 256}, {0x45, 512, 256}, {0x55, 512, 256},
38 {0x36, 512, 512}, {0x76, 512, 512}, {0x46, 512, 512},
39 {0x56, 512, 512}, {0xa2, 2048, 512}, {0xf2, 2048, 512},
40 {0xb2, 2048, 512}, {0xc2, 2048, 512}, {0x39, 512, 1024},
41 {0x79, 512, 1024}, {0x49, 512, 1024}, {0x59, 512, 1024},
42 {0x78, 512, 1024}, {0x72, 512, 1024}, {0x74, 512, 1024},
43 {0xa1, 2048, 1024}, {0xf1, 2048, 1024}, {0xb1, 2048, 1024},
44 {0xc1, 2048, 1024}, {0xaa, 2048, 2048}, {0xda, 2048, 2048},
45 {0xba, 2048, 2048}, {0xca, 2048, 2048}, {0x71, 512, 2048},
46 {0x51, 512, 2048}, {0x31, 512, 2048}, {0x41, 512, 2048},
47 {0xac, 2048, 4096}, {0xdc, 2048, 4096}, {0xbc, 2048, 4096},
48 {0xcc, 2048, 4096}, {0xa3, 2048, 8192}, {0xd3, 2048, 8192},
49 {0xb3, 2048, 8192}, {0xc3, 2048, 8192}, {0xa5, 2048, 16384},
50 {0xd5, 2048, 16384}, {0xb5, 2048, 16384}, {0xc5, 2048, 16384},
51 {0xa7, 2048, 32768}, {0xb7, 2048, 32768}, {0xae, 2048, 65536},
56 struct omap3_nand_boot_desc_s {
62 /* first 80kB (reserved section) */
63 static const uint8_t omap3_boot_rom_block1[] = { /* 0x40000000-0x40013fff */
64 /* this gets mapped to zero at power-up so let's have a branch
65 * table to the upper block ROM exception vectors here */
66 0xfe, 0x4f, 0x00, 0xea, /* b 0x40014000 */
67 0xfe, 0x4f, 0x00, 0xea, /* b 0x40014004 */
68 0xfe, 0x4f, 0x00, 0xea, /* b 0x40014008 */
69 0xfe, 0x4f, 0x00, 0xea, /* b 0x4001400c */
70 0xfe, 0x4f, 0x00, 0xea, /* b 0x40014010 */
71 0xfe, 0x4f, 0x00, 0xea, /* b 0x40014014 */
72 0xfe, 0x4f, 0x00, 0xea, /* b 0x40014018 */
73 0xfe, 0x4f, 0x00, 0xea, /* b 0x4001401c */
77 static const uint8_t omap3_boot_rom_block2[] = { /* 0x40014000-0x4001bfff */
78 /* 0x40014000: ROM Exception vectors */
79 0x3e, 0x00, 0x00, 0xea, /* b 0x40014100 */
80 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
81 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
82 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
83 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
84 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
85 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
86 0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
87 /* 0x40014020: ROM CRC */
88 0xff, 0xff, 0xff, 0xff,
89 /* 0x40014024: unused(?), we use it for some data */
90 0xc8, 0xff, 0x20, 0x40, /* 0x40014024: undef sram vector address */
91 0xcc, 0xff, 0x20, 0x40, /* 0x40014028: swi sram vector address */
92 0xd0, 0xff, 0x20, 0x40, /* 0x4001402c: pabt sram vector address */
93 0xd4, 0xff, 0x20, 0x40, /* 0x40014030: dabt sram vector address */
94 0xd8, 0xff, 0x20, 0x40, /* 0x40014034: unused sram vector address */
95 0xdc, 0xff, 0x20, 0x40, /* 0x40014038: irq sram vector address */
96 0xe0, 0xff, 0x20, 0x40, /* 0x4001403c: fiq sram vector address */
97 0xff, 0xff, 0xff, 0xff, /* 0x40014040: boot loader image start address */
98 0xff, 0xff, 0xff, 0xff, /* 0x40014044: booting parameter structure 0-3 */
99 0xff, 0xff, 0xff, 0xff, /* 0x40014048: booting parameter structure 4-7 */
100 0xff, 0xff, 0xff, 0xff, /* 0x4001404c: booting parameter structure 8-11 */
101 0x0e, 0xf0, 0xb0, 0xe1, /* 0x40014050: "movs pc, lr" */
102 0xff, 0xff, 0xff, 0xff,
103 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
104 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
105 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108 /* 0x40014080: Dead loops */
109 0xfe, 0xff, 0xff, 0xea, /* b 0x40014080 @ undefined exception */
110 0xfe, 0xff, 0xff, 0xea, /* b 0x40014084 @ swi exception */
111 0xfe, 0xff, 0xff, 0xea, /* b 0x40014088 @ prefetch abort exception */
112 0xfe, 0xff, 0xff, 0xea, /* b 0x4001408c @ data abort exception */
113 0xfe, 0xff, 0xff, 0xea, /* b 0x40014090 @ unused exception */
114 0xfe, 0xff, 0xff, 0xea, /* b 0x40014094 @ irq exception */
115 0xfe, 0xff, 0xff, 0xea, /* b 0x40014098 @ fiq exception */
116 0xfe, 0xff, 0xff, 0xea, /* b 0x4001409c @ validation tests pass */
117 0xfe, 0xff, 0xff, 0xea, /* b 0x400140a0 @ validation tests fail */
118 0xfe, 0xff, 0xff, 0xea, /* b 0x400140a4 @ boot failed: no more devices */
119 0xfe, 0xff, 0xff, 0xea, /* b 0x400140a8 @ image not executed or returned */
120 0xfe, 0xff, 0xff, 0xea, /* b 0x400140ac @ reserved */
121 0xfe, 0xff, 0xff, 0xea, /* b 0x400140b0 @ reserved */
122 0xfe, 0xff, 0xff, 0xea, /* b 0x400140b4 @ reserved */
123 0xfe, 0xff, 0xff, 0xea, /* b 0x400140b8 @ reserved */
124 0xfe, 0xff, 0xff, 0xea, /* b 0x400140bc @ reserved */
125 /* 0x400140c0: should perform a software reset & jump to r0 */
126 0x00, 0xf0, 0xa0, 0xe1, /* mov pc, r0 */
127 0xff, 0xff, 0xff, 0xff,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 /* 0x40014100: code, ROM emulation uses this to launch the
136 * boot loader after it has been read into memory */
137 0xc8, 0x10, 0x1f, 0xe5, /* ldr r1, [#0x40014040] @ boot loader start */
138 0xb0, 0x0c, 0x0f, 0xe3, /* movw r0, #0xfcb0 */
139 0x20, 0x00, 0x44, 0xe3, /* movt r0, #0x4020 @ stack top at 0x4020fcb0 */
140 0xdf, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdf @ enter SYS mode */
141 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
142 0x80, 0x0c, 0x40, 0xe2, /* sub r0, r0, #32768 @ 32kB SYS/USR stack */
143 0xd1, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd1 @ enter FIQ mode */
144 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
145 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB FIQ stack */
146 0xd2, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd2 @ enter IRQ mode */
147 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
148 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB IRQ stack */
149 0xd7, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd7 @ enter ABT mode */
150 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
151 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB ABT stack */
152 0xdb, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdb @ enter UND mode */
153 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
154 0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048 @ 2kB UND stack */
155 0xd3, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd3 @ enter SVC mode */
156 0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 @ 23kB left for SVC stack */
157 0x44, 0x00, 0x04, 0xe3, /* movw r0, #0x4044 */
158 0x01, 0x00, 0x44, 0xe3, /* movt r0, #0x4001 @ r0 -> booting parameter struct */
159 0x01, 0xf0, 0xa0, 0xe1, /* mov pc, r1 */
162 /* SRAM exception vectors, to be placed at 0x4020ffc8 */
163 static const uint8_t omap3_sram_vectors[] = {
164 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe4] @ undefined */
165 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe8] @ swi */
166 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffec] @ prefetch abort */
167 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff0] @ data abort */
168 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff4] @ unused */
169 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff8] @ irq */
170 0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fffc] @ fiq */
171 0x80, 0x40, 0x01, 0x00, /* 0x14080 */
172 0x50, 0x40, 0x01, 0x40, /* 0x40014050 (default is 0x14084) */
173 0x88, 0x40, 0x01, 0x00, /* 0x14088 */
174 0x8c, 0x40, 0x01, 0x00, /* 0x1408c */
175 0x90, 0x40, 0x01, 0x00, /* 0x14090 */
176 0x94, 0x40, 0x01, 0x00, /* 0x14094 */
177 0x98, 0x40, 0x01, 0x00, /* 0x14098 */
180 static inline uint32_t omap3_get_le32(const void *p)
182 const uint8_t *q = (const uint8_t *)p;
191 static inline uint32_t omap3_get_le16(const void *p)
193 const uint8_t *q = (const uint8_t *)p;
200 static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
204 cpu_physical_memory_read(addr, x, 4);
206 x[1] = (lsb >> 8) & 0xff;
207 cpu_physical_memory_write(addr, x, 4);
220 } omap3_boot_device_t;
222 struct omap3_boot_s {
223 struct omap_mpu_state_s *mpu;
224 omap3_boot_device_t devicetype;
234 target_phys_addr_t addr;
238 static struct omap3_boot_s *omap3_boot_init(struct omap_mpu_state_s *mpu,
239 omap3_boot_device_t dtype,
243 struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
245 s->devicetype = dtype;
247 if (data_len >= 512) {
248 if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
249 || !strncasecmp((char *)(data + 0x14), "chram", 5)
250 || !strncasecmp((char *)(data + 0x14), "chflash", 7)
251 || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
252 s->state = confighdr;
257 static void omap3_boot_chsettings(struct omap3_boot_s *boot,
258 const uint8_t *chtoc)
262 if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
263 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
266 if (!chtoc[4]) { /* section disabled? */
269 if (omap3_get_le16(chtoc + 5) != 0x0001) {
270 fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
271 omap3_get_le16(chtoc));
274 boot->chflags |= 0x01;
275 flags = omap3_get_le32(chtoc + 8);
278 cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
279 cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
280 cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
281 if (flags & (1 << 2)) { /* clock configuration */
282 cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
283 cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
285 if (flags & (1 << 5)) { /* DPLL3 CORE */
286 if (flags & (1 << 8)) { /* enable DPLL3 bypass */
287 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
288 x &= ~7; x |= 5; /* set DPLL3 bypass */
289 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
291 cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
292 cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
293 cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
295 if (flags & (1 << 3)) { /* DPLL4 PER */
296 if (flags & (1 << 6)) { /* enable DPLL4 bypass */
297 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
298 x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
299 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
301 cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
302 cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
303 cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
304 cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
306 if (flags & (1 << 3)) { /* DPLL1 MPU */
307 if (flags & (1 << 7)) { /* enable DPLL1 bypass */
308 cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
309 x &= ~7; x |= 5; /* set DPLL1 bypass */
310 cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
312 cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
313 cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
314 cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
315 cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
316 cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
318 switch ((flags >> 24) & 0xff) {
319 case 0x01: x = 0; break; /* 12MHz */
320 case 0x02: x = 1; break; /* 13MHz */
321 case 0x03: x = 5; break; /* 16.8MHz */
322 case 0x04: x = 2; break; /* 19.2MHz */
323 case 0x05: x = 3; break; /* 26MHz */
324 case 0x06: x = 4; break; /* 38.4MHz */
326 fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
330 if (x != omap3_get_le32(chtoc + 0x04)) {
331 fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
336 static void omap3_boot_chram(struct omap3_boot_s *boot,
337 const uint8_t *chtoc)
339 if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
340 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
343 if (!chtoc[4]) { /* section disabled? */
346 boot->chflags |= 0x02;
347 omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
348 omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
349 cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4); /* SDRC_DLLA_CTRL */
351 cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4); /* SDRC_MCFG_0 */
352 omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
353 omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
354 omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
355 omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
356 cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4); /* SDRC_ACTIM_CTRLA_0 */
357 cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4); /* SDRC_ACTIM_CTRLB_0 */
358 cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4); /* SDRC_RFR_CTRL_0 */
360 cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4); /* SDRC_MCFG_1 */
361 omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
362 omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
363 omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
364 omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
365 cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4); /* SDRC_ACTIM_CTRLA_1 */
366 cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4); /* SDRC_ACTIM_CTRLB_1 */
367 cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4); /* SDRC_RFR_CTRL_1 */
370 static void omap3_boot_chflash(struct omap3_boot_s *boot,
371 const uint8_t *chtoc)
373 if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
374 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
377 if (!chtoc[4]) { /* section disabled? */
380 boot->chflags |= 0x04;
381 omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
382 omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
383 omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
384 omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
385 cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4); /* GPMC_CONFIG1_0 */
386 cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4); /* GPMC_CONFIG2_0 */
387 cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4); /* GPMC_CONFIG3_0 */
388 cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4); /* GPMC_CONFIG4_0 */
389 cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4); /* GPMC_CONFIG5_0 */
390 cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4); /* GPMC_CONFIG6_0 */
391 cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4); /* GPMC_CONFIG7_0 */
392 cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4); /* GPMC_PREFETCH_CONFIG1 */
393 omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
394 omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
395 /* TODO: ECC config registers. The TRM spec is not clear on these */
398 static void omap3_boot_chmmcsd(struct omap3_boot_s *boot,
399 const uint8_t *chtoc)
401 if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
402 fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
405 if (!chtoc[4]) { /* section disabled? */
408 boot->chflags |= 0x08;
409 /* TODO: MMCHS registers */
412 /* returns non-zero if more blocks are needed */
413 static uint32_t omap3_boot_block(const uint8_t *data,
415 struct omap3_boot_s *s)
417 const uint8_t *p = 0;
423 for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
424 if (!strcasecmp((char *)(p + 0x14), "chsettings"))
425 omap3_boot_chsettings(s, p + omap3_get_le32(p));
426 else if (!strcasecmp((char *)(p + 0x14), "chram"))
427 omap3_boot_chram(s, p + omap3_get_le32(p));
428 else if (!strcasecmp((char *)(p + 0x14), "chflash"))
429 omap3_boot_chflash(s, p + omap3_get_le32(p));
430 else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
431 omap3_boot_chmmcsd(s, p + omap3_get_le32(p));
433 fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
434 __FUNCTION__, (char *)(p + 0x14));
448 s->count = omap3_get_le32(data);
449 s->addr = omap3_get_le32(data + 4);
450 if (!s->count || (s->count >> 24) || !s->addr || s->addr == 0xffffffff)
452 /* patch image start address in boot ROM */
453 cpu_physical_memory_write_rom(0x40014040, data + 4, 4);
454 /* start copying image */
460 i = (s->count >= data_len) ? data_len : s->count;
461 cpu_physical_memory_write(s->addr, data, i);
473 /* returns non-zero if boot has finished succesfully */
474 static int omap3_boot_finish(struct omap3_boot_s *s)
477 0, 0, 0, 0, /* last received booting message */
478 (uint8_t)s->devicetype,
482 0, 0, 0, 0 /* device descriptor */
484 int result = (s->state == done);
487 /* fill in the booting parameter structure */
488 cpu_physical_memory_write_rom(0x40014044, x, 12);
494 /* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
495 static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
499 /* there are 0x10 items with 0x20 bytes per item */
500 for (i = 0x10; i--; s += 0x20) {
501 if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
502 if (!*s || !strncasecmp((void *)s, "mlo ", 8+3)) return s;
507 struct omap3_fat_drv_s {
508 BlockDriverState *bs;
509 uint8_t ptype; /* 12, 16, 32 */
510 uint64_t c0; /* physical byte offset for data cluster 0 */
511 uint64_t fat; /* physical byte offset for used FAT sector 0 */
512 uint32_t spc; /* sectors per cluster */
515 /* returns cluster data in the buffer and next cluster chain number
516 or 0 if unsuccessful */
517 static uint32_t omap3_read_fat_cluster(uint8_t *data,
518 struct omap3_fat_drv_s *drv,
522 uint32_t len = drv->spc * 0x200; /* number of bytes to read */
524 switch (drv->ptype) { /* check for EOF */
525 case 12: if (cl > 0xff0) return 0; break;
526 case 16: if (cl > 0xfff0) return 0; break;
527 case 32: if (cl > 0x0ffffff0) return 0; break;
531 if (bdrv_pread(drv->bs,
532 drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
536 switch (drv->ptype) { /* determine next cluster # */
538 fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
542 return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
543 ? 0 : omap3_get_le16(buf);
545 return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
546 ? 0 : omap3_get_le32(buf) & 0x0fffffff;
553 static int omap3_mmc_fat_boot(BlockDriverState *bs,
556 struct omap_mpu_state_s *mpu)
558 struct omap3_fat_drv_s drv;
559 struct omap3_boot_s *boot;
560 uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
561 const uint8_t *p, *q;
565 /* determine FAT type */
568 fatsize = omap3_get_le16(sector + 0x16);
570 fatsize = omap3_get_le32(sector + 0x24);
571 bootsize = omap3_get_le16(sector + 0x0e);
572 cluster0 = bootsize + fatsize * sector[0x10];
573 rootsize = omap3_get_le16(sector + 0x11);
577 drv.spc = sector[0x0d];
578 i = omap3_get_le16(sector + 0x13);
580 i = omap3_get_le32(sector + 0x20);
581 i = (i - (cluster0 + rootsize)) / drv.spc;
582 drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
584 /* search for boot loader file */
586 drv.fat = (bootsize + pstart) * 0x200;
587 drv.c0 = (cluster0 + pstart) * 0x200;
588 if (drv.ptype == 32) {
589 i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
590 j = omap3_get_le16(sector + 0x28);
592 drv.fat += (j & 0x0f) * fatsize * 0x200;
593 cluster = qemu_mallocz(drv.spc * 0x200);
594 for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
595 for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
596 p = omap3_scan_fat_dir_sector(q);
598 memcpy(sector, q - 0x200, 0x200); /* save the sector */
601 } else { /* FAT12/16 */
602 for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
603 if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
605 p = omap3_scan_fat_dir_sector(sector);
609 if (p && *p) { /* did we indeed find the file? */
610 i = omap3_get_le16(p + 0x14);
612 i |= omap3_get_le16(p + 0x1a);
614 uint8 *data = qemu_mallocz(j);
615 if ((i = omap3_read_fat_cluster(data, &drv, i))) {
616 boot = omap3_boot_init(mpu, mmc1, data, j);
617 boot->state = imagehdr; /* override CH detection */
618 while (omap3_boot_block(data, j, boot))
619 i = omap3_read_fat_cluster(data, &drv, i);
620 result = omap3_boot_finish(boot);
622 fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
626 fprintf(stderr, "%s: MLO file not found in the root directory\n",
632 static int omap3_mmc_raw_boot(BlockDriverState *bs,
634 struct omap_mpu_state_s *mpu)
636 struct omap3_boot_s *boot;
640 if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
641 boot = omap3_boot_init(mpu, mmc1, sector, 0x200);
642 if (boot->state == confighdr) { /* CH must be present for raw boot */
643 while (omap3_boot_block(sector, 0x200, boot)) {
644 if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
645 fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
651 result = (boot->state == done);
657 /* returns non-zero if successful, zero if unsuccessful */
658 static int omap3_mmc_boot(struct omap_mpu_state_s *s)
660 BlockDriverState *bs;
661 int sdindex = drive_get_index(IF_SD, 0, 0);
666 /* very simple implementation for GP device boot,
667 supports only two modes:
668 1. MBR partition table with an active FAT partition
669 and boot loader file (MLO) in its root directory, or
670 2. CH sector located on first sector, followed by boot loader image */
672 bs = drives_table[sdindex].bdrv;
673 sector = qemu_mallocz(0x200);
674 if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
675 for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10)
676 if (p[0] == 0x80) break;
677 if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
678 && i < 4 /* active partition exists */
679 && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
680 || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
681 && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
682 sector, 0x200) == 0x200
683 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
684 result = omap3_mmc_fat_boot(bs, sector, pstart, s);
686 result = omap3_mmc_raw_boot(bs, sector, s);
693 static inline void omap3_nand_sendcmd(struct omap3_nand_boot_desc_s *nd,
696 uint8_t x[2] = { cmd, 0 };
698 cpu_physical_memory_write(0x6e00007c, x, nd->bus16 ? 2 : 1);
701 static inline void omap3_nand_sendaddr_byte(struct omap3_nand_boot_desc_s *nd,
704 uint8_t x[2] = { a, 0 };
706 cpu_physical_memory_write(0x6e000080, x, nd->bus16 ? 2 : 1);
709 static inline uint8_t omap3_nand_readbyte(struct omap3_nand_boot_desc_s *nd)
713 cpu_physical_memory_read(0x6e000084, x, nd->bus16 ? 2 : 1);
717 static inline void omap3_nand_readpage(struct omap3_nand_boot_desc_s *nd,
723 omap3_nand_sendcmd(nd, 0x00); /* read page */
724 omap3_nand_sendaddr_byte(nd, 0x00);
725 if (nd->pagesize >= 2048) {
726 omap3_nand_sendaddr_byte(nd, 0x00);
727 omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
728 omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
729 if (nd->capacity_Mb >= 2048)
730 omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 16) & 0xff));
731 omap3_nand_sendcmd(nd, 0x30); /* confirm read */
733 omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
734 omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
737 for (i = nd->pagesize / 2; i--; data += 2)
738 cpu_physical_memory_read(0x6e000084, data, 2);
740 for (i = nd->pagesize; i--; data++)
741 cpu_physical_memory_read(0x6e000084, data, 1);
745 /* returns non-zero if successful, zero if unsuccessful */
746 static int omap3_nand_boot(struct omap_mpu_state_s *mpu, int bus16)
748 struct omap3_nand_boot_desc_s *nd;
749 struct omap3_boot_s *boot;
755 /* TODO: support bad block marks */
756 nd = qemu_mallocz(sizeof(struct omap3_nand_boot_desc_s));
758 omap3_nand_sendcmd(nd, 0xff); /* reset */
759 omap3_nand_sendcmd(nd, 0x90); /* read id */
760 omap3_nand_sendaddr_byte(nd, 0);
761 id[0] = omap3_nand_readbyte(nd); /* manufacturer id */
762 id[1] = omap3_nand_readbyte(nd); /* device id */
763 id[2] = omap3_nand_readbyte(nd); /* don't care */
764 id[3] = omap3_nand_readbyte(nd); /* attributes */
765 for (i = 0; omap3_boot_nand_devices[i].id; i++) {
766 if (omap3_boot_nand_devices[i].id == id[1]) {
767 nd->capacity_Mb = omap3_boot_nand_devices[i].capacity_Mb;
768 if (nd->capacity_Mb > 1024)
769 nd->pagesize = 1024 * (1 << (id[3] & 3));
771 nd->pagesize = omap3_boot_nand_devices[i].pagesize;
775 /* TODO: if device is not recognized at this state, we should
776 * issue READ ID2 command to the device and get device parameters
779 data = qemu_mallocz(nd->pagesize);
780 /* TODO: scan through 4 first blocks for image */
781 omap3_nand_readpage(nd, 0, data);
782 boot = omap3_boot_init(mpu, nand, data, nd->pagesize);
783 while (omap3_boot_block(data, nd->pagesize, boot))
784 omap3_nand_readpage(nd, ++page, data);
785 result = omap3_boot_finish(boot);
793 void omap3_boot_rom_emu(struct omap_mpu_state_s *s)
795 const uint8_t rom_version[4] = { 0x00, 0x14, 0x00, 0x00 }; /* v. 14.00 */
796 uint8_t x[4] = {0, 0, 0, 0};
799 cpu_physical_memory_write_rom(OMAP3_Q1_BASE,
800 omap3_boot_rom_block1,
801 sizeof(omap3_boot_rom_block1));
802 cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x14000,
803 omap3_boot_rom_block2,
804 sizeof(omap3_boot_rom_block2));
805 cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x1bffc,
807 sizeof(rom_version));
808 cpu_physical_memory_write(OMAP3_SRAM_BASE + 0xffc8,
810 sizeof(omap3_sram_vectors));
812 /* if we have NAND in GPMC CS0, try to read boot loader from there.
813 * here we are relying on all memories to be attached and gpmc_attach
814 * to fill in DEVICETYPE field correctly for CS0 for us */
815 cpu_physical_memory_read(0x6e000060, x, 4); /* GPMC_CONFIG1_0 */
816 if (((x[1] >> 2) & 3) == 2) /* DEVICETYPE == NAND? */
817 result = omap3_nand_boot(s, ((x[1] >> 4) & 3) == 1);
819 /* TODO: support OneNAND and XIP */
821 /* if no boot loader found yet, try the MMC/SD card... */
823 result = omap3_mmc_boot(s);
825 if (!result) { /* no boot device found */
826 /* move PC to the appropriate ROM dead loop address */
827 s->env->regs[15] = 0x400140a4;
828 /* ...on second thought, let's just call it a day and quit */
829 cpu_abort(s->env, "no boot device found");