From 9bd33c2d5655946d5396c0ab39fb84538d1a4ca5 Mon Sep 17 00:00:00 2001
From: Anton Kochkov <xvilka@gmail.com>
Date: Sat, 19 Feb 2011 09:32:04 +0300
Subject: [PATCH] Initial support for loading bootrom for OMAP3 from file (with "-bios"
 option)


Signed-off-by: Anton Kochkov <xvilka@gmail.com>
---
 hw/beagle.c       |    2 +-
 hw/nseries.c      |    2 +-
 hw/omap.h         |    5 +++-
 hw/omap3.c        |   18 ++++++++++---
 hw/omap3_boot.c   |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/omap_gpmc.c    |    1 +
 hw/omap_gptimer.c |    6 ++++
 7 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/hw/beagle.c b/hw/beagle.c
index e859118..360e93b 100644
--- a/hw/beagle.c
+++ b/hw/beagle.c
@@ -69,7 +69,7 @@ static void beagle_common_init(ram_addr_t ram_size,
 #error MAX_SERIAL_PORTS must be at least 1!
 #endif
     s->cpu = omap3_mpu_init(cpu_model, 1, ram_size,
-                            NULL, NULL, serial_hds[0], NULL);
+                            NULL, NULL, serial_hds[0], NULL, 0);
 
     s->nand = nand_init(NAND_MFR_MICRON, 0xba, dmtd ? dmtd->bdrv : NULL);
     nand_setpins(s->nand, 0, 0, 0, 1, 0); /* no write-protect */
diff --git a/hw/nseries.c b/hw/nseries.c
index 7b6a9db..b84d238 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -2529,7 +2529,7 @@ static void n900_init(ram_addr_t ram_size,
 #endif
     s->cpu = omap3_mpu_init(omap3430, 1, N900_SDRAM_SIZE,
                             serial_hds[1], serial_hds[2],
-                            serial_hds[0], NULL);
+                            serial_hds[0], NULL, 0);
     omap_lcd_panel_attach(s->cpu->dss);
 
     s->tsc2005 = spi_create_device(omap_mcspi_bus(s->cpu->mcspi, 0),
diff --git a/hw/omap.h b/hw/omap.h
index c7ebc8a..ef7a18a 100644
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -1121,6 +1121,7 @@ struct omap_mpu_state_s {
     DeviceState *omap3_usb_otg;
     DeviceState *omap3_usb_host;
     ram_addr_t bootrom_base;
+	int security_mode;
 };
 
 /* omap1.c */
@@ -1137,10 +1138,12 @@ struct omap_mpu_state_s *omap3_mpu_init(int model, int emulate_bootrom,
                                         CharDriverState *chr_uart1,
                                         CharDriverState *chr_uart2,
                                         CharDriverState *chr_uart3,
-                                        CharDriverState *chr_uart4);
+                                        CharDriverState *chr_uart4, int security_mode);
 
 /* omap3_boot.c */
+void omap3_boot_rom_allocate(struct omap_mpu_state_s *s, int high);
 void omap3_boot_rom_init(struct omap_mpu_state_s *s);
+void omap3_boot_rom_run(struct omap_mpu_state_s *s);
 void omap3_boot_rom_emu(struct omap_mpu_state_s *s);
 
 # if TARGET_PHYS_ADDR_BITS == 32
diff --git a/hw/omap3.c b/hw/omap3.c
index df2d45a..5918806 100644
--- a/hw/omap3.c
+++ b/hw/omap3.c
@@ -3387,6 +3387,7 @@ struct omap3_scm_s {
 	uint8 mem_wkup[1024];    /*0x4800 2600*/
 	uint8 padconfs_wkup[96]; /*0x4800 2a00*/
 	uint32 general_wkup[8];  /*0x4800 2a60*/
+	int security_mode;
 };
 
 #define PADCONFS_VALUE(wakeup0,wakeup1,offmode0,offmode1, \
@@ -3548,10 +3549,17 @@ static void omap3_scm_reset(struct omap3_scm_s *s)
     memset(s->general, 0, sizeof(s->general));
 	s->general[0x01] = 0x4000000;  /* CONTROL_DEVCONF_0 */
 	s->general[0x1c] = 0x1;        /* 0x480022e0?? */
