packing update
[qemu] / hw / omap3_boot.c
1 /*
2  * TI OMAP3 boot ROM emulation. Based on information in the OMAP34xx 3.1
3  * Technical Reference Manual from Texas Instruments.
4  *
5  * Copyright (C) 2009 Nokia Corporation
6  *
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.
11  *
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.
16  *
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.
20  */
21 #include "hw.h"
22 #include "arm-misc.h"
23 #include "omap.h"
24 #include "sysemu.h"
25 #include "qemu-char.h"
26 #include "flash.h"
27 #include "block.h"
28
29 /* list of supported NAND devices according to the OMAP34xx TRM */
30 static const struct {
31     uint8_t id;
32     uint32_t pagesize;
33     uint32_t capacity_Mb;
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},
52     {0xbe, 2048, 65536},
53     {0, 0, 0}
54 };
55
56 struct omap3_nand_boot_desc_s {
57     uint32_t pagesize;
58     uint32_t capacity_Mb;
59     uint8_t bus16;
60 };
61
62 static const uint8_t omap3_boot_rom[] = { /* 0x40014000-0x4001bfff */
63     /* 0x40014000: ROM Exception vectors */
64     0x3e, 0x00, 0x00, 0xea, /* b 0x40014100 */
65     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
66     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
67     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
68     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
69     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
70     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
71     0x18, 0xf0, 0x9f, 0xe5, /* ldr pc, [pc, #0x18] */
72     /* 0x40014020: ROM CRC */
73     0xff, 0xff, 0xff, 0xff, 
74     /* 0x40014024: unused(?), we use it for some data */
75     0xc8, 0xff, 0x20, 0x40, /* 0x40014024: undef sram vector address */
76     0xcc, 0xff, 0x20, 0x40, /* 0x40014028: swi sram vector address */
77     0xd0, 0xff, 0x20, 0x40, /* 0x4001402c: pabt sram vector address */
78     0xd4, 0xff, 0x20, 0x40, /* 0x40014030: dabt sram vector address */
79     0xd8, 0xff, 0x20, 0x40, /* 0x40014034: unused sram vector address */
80     0xdc, 0xff, 0x20, 0x40, /* 0x40014038: irq sram vector address */
81     0xe0, 0xff, 0x20, 0x40, /* 0x4001403c: fiq sram vector address */
82     0xff, 0xff, 0xff, 0xff, /* 0x40014040: boot loader image start address */
83     0xff, 0xff, 0xff, 0xff, /* 0x40014044: booting parameter structure 0-3 */
84     0xff, 0xff, 0xff, 0xff, /* 0x40014048: booting parameter structure 4-7 */
85     0xff, 0xff, 0xff, 0xff, /* 0x4001404c: booting parameter structure 8-11 */
86     0x0e, 0xf0, 0xb0, 0xe1, /* 0x40014050: "movs pc, lr" */
87     0xff, 0xff, 0xff, 0xff,
88     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
89     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
90     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
91     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93     /* 0x40014080: Dead loops */
94     0xfe, 0xff, 0xff, 0xea, /* b 0x40014080 @ undefined exception */
95     0xfe, 0xff, 0xff, 0xea, /* b 0x40014084 @ swi exception */
96     0xfe, 0xff, 0xff, 0xea, /* b 0x40014088 @ prefetch abort exception */
97     0xfe, 0xff, 0xff, 0xea, /* b 0x4001408c @ data abort exception */
98     0xfe, 0xff, 0xff, 0xea, /* b 0x40014090 @ unused exception */
99     0xfe, 0xff, 0xff, 0xea, /* b 0x40014094 @ irq exception */
100     0xfe, 0xff, 0xff, 0xea, /* b 0x40014098 @ fiq exception */
101     0xfe, 0xff, 0xff, 0xea, /* b 0x4001409c @ validation tests pass */
102     0xfe, 0xff, 0xff, 0xea, /* b 0x400140a0 @ validation tests fail */
103     0xfe, 0xff, 0xff, 0xea, /* b 0x400140a4 @ boot failed: no more devices */
104     0xfe, 0xff, 0xff, 0xea, /* b 0x400140a8 @ image not executed or returned */
105     0xfe, 0xff, 0xff, 0xea, /* b 0x400140ac @ reserved */
106     0xfe, 0xff, 0xff, 0xea, /* b 0x400140b0 @ reserved */
107     0xfe, 0xff, 0xff, 0xea, /* b 0x400140b4 @ reserved */
108     0xfe, 0xff, 0xff, 0xea, /* b 0x400140b8 @ reserved */
109     0xfe, 0xff, 0xff, 0xea, /* b 0x400140bc @ reserved */
110     /* 0x400140c0: should perform a software reset & jump to r0 */
111     0x00, 0xf0, 0xa0, 0xe1, /* mov pc, r0 */
112     0xff, 0xff, 0xff, 0xff,
113     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
114     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
117     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
118     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
119     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
120     /* 0x40014100: code, ROM emulation uses this to launch the
121      * boot loader after it has been read into memory */
122     0xc8, 0x10, 0x1f, 0xe5, /* ldr r1, [#0x40014040] @ boot loader start */
123     0xb0, 0x0c, 0x0f, 0xe3, /* movw r0, #0xfcb0 */
124     0x20, 0x00, 0x44, 0xe3, /* movt r0, #0x4020   @ stack top at 0x4020fcb0 */
125     0xdf, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdf  @ enter SYS mode */
126     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
127     0x80, 0x0c, 0x40, 0xe2, /* sub r0, r0, #32768 @ 32kB SYS/USR stack */
128     0xd1, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd1  @ enter FIQ mode */
129     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
130     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB FIQ stack */
131     0xd2, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd2  @ enter IRQ mode */
132     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
133     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB IRQ stack */
134     0xd7, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd7  @ enter ABT mode */
135     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
136     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB ABT stack */
137     0xdb, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xdb  @ enter UND mode */
138     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0 */
139     0x08, 0x0c, 0x40, 0xe2, /* sub r0, r0, #2048  @ 2kB UND stack */
140     0xd3, 0xf0, 0x21, 0xe3, /* msr cpsr_c, #0xd3  @ enter SVC mode */
141     0x00, 0xd0, 0xa0, 0xe1, /* mov sp, r0         @ 23kB left for SVC stack */
142     0x44, 0x00, 0x04, 0xe3, /* movw r0, #0x4044 */
143     0x01, 0x00, 0x44, 0xe3, /* movt r0, #0x4001   @ r0 -> booting parameter struct */
144     0x01, 0xf0, 0xa0, 0xe1, /* mov pc, r1 */
145 };
146
147 /* SRAM exception vectors, to be placed at 0x4020ffc8 */
148 static const uint8_t omap3_sram_vectors[] = {
149     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe4] @ undefined */
150     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffe8] @ swi */
151     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020ffec] @ prefetch abort */
152     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff0] @ data abort */
153     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff4] @ unused */
154     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fff8] @ irq */
155     0x14, 0xf0, 0x9f, 0xe5, /* ldr pc, [#0x4020fffc] @ fiq */
156     0x80, 0x40, 0x01, 0x00, /* 0x14080 */
157     0x50, 0x40, 0x01, 0x40, /* 0x40014050 (default is 0x14084) */
158     0x88, 0x40, 0x01, 0x00, /* 0x14088 */
159     0x8c, 0x40, 0x01, 0x00, /* 0x1408c */
160     0x90, 0x40, 0x01, 0x00, /* 0x14090 */
161     0x94, 0x40, 0x01, 0x00, /* 0x14094 */
162     0x98, 0x40, 0x01, 0x00, /* 0x14098 */
163 };
164
165 static inline uint32_t omap3_get_le32(const void *p)
166 {
167     const uint8_t *q = (const uint8_t *)p;
168     uint32_t v;
169     v = q[3]; v <<= 8;
170     v |= q[2]; v <<= 8;
171     v |= q[1]; v <<= 8;
172     v |= q[0];
173     return v;
174 }
175
176 static inline uint32_t omap3_get_le16(const void *p)
177 {
178     const uint8_t *q = (const uint8_t *)p;
179     uint32_t v;
180     v = q[1]; v <<= 8;
181     v |= q[0];
182     return v;
183 }
184
185 static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
186 {
187     uint8_t x[4];
188     
189     cpu_physical_memory_read(addr, x, 4);
190     x[0] = lsb & 0xff;
191     x[1] = (lsb >> 8) & 0xff;
192     cpu_physical_memory_write(addr, x, 4);
193 }
194
195 typedef enum {
196     xip = 1,
197     nand,
198     onenand,
199     doc,
200     mmc2,
201     mmc1,
202     xipwait,
203     uart = 0x10,
204     hsusb,
205 }  omap3_boot_device_t;
206
207 struct omap3_boot_s {
208     struct omap_mpu_state_s *mpu;
209     omap3_boot_device_t devicetype;
210     enum {
211         undefined = 0,
212         confighdr,
213         chdone,
214         imagehdr,
215         copy,
216         done
217     } state;
218     uint8_t chflags;
219     target_phys_addr_t addr;
220     uint32_t count;
221 };
222
223 static struct omap3_boot_s *omap3_boot_init(struct omap_mpu_state_s *mpu,
224                                             omap3_boot_device_t dtype,
225                                             const uint8_t *data,
226                                             uint32_t data_len)
227 {
228     struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
229     s->mpu = mpu;
230     s->devicetype = dtype;
231     s->state = chdone;
232     if (data_len >= 512) {
233         if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
234             || !strncasecmp((char *)(data + 0x14), "chram", 5)
235             || !strncasecmp((char *)(data + 0x14), "chflash", 7)
236             || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
237             s->state = confighdr;
238     }
239     return s;
240 }
241
242 static void omap3_boot_chsettings(struct omap3_boot_s *boot,
243                                   const uint8_t *chtoc)
244 {
245     uint32_t flags, x;
246     
247     if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
248         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
249         return;
250     }
251     if (!chtoc[4]) { /* section disabled? */
252         return;
253     }
254     if (omap3_get_le16(chtoc + 5) != 0x0001) {
255         fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
256                 omap3_get_le16(chtoc));
257         return;
258     }
259     boot->chflags |= 0x01;
260     flags = omap3_get_le32(chtoc + 8);
261     chtoc += 12;
262     if (flags & 1) {
263         cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
264         cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
265         cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
266         if (flags & (1 << 2)) { /* clock configuration */
267             cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
268             cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
269         }
270         if (flags & (1 << 5)) { /* DPLL3 CORE */
271             if (flags & (1 << 8)) { /* enable DPLL3 bypass */
272                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
273                 x &= ~7; x |= 5; /* set DPLL3 bypass */
274                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
275             }
276             cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
277             cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
278             cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
279         }
280         if (flags & (1 << 3)) { /* DPLL4 PER */
281             if (flags & (1 << 6)) { /* enable DPLL4 bypass */
282                 cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
283                 x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
284                 cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
285             }
286             cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
287             cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
288             cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
289             cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
290         }
291         if (flags & (1 << 3)) { /* DPLL1 MPU */
292             if (flags & (1 << 7)) { /* enable DPLL1 bypass */
293                 cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
294                 x &= ~7; x |= 5; /* set DPLL1 bypass */
295                 cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
296             }
297             cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
298             cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
299             cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
300             cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
301             cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
302         }
303         switch ((flags >> 24) & 0xff) {
304             case 0x01: x = 0; break; /* 12MHz */
305             case 0x02: x = 1; break; /* 13MHz */
306             case 0x03: x = 5; break; /* 16.8MHz */
307             case 0x04: x = 2; break; /* 19.2MHz */
308             case 0x05: x = 3; break; /* 26MHz */
309             case 0x06: x = 4; break; /* 38.4MHz */
310             default:
311                 fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
312                 x = 1;
313                 break;
314         }
315         if (x != omap3_get_le32(chtoc + 0x04)) {
316             fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
317         }
318     }
319 }
320
321 static void omap3_boot_chram(struct omap3_boot_s *boot,
322                              const uint8_t *chtoc)
323 {
324     if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
325         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
326         return;
327     }
328     if (!chtoc[4]) { /* section disabled? */
329         return;
330     }
331     boot->chflags |= 0x02;
332     omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
333     omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
334     cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4);      /* SDRC_DLLA_CTRL */
335     
336     cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4);      /* SDRC_MCFG_0 */
337     omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
338     omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
339     omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
340     omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
341     cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_0 */
342     cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_0 */
343     cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_0 */
344     
345     cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4);      /* SDRC_MCFG_1 */
346     omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
347     omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
348     omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
349     omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
350     cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4);      /* SDRC_ACTIM_CTRLA_1 */
351     cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4);      /* SDRC_ACTIM_CTRLB_1 */
352     cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4);      /* SDRC_RFR_CTRL_1 */
353 }
354
355 static void omap3_boot_chflash(struct omap3_boot_s *boot,
356                                const uint8_t *chtoc)
357 {
358     if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
359         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
360         return;
361     }
362     if (!chtoc[4]) { /* section disabled? */
363         return;
364     }
365     boot->chflags |= 0x04;
366     omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
367     omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
368     omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
369     omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
370     cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4);      /* GPMC_CONFIG1_0 */
371     cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4);      /* GPMC_CONFIG2_0 */
372     cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4);      /* GPMC_CONFIG3_0 */
373     cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4);      /* GPMC_CONFIG4_0 */
374     cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4);      /* GPMC_CONFIG5_0 */
375     cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4);      /* GPMC_CONFIG6_0 */
376     cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4);      /* GPMC_CONFIG7_0 */
377     cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4);      /* GPMC_PREFETCH_CONFIG1 */
378     omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
379     omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
380     /* TODO: ECC config registers. The TRM spec is not clear on these */
381 }
382
383 static void omap3_boot_chmmcsd(struct omap3_boot_s *boot,
384                                const uint8_t *chtoc)
385 {
386     if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
387         fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
388         return;
389     }
390     if (!chtoc[4]) { /* section disabled? */
391         return;
392     }
393     boot->chflags |= 0x08;
394     /* TODO: MMCHS registers */
395 }
396
397 /* returns non-zero if more blocks are needed */
398 static uint32_t omap3_boot_block(const uint8_t *data,
399                                  uint32_t data_len,
400                                  struct omap3_boot_s *s)
401 {
402     const uint8_t *p = 0;
403     uint32_t i = 0;
404     
405     switch (s->state) {
406         case confighdr:
407             i = data_len;
408             for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
409                 if (!strcasecmp((char *)(p + 0x14), "chsettings"))
410                     omap3_boot_chsettings(s, p + omap3_get_le32(p));
411                 else if (!strcasecmp((char *)(p + 0x14), "chram"))
412                     omap3_boot_chram(s, p + omap3_get_le32(p));
413                 else if (!strcasecmp((char *)(p + 0x14), "chflash"))
414                     omap3_boot_chflash(s, p + omap3_get_le32(p));
415                 else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
416                     omap3_boot_chmmcsd(s, p + omap3_get_le32(p));
417                 else
418                     fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
419                             __FUNCTION__, (char *)(p + 0x14));
420             }
421             data += 512;
422             data_len -= 512;
423             s->state = chdone;
424             /* fallthrough */
425         case chdone:
426             s->state = imagehdr;
427             /* fallthrough */
428         case imagehdr:
429             if (!data_len)
430                 return 1;
431             if (data_len < 8)
432                 break;
433             s->count = omap3_get_le32(data);
434             s->addr = omap3_get_le32(data + 4);
435             if (!s->count || (s->count >> 24) || !s->addr || s->addr == 0xffffffff)
436                 break;
437             /* patch image start address in boot ROM */
438             cpu_physical_memory_write_rom(0x40014040, data + 4, 4);
439             /* start copying image */
440             data += 8;
441             data_len -= 8;
442             s->state = copy;
443             /* fallthrough */
444         case copy:
445             i = (s->count >= data_len) ? data_len : s->count;
446             cpu_physical_memory_write(s->addr, data, i);
447             s->addr += i;
448             s->count -= i;
449             if (!s->count)
450                 s->state = done;
451             return s->count;
452         default:
453             break;
454     }
455     return 0;
456 }
457
458 /* returns non-zero if boot has finished succesfully */
459 static int omap3_boot_finish(struct omap3_boot_s *s)
460 {
461     uint8_t x[12] = {
462         0, 0, 0, 0, /* last received booting message */
463         (uint8_t)s->devicetype,
464         0,
465         1, /* POR */
466         s->chflags,
467         0, 0, 0, 0 /* device descriptor */
468     };
469     int result = (s->state == done);
470
471     if (result) {
472         /* fill in the booting parameter structure */
473         cpu_physical_memory_write_rom(0x40014044, x, 12);
474     }
475     free(s);
476     return result;
477 }
478
479 /* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
480 static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
481 {
482     int i;
483     
484     /* there are 0x10 items with 0x20 bytes per item */
485     for (i = 0x10; i--; s += 0x20) {
486         if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
487         if (!*s || !strncasecmp((void *)s, "mlo        ", 8+3)) return s;
488     }
489     return 0;
490 }
491
492 struct omap3_fat_drv_s {
493     BlockDriverState *bs;
494     uint8_t ptype; /* 12, 16, 32 */
495     uint64_t c0;   /* physical byte offset for data cluster 0 */
496     uint64_t fat;  /* physical byte offset for used FAT sector 0 */
497     uint32_t spc;  /* sectors per cluster */
498 };
499
500 /* returns cluster data in the buffer and next cluster chain number
501  or 0 if unsuccessful */
502 static uint32_t omap3_read_fat_cluster(uint8_t *data,
503                                        struct omap3_fat_drv_s *drv,
504                                        uint32_t cl)
505 {
506     uint8_t buf[ 4 ];
507     uint32_t len = drv->spc * 0x200; /* number of bytes to read */
508     
509     switch (drv->ptype) { /* check for EOF */
510         case 12: if (cl > 0xff0) return 0; break;
511         case 16: if (cl > 0xfff0) return 0; break;
512         case 32: if (cl > 0x0ffffff0) return 0; break;
513         default: return 0;
514     }
515     
516     if (bdrv_pread(drv->bs, 
517                    drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
518                    data, len) != len)
519         return 0;
520     
521     switch (drv->ptype) { /* determine next cluster # */
522         case 12:
523             fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
524                     __FUNCTION__);
525             break;
526         case 16:
527             return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
528             ? 0 : omap3_get_le16(buf);
529         case 32:
530             return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
531             ? 0 : omap3_get_le32(buf) & 0x0fffffff;
532         default:
533             break;
534     }
535     return 0;
536 }
537
538 static int omap3_mmc_fat_boot(BlockDriverState *bs,
539                               uint8_t *sector,
540                               uint32_t pstart,
541                               struct omap_mpu_state_s *mpu)
542 {
543     struct omap3_fat_drv_s drv;
544     struct omap3_boot_s *boot;
545     uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
546     const uint8_t *p, *q;
547     uint8_t *cluster;
548     int result = 0;
549     
550     /* determine FAT type */
551     
552     drv.bs = bs;
553     fatsize = omap3_get_le16(sector + 0x16);
554     if (!fatsize) 
555         fatsize = omap3_get_le32(sector + 0x24);
556     bootsize = omap3_get_le16(sector + 0x0e);
557     cluster0 = bootsize + fatsize * sector[0x10];
558     rootsize = omap3_get_le16(sector + 0x11);
559     if (rootsize & 0x0f)
560         rootsize += 0x10;
561     rootsize >>= 4;
562     drv.spc = sector[0x0d];
563     i = omap3_get_le16(sector + 0x13);
564     if (!i)
565         i = omap3_get_le32(sector + 0x20);
566     i = (i - (cluster0 + rootsize)) / drv.spc;
567     drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
568     
569     /* search for boot loader file */
570     
571     drv.fat = (bootsize + pstart) * 0x200;
572     drv.c0 = (cluster0 + pstart) * 0x200;
573     if (drv.ptype == 32) {
574         i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
575         j = omap3_get_le16(sector + 0x28);
576         if (j & 0x80)
577             drv.fat += (j & 0x0f) * fatsize * 0x200;
578         cluster = qemu_mallocz(drv.spc * 0x200);
579         for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
580             for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
581                 p = omap3_scan_fat_dir_sector(q);
582             if (p) 
583                 memcpy(sector, q - 0x200, 0x200); /* save the sector */
584         }
585         free(cluster);
586     } else { /* FAT12/16 */
587         for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
588             if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
589                 break;
590             p = omap3_scan_fat_dir_sector(sector);
591         }
592     }
593     
594     if (p && *p) { /* did we indeed find the file? */
595         i = omap3_get_le16(p + 0x14);
596         i <<= 16;
597         i |= omap3_get_le16(p + 0x1a);
598         j = drv.spc * 0x200;
599         uint8 *data = qemu_mallocz(j);
600         if ((i = omap3_read_fat_cluster(data, &drv, i))) {
601             boot = omap3_boot_init(mpu, mmc1, data, j);
602             boot->state = imagehdr; /* override CH detection */
603             while (omap3_boot_block(data, j, boot))
604                 i = omap3_read_fat_cluster(data, &drv, i);
605             result = omap3_boot_finish(boot);
606         } else
607             fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
608                     __FUNCTION__);
609         free(data);
610     } else
611         fprintf(stderr, "%s: MLO file not found in the root directory\n",
612                 __FUNCTION__);
613     
614     return result;
615 }
616
617 static int omap3_mmc_raw_boot(BlockDriverState *bs,
618                               uint8_t *sector,
619                               struct omap_mpu_state_s *mpu)
620 {
621     struct omap3_boot_s *boot;
622     uint32_t i = 0;
623     int result = 0;
624     
625     if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
626         boot = omap3_boot_init(mpu, mmc1, sector, 0x200);
627         if (boot->state == confighdr) { /* CH must be present for raw boot */
628             while (omap3_boot_block(sector, 0x200, boot)) {
629                 if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
630                     fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
631                             __FUNCTION__, i);
632                     break;
633                 }
634             }
635         }
636         result = (boot->state == done);
637         free(boot);
638     }
639     return result;
640 }
641
642 /* returns non-zero if successful, zero if unsuccessful */
643 static int omap3_mmc_boot(struct omap_mpu_state_s *s)
644 {
645     BlockDriverState *bs;
646     int sdindex = drive_get_index(IF_SD, 0, 0);
647     uint8_t *sector, *p;
648     uint32_t pstart, i;
649     int result = 0;
650     
651     /* very simple implementation for GP device boot,
652      supports only two modes:
653      1. MBR partition table with an active FAT partition
654      and boot loader file (MLO) in its root directory, or
655      2. CH sector located on first sector, followed by boot loader image */
656     if (sdindex >= 0) {
657         bs = drives_table[sdindex].bdrv;
658         sector = qemu_mallocz(0x200);
659         if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
660             for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10) 
661                 if (p[0] == 0x80) break;
662             if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
663                 && i < 4 /* active partition exists */
664                 && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
665                     || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
666                 && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
667                               sector, 0x200) == 0x200
668                 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
669                 result = omap3_mmc_fat_boot(bs, sector, pstart, s);
670             else
671                 result = omap3_mmc_raw_boot(bs, sector, s);
672         }
673         free(sector);
674     }
675     return result;
676 }
677
678 static inline void omap3_nand_sendcmd(struct omap3_nand_boot_desc_s *nd,
679                                       uint8_t cmd)
680 {
681     uint8_t x[2] = { cmd, 0 };
682     
683     cpu_physical_memory_write(0x6e00007c, x, nd->bus16 ? 2 : 1);
684 }
685
686 static inline void omap3_nand_sendaddr_byte(struct omap3_nand_boot_desc_s *nd,
687                                             uint8_t a)
688 {
689     uint8_t x[2] = { a, 0 };
690     
691     cpu_physical_memory_write(0x6e000080, x, nd->bus16 ? 2 : 1);
692 }
693
694 static inline uint8_t omap3_nand_readbyte(struct omap3_nand_boot_desc_s *nd)
695 {
696     uint8_t x[2];
697     
698     cpu_physical_memory_read(0x6e000084, x, nd->bus16 ? 2 : 1);
699     return x[0];
700 }
701
702 static inline void omap3_nand_readpage(struct omap3_nand_boot_desc_s *nd,
703                                        uint32_t pageaddr,
704                                        uint8_t *data)
705 {
706     uint32_t i;
707     
708     omap3_nand_sendcmd(nd, 0x00); /* read page */
709     omap3_nand_sendaddr_byte(nd, 0x00);
710     if (nd->pagesize >= 2048) {
711         omap3_nand_sendaddr_byte(nd, 0x00);
712         omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
713         omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
714         if (nd->capacity_Mb >= 2048)
715             omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 16) & 0xff));
716         omap3_nand_sendcmd(nd, 0x30); /* confirm read */
717     } else {
718         omap3_nand_sendaddr_byte(nd, (uint8_t)(pageaddr & 0xff));
719         omap3_nand_sendaddr_byte(nd, (uint8_t)((pageaddr >> 8) & 0xff));
720     }
721     if (nd->bus16) {
722         for (i = nd->pagesize / 2; i--; data += 2)
723             cpu_physical_memory_read(0x6e000084, data, 2);
724     } else {
725         for (i = nd->pagesize; i--; data++)
726             cpu_physical_memory_read(0x6e000084, data, 1);
727     }
728 }
729
730 /* returns non-zero if successful, zero if unsuccessful */
731 static int omap3_nand_boot(struct omap_mpu_state_s *mpu, int bus16)
732 {
733     struct omap3_nand_boot_desc_s *nd;
734     struct omap3_boot_s *boot;
735     uint8_t *data;
736     uint32_t page = 0;
737     int result = 0, i;
738     uint8_t id[4];
739     
740     /* TODO: support bad block marks */
741     nd = qemu_mallocz(sizeof(struct omap3_nand_boot_desc_s));
742     nd->bus16 = bus16;
743     omap3_nand_sendcmd(nd, 0xff); /* reset */
744     omap3_nand_sendcmd(nd, 0x90); /* read id */
745     omap3_nand_sendaddr_byte(nd, 0);
746     id[0] = omap3_nand_readbyte(nd); /* manufacturer id */
747     id[1] = omap3_nand_readbyte(nd); /* device id */
748     id[2] = omap3_nand_readbyte(nd); /* don't care */
749     id[3] = omap3_nand_readbyte(nd); /* attributes */
750     for (i = 0; omap3_boot_nand_devices[i].id; i++) {
751         if (omap3_boot_nand_devices[i].id == id[1]) {
752             nd->capacity_Mb = omap3_boot_nand_devices[i].capacity_Mb;
753             if (nd->capacity_Mb > 1024)
754                 nd->pagesize = 1024 * (1 << (id[3] & 3));
755             else
756                 nd->pagesize = omap3_boot_nand_devices[i].pagesize;
757             break;
758         }
759     }
760     /* TODO: if device is not recognized at this state, we should
761      * issue READ ID2 command to the device and get device parameters
762      * from there */
763     if (nd->pagesize) {
764         data = qemu_mallocz(nd->pagesize);
765         /* TODO: scan through 4 first blocks for image */
766         omap3_nand_readpage(nd, 0, data);
767         boot = omap3_boot_init(mpu, nand, data, nd->pagesize);
768         while (omap3_boot_block(data, nd->pagesize, boot))
769             omap3_nand_readpage(nd, ++page, data);
770         result = omap3_boot_finish(boot);
771         free(data);
772     }
773     free(nd);
774     return result;
775 }
776
777
778 void omap3_boot_rom_emu(struct omap_mpu_state_s *s)
779 {
780     const uint8_t rom_version[4] = { 0x00, 0x14, 0x00, 0x00 }; /* v. 14.00 */
781     uint8_t x[4] = {0, 0, 0, 0};
782     int result = 0;
783     
784     cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x14000,
785                                   omap3_boot_rom,
786                                   sizeof(omap3_boot_rom));
787     cpu_physical_memory_write_rom(OMAP3_Q1_BASE + 0x1bffc,
788                                   rom_version,
789                                   sizeof(rom_version));
790     cpu_physical_memory_write(OMAP3_SRAM_BASE + 0xffc8,
791                               omap3_sram_vectors,
792                               sizeof(omap3_sram_vectors));
793
794     /* if we have NAND in GPMC CS0, try to read boot loader from there.
795      * here we are relying on all memories to be attached and gpmc_attach
796      * to fill in DEVICETYPE field correctly for CS0 for us */
797     cpu_physical_memory_read(0x6e000060, x, 4); /* GPMC_CONFIG1_0 */
798     if (((x[1] >> 2) & 3) == 2) /* DEVICETYPE == NAND? */
799         result = omap3_nand_boot(s, ((x[1] >> 4) & 3) == 1);
800
801     /* TODO: support OneNAND and XIP */
802     
803     /* if no boot loader found yet, try the MMC/SD card... */
804     if (!result)
805         result = omap3_mmc_boot(s);
806     
807     if (!result) { /* no boot device found */
808         /* move PC to the appropriate ROM dead loop address */
809         s->env->regs[15] = 0x400140a4;
810         /* ...on second thought, let's just call it a day and quit */
811         cpu_abort(s->env, "no boot device found");
812     }
813 }