s->general[0x01] = 0x4000000; /* CONTROL_DEVCONF_0 */
s->general[0x1c] = 0x1; /* 0x480022e0?? */
s->general[0x20] = 0x30f; /* CONTROL_STATUS:
- * - device type = GP Device
- * - sys_boot = NAND, USB, UART3, MMC1 */
+ * - device type = GP Device
+ * - sys_boot:6 = oscillator bypass mode
+ * - sys_boot:0-5 = NAND, USB, UART3, MMC1*/
s->general[0x75] = 0x7fc0; /* CONTROL_PROG_IO0 */
s->general[0x76] = 0xaa; /* CONTROL_PROG_IO1 */
s->general[0x7c] = 0x2700; /* CONTROL_SDRC_SHARING */
return s;
}
-#define OMAP3_BOOT_ROM_SIZE 0x1c000 /* 80 + 32 KB */
-static const uint8_t omap3_boot_rom[] = {
- 0x0e, 0xf0, 0xb0, 0xe1, /* movs pc, lr */
- 0x0e, 0xf0, 0xb0, 0xe1, /* movs pc, lr */
- 0x0e, 0xf0, 0xb0, 0xe1, /* movs pc, lr */
- 0x04, 0xf0, 0x5e, 0xe2, /* subs pc, lr, #4 */
- 0x08, 0xf0, 0x5e, 0xe2, /* subs pc, lr, #8 */
- 0x0e, 0xf0, 0xb0, 0xe1, /* movs pc, lr */
- 0x04, 0xf0, 0x5e, 0xe2, /* subs pc, lr, #4 */
- 0x04, 0xf0, 0x5e, 0xe2, /* subs pc, lr, #4 */
-};
+#define OMAP3_BOOT_ROM_SIZE 0x1c000 /* 80 + 32 kB */
static const struct dma_irq_map omap3_dma_irq_map[] = {
{0, OMAP_INT_3XXX_SDMA_IRQ0},
bootrom_base | IO_MEM_ROM);
cpu_register_physical_memory(0, OMAP3_BOOT_ROM_SIZE,
bootrom_base | IO_MEM_ROM);
- cpu_physical_memory_write_rom(OMAP3_Q1_BASE, omap3_boot_rom,
- sizeof(omap3_boot_rom));
s->l4 = omap_l4_init(OMAP3_L4_BASE,
sizeof(omap3_l4_agent_info)
s->irq[0][OMAP_INT_3XXX_TLL_IRQ]);
return s;
}
-
-
-static inline uint32_t omap3_get_le32(const void *p)
-{
- const uint8_t *q = (const uint8_t *)p;
- uint32_t v;
- v = q[3]; v <<= 8;
- v |= q[2]; v <<= 8;
- v |= q[1]; v <<= 8;
- v |= q[0];
- return v;
-}
-
-static inline uint32_t omap3_get_le16(const void *p)
-{
- const uint8_t *q = (const uint8_t *)p;
- uint32_t v;
- v = q[1]; v <<= 8;
- v |= q[0];
- return v;
-}
-
-static inline void omap3_boot_setlsb(target_phys_addr_t addr, uint16_t lsb)
-{
- uint8_t x[4];
-
- cpu_physical_memory_read(addr, x, 4);
- x[0] = lsb & 0xff;
- x[1] = (lsb >> 8) & 0xff;
- cpu_physical_memory_write(addr, x, 4);
-}
-
-struct omap3_boot_s {
- struct omap_mpu_state_s *mpu;
- enum {
- undefined = 0,
- confighdr,
- chdone,
- imagehdr,
- copy,
- done
- } state;
- target_phys_addr_t addr;
- uint32_t count;
-};
-
-static struct omap3_boot_s *omap3_boot_init(const uint8_t *data,
- uint32_t data_len,
- struct omap_mpu_state_s *mpu)
-{
- struct omap3_boot_s *s = qemu_mallocz(sizeof(struct omap3_boot_s));
- s->mpu = mpu;
- s->state = imagehdr;
- if (data_len >= 512) {
- if (!strncasecmp((char *)(data + 0x14), "chsettings", 10)
- || !strncasecmp((char *)(data + 0x14), "chram", 5)
- || !strncasecmp((char *)(data + 0x14), "chflash", 7)
- || !strncasecmp((char *)(data + 0x14), "chmmcsd", 7))
- s->state = confighdr;
- }
- return s;
-}
-
-static void omap3_boot_chsettings(const uint8_t *chtoc)
-{
- uint32_t flags, x;
-
- if (omap3_get_le32(chtoc) != 0xc0c0c0c1) {
- fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
- return;
- }
- if (!chtoc[4]) { /* section disabled? */
- return;
- }
- if (omap3_get_le16(chtoc + 5) != 0x0001) {
- fprintf(stderr, "%s: unsupported CH version (0x%04x)\n", __FUNCTION__,
- omap3_get_le16(chtoc));
- return;
- }
- flags = omap3_get_le32(chtoc + 8);
- chtoc += 12;
- if (flags & 1) {
- cpu_physical_memory_write(0x48307270, chtoc + 0x00, 4); /* PRM_CLKSRC_CTRL */
- cpu_physical_memory_write(0x48306d40, chtoc + 0x04, 4); /* PRM_CLKSEL */
- cpu_physical_memory_write(0x48005140, chtoc + 0x08, 4); /* CM_CLKSEL1_EMU */
- if (flags & (1 << 2)) { /* clock configuration */
- cpu_physical_memory_write(0x48004a40, chtoc + 0x0c, 4); /* CM_CLKSEL_CORE */
- cpu_physical_memory_write(0x48004c40, chtoc + 0x10, 4); /* CM_CLKSEL_WKUP */
- }
- if (flags & (1 << 5)) { /* DPLL3 CORE */
- if (flags & (1 << 8)) { /* enable DPLL3 bypass */
- cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
- x &= ~7; x |= 5; /* set DPLL3 bypass */
- cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
- }
- cpu_physical_memory_write(0x48004d00, chtoc + 0x14, 4); /* CM_CLKEN_PLL */
- cpu_physical_memory_write(0x48004d30, chtoc + 0x18, 4); /* CM_AUTOIDLE_PLL */
- cpu_physical_memory_write(0x48004d40, chtoc + 0x1c, 4); /* CM_CLKSEL1_PLL */
- }
- if (flags & (1 << 3)) { /* DPLL4 PER */
- if (flags & (1 << 6)) { /* enable DPLL4 bypass */
- cpu_physical_memory_read(0x48004d00, (uint8_t *)&x, 4);
- x &= ~0x70000; x |= 0x10000; /* set DPLL4 in stop mode */
- cpu_physical_memory_write(0x48004d00, (uint8_t *)&x, 4);
- }
- cpu_physical_memory_write(0x48004d00, chtoc + 0x20, 4); /* CM_CLKEN_PLL */
- cpu_physical_memory_write(0x48004d30, chtoc + 0x24, 4); /* CM_AUTOIDLE_PLL */
- cpu_physical_memory_write(0x48004d44, chtoc + 0x28, 4); /* CM_CLKSEL2_PLL */
- cpu_physical_memory_write(0x48004d48, chtoc + 0x2c, 4); /* CM_CLKSEL3_PLL */
- }
- if (flags & (1 << 3)) { /* DPLL1 MPU */
- if (flags & (1 << 7)) { /* enable DPLL1 bypass */
- cpu_physical_memory_read(0x48004904, (uint8_t *)&x, 4);
- x &= ~7; x |= 5; /* set DPLL1 bypass */
- cpu_physical_memory_write(0x48004904, (uint8_t *)&x, 4);
- }
- cpu_physical_memory_write(0x48004904, chtoc + 0x30, 4); /* CM_CLKEN_PLL_MPU */
- cpu_physical_memory_write(0x48004934, chtoc + 0x34, 4); /* CM_AUTOIDLE_PLL_MPU */
- cpu_physical_memory_write(0x48004940, chtoc + 0x38, 4); /* CM_CLKSEL1_PLL_MPU */
- cpu_physical_memory_write(0x48004944, chtoc + 0x3c, 4); /* CM_CLKSEL2_PLL_MPU */
- cpu_physical_memory_write(0x48004948, chtoc + 0x40, 4); /* CM_CLKSTCTRL_MPU */
- }
- switch ((flags >> 24) & 0xff) {
- case 0x01: x = 0; break; /* 12MHz */
- case 0x02: x = 1; break; /* 13MHz */
- case 0x03: x = 5; break; /* 16.8MHz */
- case 0x04: x = 2; break; /* 19.2MHz */
- case 0x05: x = 3; break; /* 26MHz */
- case 0x06: x = 4; break; /* 38.4MHz */
- default:
- fprintf(stderr, "%s: unsupported SYS.CLK setting\n", __FUNCTION__);
- x = 1;
- break;
- }
- if (x != omap3_get_le32(chtoc + 0x04)) {
- fprintf(stderr, "%s: mismatch in SYS.CLK id and PRM_CLKSEL value\n", __FUNCTION__);
- }
- }
-}
-
-static void omap3_boot_chram(const uint8_t *chtoc)
-{
- if (omap3_get_le32(chtoc) != 0xc0c0c0c2) {
- fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
- return;
- }
- if (!chtoc[4]) { /* section disabled? */
- return;
- }
- omap3_boot_setlsb(0x6d000040, omap3_get_le16(chtoc + 0x0a)); /* SDRC_CS_CFG */
- omap3_boot_setlsb(0x6d000044, omap3_get_le16(chtoc + 0x0c)); /* SDRC_SHARING */
- cpu_physical_memory_write(0x6d000060, chtoc + 0x10, 4); /* SDRC_DLLA_CTRL */
-
- cpu_physical_memory_write(0x6d000080, chtoc + 0x20, 4); /* SDRC_MCFG_0 */
- omap3_boot_setlsb(0x6d000084, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_0 */
- omap3_boot_setlsb(0x6d000088, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_0? */
- omap3_boot_setlsb(0x6d00008c, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_0 */
- omap3_boot_setlsb(0x6d000090, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_0? */
- cpu_physical_memory_write(0x6d00009c, chtoc + 0x2c, 4); /* SDRC_ACTIM_CTRLA_0 */
- cpu_physical_memory_write(0x6d0000a0, chtoc + 0x30, 4); /* SDRC_ACTIM_CTRLB_0 */
- cpu_physical_memory_write(0x6d0000a4, chtoc + 0x34, 4); /* SDRC_RFR_CTRL_0 */
-
- cpu_physical_memory_write(0x6d0000b0, chtoc + 0x20, 4); /* SDRC_MCFG_1 */
- omap3_boot_setlsb(0x6d0000b4, omap3_get_le16(chtoc + 0x24)); /* SDRC_MR_1 */
- omap3_boot_setlsb(0x6d0000b8, omap3_get_le16(chtoc + 0x26)); /* SDRC_EMR1_1? */
- omap3_boot_setlsb(0x6d0000bc, omap3_get_le16(chtoc + 0x28)); /* SDRC_EMR2_1 */
- omap3_boot_setlsb(0x6d0000c0, omap3_get_le16(chtoc + 0x2a)); /* SDRC_EMR3_1? */
- cpu_physical_memory_write(0x6d0000cc, chtoc + 0x2c, 4); /* SDRC_ACTIM_CTRLA_1 */
- cpu_physical_memory_write(0x6d0000d0, chtoc + 0x30, 4); /* SDRC_ACTIM_CTRLB_1 */
- cpu_physical_memory_write(0x6d0000d4, chtoc + 0x34, 4); /* SDRC_RFR_CTRL_1 */
-}
-
-static void omap3_boot_chflash(const uint8_t *chtoc)
-{
- if (omap3_get_le32(chtoc) != 0xc0c0c0c3) {
- fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
- return;
- }
- if (!chtoc[4]) { /* section disabled? */
- return;
- }
- omap3_boot_setlsb(0x6e000010, omap3_get_le16(chtoc + 0x08)); /* GPMC_SYSCONFIG */
- omap3_boot_setlsb(0x6e00001c, omap3_get_le16(chtoc + 0x0a)); /* GPMC_IRQENABLE */
- omap3_boot_setlsb(0x6e000040, omap3_get_le16(chtoc + 0x0c)); /* GPMC_TIMEOUT_CONTROL */
- omap3_boot_setlsb(0x6e000050, omap3_get_le16(chtoc + 0x0e)); /* GPMC_CONFIG */
- cpu_physical_memory_write(0x6e000060, chtoc + 0x10, 4); /* GPMC_CONFIG1_0 */
- cpu_physical_memory_write(0x6e000064, chtoc + 0x14, 4); /* GPMC_CONFIG2_0 */
- cpu_physical_memory_write(0x6e000068, chtoc + 0x18, 4); /* GPMC_CONFIG3_0 */
- cpu_physical_memory_write(0x6e00006c, chtoc + 0x1c, 4); /* GPMC_CONFIG4_0 */
- cpu_physical_memory_write(0x6e000070, chtoc + 0x20, 4); /* GPMC_CONFIG5_0 */
- cpu_physical_memory_write(0x6e000074, chtoc + 0x24, 4); /* GPMC_CONFIG6_0 */
- cpu_physical_memory_write(0x6e000078, chtoc + 0x28, 4); /* GPMC_CONFIG7_0 */
- cpu_physical_memory_write(0x6e0001e0, chtoc + 0x2c, 4); /* GPMC_PREFETCH_CONFIG1 */
- omap3_boot_setlsb(0x6e0001e4, omap3_get_le16(chtoc + 0x30)); /* GPMC_PREFETCH_CONFIG2 */
- omap3_boot_setlsb(0x6e0001ec, omap3_get_le16(chtoc + 0x32)); /* GPMC_PREFETCH_CONTROL */
- /* TODO: ECC config registers. The TRM spec is not clear on these */
-}
-
-static void omap3_boot_chmmcsd(const uint8_t *chtoc)
-{
- if (omap3_get_le32(chtoc) != 0xc0c0c0c4) {
- fprintf(stderr, "%s: invalid section verification key\n", __FUNCTION__);
- return;
- }
- if (!chtoc[4]) { /* section disabled? */
- return;
- }
- /* TODO: MMCHS registers */
-}
-
-/* returns non-zero if more blocks are needed */
-static uint32_t omap3_boot_block(const uint8_t *data,
- uint32_t data_len,
- struct omap3_boot_s *s)
-{
- const uint8_t *p = 0;
- uint32_t i = 0;
-
- switch (s->state) {
- case confighdr:
- i = data_len;
- for (p = data; i >= 32 && omap3_get_le32(p) != 0xffffffff; p += 32, i -= 32) {
- if (!strcasecmp((char *)(p + 0x14), "chsettings"))
- omap3_boot_chsettings(p + omap3_get_le32(p));
- else if (!strcasecmp((char *)(p + 0x14), "chram"))
- omap3_boot_chram(p + omap3_get_le32(p));
- else if (!strcasecmp((char *)(p + 0x14), "chflash"))
- omap3_boot_chflash(p + omap3_get_le32(p));
- else if (!strcasecmp((char *)(p + 0x14), "chmmcsd"))
- omap3_boot_chmmcsd(p + omap3_get_le32(p));
- else
- fprintf(stderr, "%s: unknown CHTOC item \"%s\"\n",
- __FUNCTION__, (char *)(p + 0x14));
- }
- data += 512;
- data_len -= 512;
- s->state = chdone;
- /* fallthrough */
- case chdone:
- s->state = imagehdr;
- /* fallthrough */
- case imagehdr:
- if (!data_len)
- return 1;
- if (data_len < 8)
- break;
- s->count = omap3_get_le32(data);
- s->addr = omap3_get_le32(data + 4);
- if (!s->count || !s->addr || s->addr == 0xffffffff)
- break;
- s->mpu->env->regs[15] = s->addr;
- data += 8;
- data_len -= 8;
- s->state = copy;
- /* fallthrough */
- case copy:
- i = (s->count >= data_len) ? data_len : s->count;
- cpu_physical_memory_write(s->addr, data, i);
- s->addr += i;
- s->count -= i;
- if (!s->count)
- s->state = done;
- return s->count;
- default:
- break;
- }
- return 0;
-}
-
-/* returns ptr to matching dir entry / zero entry or 0 if unsuccessful */
-static const uint8_t *omap3_scan_fat_dir_sector(const uint8_t *s)
-{
- int i;
-
- /* there are 0x10 items with 0x20 bytes per item */
- for (i = 0x10; i--; s += 0x20) {
- if (*s == 0xe5 || (s[0x0b] & 0x0f) == 0x0f) continue; /* erased/LFN */
- if (!*s || !strncasecmp((void *)s, "mlo ", 8+3)) return s;
- }
- return 0;
-}
-
-struct omap3_fat_drv_s {
- BlockDriverState *bs;
- uint8_t ptype; /* 12, 16, 32 */
- uint64_t c0; /* physical byte offset for data cluster 0 */
- uint64_t fat; /* physical byte offset for used FAT sector 0 */
- uint32_t spc; /* sectors per cluster */
-};
-
-/* returns cluster data in the buffer and next cluster chain number
- or 0 if unsuccessful */
-static uint32_t omap3_read_fat_cluster(uint8_t *data,
- struct omap3_fat_drv_s *drv,
- uint32_t cl)
-{
- uint8_t buf[ 4 ];
- uint32_t len = drv->spc * 0x200; /* number of bytes to read */
-
- switch (drv->ptype) { /* check for EOF */
- case 12: if (cl > 0xff0) return 0; break;
- case 16: if (cl > 0xfff0) return 0; break;
- case 32: if (cl > 0x0ffffff0) return 0; break;
- default: return 0;
- }
-
- if (bdrv_pread(drv->bs,
- drv->c0 + ((drv->ptype == 32 ? cl - 2 : cl) * len),
- data, len) != len)
- return 0;
-
- switch (drv->ptype) { /* determine next cluster # */
- case 12:
- fprintf(stderr, "%s: FAT12 parsing not implemented!\n",
- __FUNCTION__);
- break;
- case 16:
- return (bdrv_pread(drv->bs, drv->fat + cl * 2, buf, 2) != 2)
- ? 0 : omap3_get_le16(buf);
- case 32:
- return (bdrv_pread(drv->bs, drv->fat + cl * 4, buf, 4) != 4)
- ? 0 : omap3_get_le32(buf) & 0x0fffffff;
- default:
- break;
- }
- return 0;
-}
-
-static int omap3_mmc_fat_boot(BlockDriverState *bs,
- uint8_t *sector,
- uint32_t pstart,
- struct omap_mpu_state_s *mpu)
-{
- struct omap3_fat_drv_s drv;
- struct omap3_boot_s *boot;
- uint32_t i, j, cluster0, fatsize, bootsize, rootsize;
- const uint8_t *p, *q;
- uint8_t *cluster;
- int result = 0;
-
- /* determine FAT type */
-
- drv.bs = bs;
- fatsize = omap3_get_le16(sector + 0x16);
- if (!fatsize)
- fatsize = omap3_get_le32(sector + 0x24);
- bootsize = omap3_get_le16(sector + 0x0e);
- cluster0 = bootsize + fatsize * sector[0x10];
- rootsize = omap3_get_le16(sector + 0x11);
- if (rootsize & 0x0f)
- rootsize += 0x10;
- rootsize >>= 4;
- drv.spc = sector[0x0d];
- i = omap3_get_le16(sector + 0x13);
- if (!i)
- i = omap3_get_le32(sector + 0x20);
- i = (i - (cluster0 + rootsize)) / drv.spc;
- drv.ptype = (i < 4085) ? 12 : (i < 65525) ? 16 : 32;
-
- /* search for boot loader file */
-
- drv.fat = (bootsize + pstart) * 0x200;
- drv.c0 = (cluster0 + pstart) * 0x200;
- if (drv.ptype == 32) {
- i = omap3_get_le32(sector + 0x2c); /* first root cluster # */
- j = omap3_get_le16(sector + 0x28);
- if (j & 0x80)
- drv.fat += (j & 0x0f) * fatsize * 0x200;
- cluster = qemu_mallocz(drv.spc * 0x200);
- for (p = 0; !p && (i = omap3_read_fat_cluster(cluster, &drv, i)); ) {
- for (j = drv.spc, q=cluster; j-- & !p; q += 0x200)
- p = omap3_scan_fat_dir_sector(q);
- if (p)
- memcpy(sector, q - 0x200, 0x200); /* save the sector */
- }
- free(cluster);
- } else { /* FAT12/16 */
- for (i = rootsize, j = 0, p = 0; i-- && !p; j++) {
- if (bdrv_pread(drv.bs, drv.c0 + j * 0x200, sector, 0x200) != 0x200)
- break;
- p = omap3_scan_fat_dir_sector(sector);
- }
- }
-
- if (p && *p) { /* did we indeed find the file? */
- i = omap3_get_le16(p + 0x14);
- i <<= 16;
- i |= omap3_get_le16(p + 0x1a);
- j = drv.spc * 0x200;
- uint8 *data = qemu_mallocz(j);
- if ((i = omap3_read_fat_cluster(data, &drv, i))) {
- boot = omap3_boot_init(data, j, mpu);
- boot->state = imagehdr; /* override CH detection */
- while (omap3_boot_block(data, j, boot))
- i = omap3_read_fat_cluster(data, &drv, i);
- result = (boot->state == done);
- free(boot);
- } else
- fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
- __FUNCTION__);
- free(data);
- } else
- fprintf(stderr, "%s: MLO file not found in the root directory\n",
- __FUNCTION__);
-
- return result;
-}
-
-static int omap3_mmc_raw_boot(BlockDriverState *bs,
- uint8_t *sector,
- struct omap_mpu_state_s *mpu)
-{
- struct omap3_boot_s *boot;
- uint32_t i = 0;
- int result = 0;
-
- if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
- boot = omap3_boot_init(sector, 0x200, mpu);
- if (boot->state == confighdr) { /* CH must be present for raw boot */
- while (omap3_boot_block(sector, 0x200, boot)) {
- if (bdrv_pread(bs, ++i, sector, 0x200) != 0x200) {
- fprintf(stderr, "%s: error trying to read sector %u on boot device\n",
- __FUNCTION__, i);
- break;
- }
- }
- }
- result = (boot->state == done);
- free(boot);
- }
- return result;
-}
-
-/* returns non-zero if successful, zero if unsuccessful */
-int omap3_mmc_boot(struct omap_mpu_state_s *s)
-{
- BlockDriverState *bs;
- int sdindex = drive_get_index(IF_SD, 0, 0);
- uint8_t *sector, *p;
- uint32_t pstart, i;
- int result = 0;
-
- /* very simple implementation for GP device boot,
- supports only two modes:
- 1. MBR partition table with an active FAT partition
- and boot loader file (MLO) in its root directory, or
- 2. CH sector located on first sector, followed by boot loader image */
- if (sdindex >= 0) {
- bs = drives_table[sdindex].bdrv;
- sector = qemu_mallocz(0x200);
- if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
- for (i = 0, p = sector + 0x1be; i < 4; i++, p += 0x10)
- if (p[0] == 0x80) break;
- if (sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa /* signature */
- && i < 4 /* active partition exists */
- && (p[4] == 1 || p[4] == 4 || p[4] == 6 || p[4] == 11
- || p[4] == 12 || p[4] == 14 || p[4] == 15) /* FAT */
- && bdrv_pread(bs, (pstart = omap3_get_le32(p + 8)) * 0x200,
- sector, 0x200) == 0x200
- && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa)
- result = omap3_mmc_fat_boot(bs, sector, pstart, s);
- else
- result = omap3_mmc_raw_boot(bs, sector, s);
- }
- free(sector);
- }
- return result;
-}
-
-/* returns non-zero if successful, zero if unsuccessful */
-int omap3_nand_boot(struct omap_mpu_state_s *mpu,
- struct nand_flash_s *nand,
- void (*nand_pread_f)(struct nand_flash_s *nand,
- uint64_t address,
- uint8_t *data,
- uint32_t len))
-{
- struct omap3_boot_s *boot;
- uint8_t *data;
- uint64_t addr = 0;
- int result = 0;
-
- data = qemu_mallocz(0x1000);
- nand_pread_f(nand, 0, data, 0x1000);
- boot = omap3_boot_init(data, 0x1000, mpu);
- while (omap3_boot_block(data, 0x1000, boot)) {
- addr += 0x1000;
- nand_pread_f(nand, addr, data, 0x1000);
- }
- result = (boot->state == done);
- free(boot);
- free(data);
- return result;
-}