+    if (s->security_mode == 0) {
     s->general[0x20] = 0x30f;      /* CONTROL_STATUS:
                                     * - device type  = GP Device
                                     * - sys_boot:6   = oscillator bypass mode
                                     * - sys_boot:0-5 = NAND, USB, UART3, MMC1*/
+	} else {
+		s->general[0x20] = 0xf;      /* CONTROL_STATUS:
+										* - 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 */
@@ -3691,6 +3699,7 @@ static struct omap3_scm_s *omap3_scm_init(struct omap_target_agent_s *ta,
     struct omap3_scm_s *s = (struct omap3_scm_s *) qemu_mallocz(sizeof(*s));
 
     s->mpu = mpu;
+	s->security_mode = mpu->security_mode;
 
     omap3_scm_reset(s);
 
@@ -4049,8 +4058,9 @@ static void omap3_reset(void *opaque)
     omap_synctimer_reset(s->synctimer);
     omap_sdrc_reset(s->sdrc);
     omap_gpmc_reset(s->gpmc);
-
-    omap3_boot_rom_emu(s);
+	omap3_boot_rom_allocate(s, 0);
+	if (bios_name == NULL) omap3_boot_rom_emu(s);
+	else omap3_boot_rom_run(s);
 }
 
 static const struct dma_irq_map omap3_dma_irq_map[] = {
@@ -4071,7 +4081,7 @@ struct omap_mpu_state_s *omap3_mpu_init(int model, int emulate_bootrom,
                                         CharDriverState *chr_uart1,
                                         CharDriverState *chr_uart2,
                                         CharDriverState *chr_uart3,
-                                        CharDriverState *chr_uart4)
+                                        CharDriverState *chr_uart4, int security_mode)
 {
     struct omap_mpu_state_s *s = qemu_mallocz(sizeof(*s));
     ram_addr_t sram_base, q2_base;
@@ -4089,6 +4099,7 @@ struct omap_mpu_state_s *omap3_mpu_init(int model, int emulate_bootrom,
     }
     s->sdram_size = sdram_size;
     s->sram_size = OMAP3XXX_SRAM_SIZE;
+	s->security_mode = security_mode;
 
     /* Clocks */
     omap_clk_init(s);
@@ -4109,7 +4120,6 @@ struct omap_mpu_state_s *omap3_mpu_init(int model, int emulate_bootrom,
                                cpu_irq[ARM_PIC_CPU_FIQ],
                                omap_findclk(s, "omap3_mpu_intc_fclk"),
                                omap_findclk(s, "omap3_mpu_intc_iclk"));
-
     for (i = 0; i < 4; i++) {
         drqs[i] = s->irq[omap3_dma_irq_map[i].ih][omap3_dma_irq_map[i].intr];
     }
diff --git a/hw/omap3_boot.c b/hw/omap3_boot.c
index 655a456..04a35c9 100644
--- a/hw/omap3_boot.c
+++ b/hw/omap3_boot.c
@@ -27,6 +27,7 @@
 #include "arm-misc.h"
 #include "omap.h"
 #include "sysemu.h"
+#include "loader.h"
 #include "qemu-char.h"
 #include "flash.h"
 #include "blockdev.h"
@@ -40,6 +41,8 @@
 #define TRACE(...)
 #endif
 
+#define BOOTROM_FILENAME "bootrom.bin"
+
 /* list of supported NAND devices according to the OMAP34xx TRM */
 static const struct {
     uint8_t id;
@@ -871,11 +874,62 @@ static int omap3_onenand_boot(struct omap_mpu_state_s *s)
     return result;
 }
 
+void omap3_boot_rom_allocate(struct omap_mpu_state_s *s, int high)
+{
+	char* filename;
+	const char* bootrom_name;
+	uint8_t *boot_rom = NULL;
+
+	int bootrom_size, ret;
+	
+	bootrom_name = bios_name;
+	if (bootrom_name == NULL) bootrom_name = BOOTROM_FILENAME;
+	
+	filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bootrom_name);
+	if (filename) {
+		bootrom_size = get_image_size(filename);
+	} else {
+		bootrom_size = -1;
+	}
+	if (bootrom_size <= 0 || (bootrom_size % 32768) != 0) {
+		fprintf(stderr, "qemu: could not load ARM Boot ROM '%s'\n", bootrom_name);
+	exit(1);
+	}
+	
+	if (high == 1) {
+		s->bootrom_base = qemu_ram_alloc(NULL, "omap3_boot_rom", bootrom_size);
+		ret = rom_add_file_fixed(bootrom_name, OMAP3_Q1_BASE + 0x14000, -1);
+		if (ret != 0) {
+			fprintf(stderr, "qemu: could not load ARM Boot ROM '%s'\n", bootrom_name);
+			exit(1);
+		}
+		cpu_register_physical_memory(OMAP3_Q1_BASE + 0x14000,
+													bootrom_size,
+													s->bootrom_base | IO_MEM_ROM);
+	} else {
+		boot_rom = qemu_mallocz(bootrom_size);
+		rom_copy(boot_rom, OMAP3_Q1_BASE + 0x14000, bootrom_size);
+		s->bootrom_base = qemu_ram_alloc(NULL, "omap3_low_rom", bootrom_size);
+		cpu_register_physical_memory(OMAP_CS0_BASE + 0x14000, bootrom_size, s->bootrom_base | IO_MEM_ROM);
+		cpu_physical_memory_write_rom(OMAP_CS0_BASE + 0x14000, boot_rom, bootrom_size);
+		cpu_physical_memory_read(OMAP_CS0_BASE + 0x14000, boot_rom, bootrom_size);
+		free(boot_rom);
+	}
+	cpu_physical_memory_write(OMAP3_SRAM_BASE + 0xffc8,
+												omap3_sram_vectors,
+												sizeof(omap3_sram_vectors));
+}
+
 void omap3_boot_rom_init(struct omap_mpu_state_s *s)
 {
     const uint8_t rom_version[4] = { 0x00, 0x14, 0x00, 0x00 }; /* v. 14.00 */
 
+	int boot_rom_from_file = 0;
+
+	if (bios_name != NULL) boot_rom_from_file = 1;
+
     if (!s->bootrom_base) {
+        if (!boot_rom_from_file) {
         s->bootrom_base = qemu_ram_alloc(NULL, "omap3_boot_rom",
                                          OMAP3XXX_BOOTROM_SIZE);
         cpu_register_physical_memory(OMAP3_Q1_BASE + 0x14000,
@@ -891,6 +945,22 @@ void omap3_boot_rom_init(struct omap_mpu_state_s *s)
                                   omap3_sram_vectors,
                                   sizeof(omap3_sram_vectors));
     }
+		else {
+			omap3_boot_rom_allocate(s, 1);	
+		}
+    }
+}
+
+void omap3_boot_rom_run(struct omap_mpu_state_s *s)
+{
+    /* only run the boot rom if it was initialized earlier */
+    if (!s->bootrom_base) {
+        return;
+    }
+
+	/* move PC to the boot ROM reset vector */
+    s->env->regs[15] = 0x40014000;
+	printf("using omap3_boot_rom_run function\n");
 }
 
 void omap3_boot_rom_emu(struct omap_mpu_state_s *s)
diff --git a/hw/omap_gpmc.c b/hw/omap_gpmc.c
index c5e5764..83a9d05 100644
--- a/hw/omap_gpmc.c
+++ b/hw/omap_gpmc.c
@@ -419,6 +419,7 @@ static void omap_gpmc_cs_map(struct omap_gpmc_s *s, int cs)
     uint32_t mask = (f->config[6] >> 8) & 0xf;
     uint32_t base = f->config[6] & 0x3f;
     uint32_t size;
+
     /* TODO: check for overlapping regions and report access errors */
     if (mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf
          && !(s->accept_256 && !mask)) {
diff --git a/hw/omap_gptimer.c b/hw/omap_gptimer.c
index bceeed4..3c745da 100644
--- a/hw/omap_gptimer.c
+++ b/hw/omap_gptimer.c
@@ -425,11 +425,17 @@ static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
         s->ar = (value >> 1) & 1;
         s->st = (value >> 0) & 1;
         if (s->inout && s->trigger != gpt_trigger_none)
+		{
+            printf("gpt_trigger_none: %d\n", gpt_trigger_none);
             fprintf(stderr, "%s: GP timer pin must be an output "
                     "for this trigger mode\n", __FUNCTION__);
+        }
         if (!s->inout && s->capture != gpt_capture_none)
+		{
+            printf("gpt_capture_none: %d\n", gpt_capture_none);
             fprintf(stderr, "%s: GP timer pin must be an input "
                     "for this capture mode\n", __FUNCTION__);
+		}
         if (s->trigger == gpt_trigger_none)
             omap_gp_timer_out(s, s->scpwm);
         /* TODO: make sure this doesn't overflow 32-bits */
-- 
1.7.4.rc3

