diff --git a/Makefile.objs b/Makefile.objs
index c05f5e59b..7eab2dee5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -170,6 +170,7 @@ user-obj-y += cutils.o cache-utils.o
hw-obj-y =
hw-obj-y += vl.o loader.o
+hw-obj-y += iemu.o
hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
hw-obj-y += fw_cfg.o
hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
diff --git a/devices/iPhone1/config.xml b/devices/iPhone1/config.xml
new file mode 100644
index 000000000..c85eba26b
--- /dev/null
+++ b/devices/iPhone1/config.xml
@@ -0,0 +1,7 @@
+
+ iPhone1
+ m68ap
+ skin.xml
+ iboot
+ 0x18000000
+
diff --git a/skin/devices/iphone2g/iphone2g-landscape.png b/devices/iPhone1/landscape.png
similarity index 100%
rename from skin/devices/iphone2g/iphone2g-landscape.png
rename to devices/iPhone1/landscape.png
diff --git a/skin/devices/iphone2g/iphone2g-portrait.png b/devices/iPhone1/portrait.png
similarity index 100%
rename from skin/devices/iphone2g/iphone2g-portrait.png
rename to devices/iPhone1/portrait.png
diff --git a/skin/devices/iphone2g/skin.xml b/devices/iPhone1/skin.xml
similarity index 73%
rename from skin/devices/iphone2g/skin.xml
rename to devices/iPhone1/skin.xml
index c7be880c4..fcfd9b905 100644
--- a/skin/devices/iphone2g/skin.xml
+++ b/devices/iPhone1/skin.xml
@@ -2,13 +2,13 @@
-
+
-
+
diff --git a/hw/iphone2g.c b/hw/iphone2g.c
index 6ff1c3969..008858a51 100644
--- a/hw/iphone2g.c
+++ b/hw/iphone2g.c
@@ -29,8 +29,7 @@
#define RAM_SIZE 0x08000000
#define NOR_BASE_ADDR 0x24000000
-uint32_t g_debug = (0
- //S5L8900_DEBUG_CLK
+uint32_t g_debug = ( 0 //S5L8900_DEBUG_CLK
//0xffffffff |
);
uint32_t g_dlevel = 0;
@@ -244,16 +243,11 @@ static uint32_t lcd_read(void *opaque, target_phys_addr_t offset)
return 0;
}
-// Not implemented
static void lcd_write(void *opaque, target_phys_addr_t offset, uint32_t value)
{
- //iphone2g_lcd_s *s = (iphone2g_lcd_s *)opaque;
- //fprintf(stderr, "%s: offset 0x%08x value 0x%08x\n", __FUNCTION__, offset, value);
-
if(offset == 0x78) // Window 2 framebuffer. Doesn't detect active window yet!
{
// Framebuffer Address
- //fprintf(stderr, "%s: Found framebuffer at 0x%08x.\n", __func__, value);
frame_base = value;
}
}
@@ -286,12 +280,12 @@ static iphone2g_lcd_s * iphone2g_lcd_init(target_phys_addr_t base)
static uint32_t aes_read(void *opaque, target_phys_addr_t offset)
{
- struct iphone2g_aes_s *aesop = (struct iphone2g_aes_s *)opaque;
+ struct aes_s *aesop = (struct aes_s *)opaque;
//fprintf(stderr, "%s: offset 0x%08x\n", __FUNCTION__, offset);
switch(offset) {
- case IPHONE2G_AES_STATUS:
+ case AES_STATUS:
return aesop->status;
default:
//fprintf(stderr, "%s: UNMAPPED AES_ADDR @ offset 0x%08x\n", __FUNCTION__, offset);
@@ -301,93 +295,80 @@ static uint32_t aes_read(void *opaque, target_phys_addr_t offset)
return 0;
}
-typedef struct cryptdata {
- uint8_t crypt[0x80];
-} cryptdata;
-
-cryptdata cdata[] =
-{
- {{0x93, 0x1E, 0x46, 0xB9, 0x79, 0x17, 0xd9, 0xFE, 0xA, 0x0, 0x1D, 0xAD, 0x10, 0x82, 0xA8, 0x15, 0x96, 0x4F, 0xDC, 0x24, 0x11, 0xAB, 0xCD, 0xA6, 0xDE,
-0xDD, 0xE9, 0xDA, 0xCC, 0xB4, 0xE6, 0xD9, 0x5, 0x0}},
- {{0x6B, 0x84, 0x3, 0x34, 0x9E, 0x4, 0xCB, 0xDD, 0xFF, 0x69, 0x73, 0x40, 0x53, 0x60, 0xC, 0xF7, 0xC7, 0xF, 0x2C, 0x2, 0xD, 0xA3, 0x2A, 0xFD, 0xEA, 0x8E, 0xC8, 0xEC, 0x2D, 0xa, 0xF5, 0x5E, 0x5, 0x0}},
- {{0xBD, 0x9F, 0x26, 0xC7, 0xFD, 0xF3, 0xC3, 0xDF, 0xA2, 0xE7, 0x88, 0xDB, 0x48, 0x3B, 0x7C, 0x70, 0x57, 0xFF, 0xF2, 0x7F, 0x26, 0x65, 0x80, 0x4D, 0xB4, 0x2B, 0x48, 0x5F, 0x4, 0xDF, 0x31, 0xf, 0x5, 0x0}},
- {{0x8A, 0x37, 0x45, 0x45, 0xD7, 0x94, 0xCC, 0xC5, 0xD2, 0xE5, 0x5F, 0x51, 0x85, 0x12, 0xE3, 0x57, 0xA5, 0x6F, 0xFC, 0xF2, 0xBD, 0xE3, 0xF5, 0x39, 0x2, 0x14, 0x8F, 0x69, 0x49, 0x37, 0xA9, 0x1F, 0x5, 0x0}},
- {{0xF8, 0xCB, 0xEE, 0x5F, 0xB5, 0xB1, 0x2C, 0x25, 0xf, 0x5A, 0x7F, 0x45, 0xE9, 0xB8, 0x55, 0xAE, 0xFC, 0x6C, 0x69, 0x3E, 0x6E, 0x65, 0x4D, 0x69, 0x66, 0x33, 0x17, 0x67, 0xFC, 0x9E, 0x2A, 0x8, 0x5, 0x0}},
- {{0xE7, 0x25, 0x5, 0x46, 0xAC, 0x12, 0xEA, 0x24, 0x7F, 0x1D, 0xC1, 0x98, 0x72, 0x48, 0x69, 0x8F, 0xBC, 0x3A, 0x83, 0xc, 0xAB, 0xA2, 0xC8, 0xD6, 0x8E, 0xC2, 0x5E, 0xD3, 0xFD, 0x6, 0x2A, 0xE6, 0x5, 0x0}},
- {{0xC5, 0xDA, 0x96, 0xBD, 0x24, 0xBC, 0x53, 0x77, 0x61, 0x70, 0x4E, 0x84, 0x39, 0xBF, 0x18, 0x3C, 0x29, 0x2C, 0x1F, 0xD6, 0xE1, 0x66, 0x9C, 0xAD, 0x84, 0xDF, 0x4A, 0x12, 0xF2, 0x19, 0x12, 0x72, 0x5, 0x0}},
- {{0x18, 0x60, 0x8A, 0x5B, 0x1, 0x90, 0x3E, 0x77, 0xCB, 0xAE, 0xA7, 0xA8, 0xEF, 0xA6, 0xF6, 0xF0, 0xF7, 0x44, 0x6C, 0x5A, 0xd, 0x3D, 0xC6, 0xEE, 0x20, 0xB5, 0x7A, 0x11, 0xFD, 0x6F, 0x2C, 0x6F, 0x5, 0x0}},
- {{0x2F, 0x3C, 0x85, 0x5, 0x84, 0x40, 0xED, 0xA4, 0xF6, 0x6A, 0x1A, 0x78, 0x4F, 0x3F, 0x5D, 0x26, 0xD4, 0xEE, 0x80, 0x5C, 0x67, 0xF5, 0x92, 0x90, 0x37, 0x59, 0x3A, 0x1E, 0x19, 0x89, 0xB6, 0x38, 0x79, 0x58, 0x50, 0x5C, 0xEA, 0x8D, 0xED, 0x16, 0xB4, 0xA2, 0xA, 0xA7, 0x59, 0xC8, 0x29, 0x23, 0x87, 0x57, 0xC8, 0xD1, 0xD9, 0xC0, 0x98, 0x9D, 0xF5, 0xCF, 0x71, 0x9F, 0x20, 0xD8, 0x61, 0x3D, 0x11}},
- {{0x2F, 0x3C, 0x85, 0x5, 0x84, 0x40, 0xED, 0xA4, 0xF6, 0x6A, 0x1A, 0x78, 0x4F, 0x3F, 0x5D, 0x26, 0xD4, 0xEE, 0x80, 0x5C, 0x67, 0xF5, 0x92, 0x90, 0x37, 0x59, 0x3A, 0x1E, 0x19, 0x89, 0xB6, 0x38, 0x79, 0x58, 0x50, 0x5C, 0xEA, 0x8D, 0xED, 0x16, 0xB4, 0xA2, 0xA, 0xA7, 0x59, 0xC8, 0x29, 0x23, 0x87, 0x57, 0xC8, 0xD1, 0xD9, 0xC0, 0x98, 0x9D, 0xF5, 0xCF, 0x71, 0x9F, 0x20, 0xD8, 0x61, 0x3D, 0x11}},
- {{0x2F, 0x3C, 0x85, 0x5, 0x84, 0x40, 0xED, 0xA4, 0xF6, 0x6A, 0x1A, 0x78, 0x4F, 0x3F, 0x5D, 0x26, 0xD4, 0xEE, 0x80, 0x5C, 0x67, 0xF5, 0x92, 0x90, 0x37, 0x59, 0x3A, 0x1E, 0x19, 0x89, 0xB6, 0x38, 0x79, 0x58, 0x50, 0x5C, 0xEA, 0x8D, 0xED, 0x16, 0xB4, 0xA2, 0xA, 0xA7, 0x59, 0xC8, 0x29, 0x23, 0x87, 0x57, 0xC8, 0xD1, 0xD9, 0xC0, 0x98, 0x9D, 0xF5, 0xCF, 0x71, 0x9F, 0x20, 0xD8, 0x61, 0x3D, 0x11}},
- {{0x2F, 0x3C, 0x85, 0x5, 0x84, 0x40, 0xED, 0xA4, 0xF6, 0x6A, 0x1A, 0x78, 0x4F, 0x3F, 0x5D, 0x26, 0xD4, 0xEE, 0x80, 0x5C, 0x67, 0xF5, 0x92, 0x90, 0x37, 0x59, 0x3A, 0x1E, 0x19, 0x89, 0xB6, 0x38, 0x79, 0x58, 0x50, 0x5C, 0xEA, 0x8D, 0xED, 0x16, 0xB4, 0xA2, 0xA, 0xA7, 0x59, 0xC8, 0x29, 0x23, 0x87, 0x57, 0xC8, 0xD1, 0xD9, 0xC0, 0x98, 0x9D, 0xF5, 0xCF, 0x71, 0x9F, 0x20, 0xD8, 0x61, 0x3D, 0x11}}
-
-};
-static int ccount = 0;
-
static void aes_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
- struct iphone2g_aes_s *aesop = (struct iphone2g_aes_s *)opaque;
- uint8_t inbuf[0x1000];
- uint8_t *buf;
- //uint32_t ctr;
+ struct aes_s *aesop = (struct aes_s *)opaque;
+ static uint8_t keylenop = 0;
- //fprintf(stderr, "%s: offset 0x%08x value 0x%08x\n", __FUNCTION__, offset, value);
+ uint8_t inbuf[0x1000];
+ uint8_t *buf;
- switch(offset) {
- case IPHONE2G_AES_GO:
- //fprintf(stderr, "%s: Received AES_GO lets do it\n", __FUNCTION__);
- memset(aesop->ivec, 0, 16);
+ //fprintf(stderr, "%s: offset 0x%08x value 0x%08x\n", __FUNCTION__, offset, value);
+ switch(offset) {
+ case AES_GO:
memset(inbuf, 0, sizeof(inbuf));
- //fprintf(stderr, "%s: AES_DECRYPT INADDR 0x%08x INSIZE 0x%08x OUTADDR 0x%08x\n", __FUNCTION__, aesop->inaddr, aesop->insize, aesop->outaddr);
-
cpu_physical_memory_read((aesop->inaddr - 0x80000000), (uint8_t *)inbuf, aesop->insize);
- /*
- for( ctr = 0; ctr < aesop->insize; ctr++ )
- {
- fprintf(stderr, "%02x ", inbuf[ ctr ] );
- }
- fprintf(stderr, "\n" );
- */
- buf = (uint8_t *) malloc(aesop->insize);
- memset(buf, 0, aesop->insize);
- if(aesop->insize >= 0x20)
- {
- memcpy(buf, cdata[ccount].crypt, aesop->insize);
- ccount++;
- } else {
- //AES_cbc_encrypt(inbuf, buf, aesop->insize, &aesop->decryptKey, aesop->ivec, AES_DECRYPT);
- /*
- fprintf(stderr, "decrypting: ");
- for( ctr = 0; ctr < aesop->insize; ctr++ )
- {
- fprintf(stderr, "%02x ", buf[ ctr ] );
- }
- */
- ;
+
+ switch(aesop->keytype) {
+ case AESGID:
+ fprintf(stderr, "%s: No support for GID key\n", __func__);
+ return;
+ case AESUID:
+ AES_set_decrypt_key(key_uid, sizeof(key_uid) * 8, &aesop->decryptKey);
+ break;
+ case AESCustom:
+ AES_set_decrypt_key((uint8_t *)aesop->custkey, 0x20 * 8, &aesop->decryptKey);
+ break;
}
+
+ buf = (uint8_t *) qemu_mallocz(aesop->insize);
+
+ AES_cbc_encrypt(inbuf, buf, aesop->insize, &aesop->decryptKey, (uint8_t *)aesop->ivec, aesop->operation);
+
cpu_physical_memory_write((aesop->outaddr - 0x80000000), buf, aesop->insize);
- free(buf);
+ memset(aesop->custkey, 0, 0x20);
+ memset(aesop->ivec, 0, 0x10);
+ qemu_free(buf);
+ keylenop = 0;
aesop->outsize = aesop->insize;
aesop->status = 0xf;
break;
- case IPHONE2G_AES_INADDR:
+ case AES_KEYLEN:
+ if(keylenop == 1) {
+ aesop->operation = value;
+ }
+ keylenop++;
+ aesop->keylen = value;
+ break;
+ case AES_INADDR:
aesop->inaddr = value;
break;
- case IPHONE2G_AES_INSIZE:
+ case AES_INSIZE:
aesop->insize = value;
break;
- case IPHONE2G_AES_OUTSIZE:
+ case AES_OUTSIZE:
aesop->outsize = value;
break;
- case IPHONE2G_AES_OUTADDR:
+ case AES_OUTADDR:
aesop->outaddr = value;
break;
- case IPHONE2G_AES_KEY ... ((IPHONE2G_AES_KEY + IPHONE2G_AES_KEYSIZE) - 1):
- break;
- case IPHONE2G_AES_IV ... ((IPHONE2G_AES_IV + IPHONE2G_AES_IVSIZE) -1 ):
+ case AES_TYPE:
+ aesop->keytype = value;
break;
+ case AES_KEY_REG ... ((AES_KEY_REG + AES_KEYSIZE) - 1):
+ {
+ uint8_t idx = (offset - AES_KEY_REG) / 4;
+ aesop->custkey[idx] |= value;
+ break;
+ }
+ case AES_IV_REG ... ((AES_IV_REG + AES_IVSIZE) -1 ):
+ {
+ uint8_t idx = (offset - AES_IV_REG) / 4;
+ aesop->ivec[idx] |= value;
+ break;
+ }
default:
//fprintf(stderr, "%s: UNMAPPED AES_ADDR @ offset 0x%08x - 0x%08x\n", __FUNCTION__, offset, value);
break;
@@ -407,16 +388,123 @@ static CPUWriteMemoryFunc *aes_writefn[] = {
aes_write,
};
-static void iphone2g_aes_init(target_phys_addr_t base)
+static void aes_init(target_phys_addr_t base)
{
- struct iphone2g_aes_s *aesop = (struct iphone2g_aes_s *) qemu_mallocz(sizeof(iphone2g_aes_s));
+ struct aes_s *aesop = (struct aes_s *) qemu_mallocz(sizeof(aes_s));
int io;
io = cpu_register_io_memory(aes_readfn, aes_writefn, aesop, DEVICE_LITTLE_ENDIAN);
cpu_register_physical_memory(base, 0xFF, io);
+}
+
+typedef struct sha1_status {
+ uint32_t config;
+ uint32_t reset;
+ uint32_t hresult;
+ uint32_t insize;
+ uint32_t unkstat;
+ uint8_t hashout[0x14];
+} sha1_status_s;
+
+static void sha1_reset(void *opaque)
+{
+ sha1_status_s *s = (sha1_status_s *)opaque;
+ memset(s, 0, sizeof(sha1_status_s));
+}
+
+static uint32_t sha1_read(void *opaque, target_phys_addr_t offset)
+{
+ sha1_status_s *s = (sha1_status_s *)opaque;
+
+ //fprintf(stderr, "%s: offset 0x%08x\n", __FUNCTION__, offset);
- //AES_set_decrypt_key(key_0x837, sizeof(key_0x837) * 8, &aesop->decryptKey);
+ switch(offset) {
+ case SHA_CONFIG:
+ return s->config;
+ case SHA_RESET:
+ return 0;
+ case SHA_HRESULT:
+ return s->hresult;
+ case SHA_INSIZE:
+ return s->insize;
+ /* Hash result ouput */
+ case 0x20 ... 0x34:
+ //fprintf(stderr, "Hash out %08x\n", *(uint32_t *)&s->hashout[offset - 0x20]);
+ return *(uint32_t *)&s->hashout[offset - 0x20];
+ }
+ return 0;
+}
+
+static void sha1_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ sha1_status_s *s = (sha1_status_s *)opaque;
+
+ //fprintf(stderr, "%s: offset 0x%08x value 0x%08x\n", __FUNCTION__, offset, value);
+
+ switch(offset) {
+ case SHA_CONFIG:
+ if((value & 0x2) && (s->config & 0x8))
+ {
+ uint8_t *hptr;
+
+ if(!s->hresult || !s->insize)
+ return;
+
+ /* Why do they give us incorrect size? */
+ s->insize += 0x20;
+
+ hptr = (uint8_t *) qemu_mallocz(s->insize);
+ cpu_physical_memory_read(s->hresult, (uint8_t *)hptr, s->insize);
+
+ SHA_CTX context;
+ SHA1_Init(&context);
+ SHA1_Update(&context, (uint8_t*) hptr, s->insize);
+ SHA1_Final(s->hashout, &context);
+
+ qemu_free(hptr);
+ } else {
+ s->config = value;
+ }
+ break;
+ case SHA_RESET:
+ if(value & 1)
+ sha1_reset(s);
+ break;
+ case SHA_HRESULT:
+ s->hresult = value;
+ break;
+ case SHA_INSIZE:
+ s->insize = value;
+ break;
+ case SHA_UNKSTAT:
+ s->unkstat = value;
+ break;
+ }
+
+
+}
+
+static CPUReadMemoryFunc * const sha1_readfn[] = {
+ sha1_read,
+ sha1_read,
+ sha1_read,
+};
+
+static CPUWriteMemoryFunc * const sha1_writefn[] = {
+ sha1_write,
+ sha1_write,
+ sha1_write,
+};
+
+static void sha1_init(target_phys_addr_t base)
+{
+ sha1_status_s *s = (sha1_status_s *) qemu_mallocz(sizeof(sha1_status_s));
+ int iomemtype = cpu_register_io_memory(sha1_readfn,
+ sha1_writefn,
+ s, DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(base, 0xFF, iomemtype);
}
typedef struct iphone2gKeyState_s {
@@ -500,7 +588,9 @@ static void iphone2g_init(ram_addr_t ram_size,
exit(1);
}
- cpu_register_physical_memory(iboot_base, (ram_addr_t)iboot_size,(phys_flash = qemu_ram_alloc(NULL, "iphone2g.iboot", iboot_size)));
+ cpu_register_physical_memory(0x22000000, 0x500000, qemu_ram_alloc(NULL, "iphone2g.sram", 0x500000));
+
+ cpu_register_physical_memory(iboot_base, (ram_addr_t)iboot_size, qemu_ram_alloc(NULL, "iphone2g.iboot", iboot_size) | IO_MEM_RAM);
load_image_targphys(option_rom[0].name, iboot_base, iboot_size);
@@ -508,7 +598,7 @@ static void iphone2g_init(ram_addr_t ram_size,
/* Map in default ram space */
cpu_register_physical_memory(RAM_BASE_ADDR, RAM_SIZE, ramoff | IO_MEM_RAM);
/* Also map higher ram space to default */
- cpu_register_physical_memory(RAM_HIGH_ADDR, RAM_SIZE, ramoff | IO_MEM_RAM);
+ //cpu_register_physical_memory(RAM_HIGH_ADDR, RAM_SIZE, ramoff | IO_MEM_RAM);
/* Also also map to 0x0 as that's what OIB uses */
cpu_register_physical_memory(0x0, RAM_SIZE, ramoff | IO_MEM_RAM);
@@ -531,7 +621,10 @@ static void iphone2g_init(ram_addr_t ram_size,
iphone2g_lcd_init(LCD_BASE_ADDR);
/* Init AES hardware */
- iphone2g_aes_init(AES_BASE_ADDR);
+ aes_init(AES_BASE_ADDR);
+
+ /* Init SHA1 hardware */
+ sha1_init(SHA1_BASE_ADDR);
/* Button emulation */
iphone2g_register_keyboard();
@@ -540,8 +633,8 @@ static void iphone2g_init(ram_addr_t ram_size,
}
static QEMUMachine iphone2g_machine = {
- .name = "iphone2g",
- .desc = "iPhone 2G",
+ .name = "iPhone1",
+ .desc = "iPhone 1",
.init = iphone2g_init,
};
diff --git a/hw/iphone2g.h b/hw/iphone2g.h
index e980213a1..51a116bce 100644
--- a/hw/iphone2g.h
+++ b/hw/iphone2g.h
@@ -4,39 +4,59 @@
#include
#include
-#define key_0x837 ((uint8_t[]){0x18, 0x84, 0x58, 0xA6, 0xD1, 0x50, 0x34, 0xDF, 0xE3, 0x86, 0xF2, 0x3B, 0x61, 0xD4, 0x37, 0x74})
+#define key_uid ((uint8_t[]){0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF})
+
+#define GET_BITS(x, start, length) ((((uint32_t)(x)) << (32 - ((start) + (length)))) >> (32 - (length)))
+#define GET_KEYLEN(x) GET_BITS(x, 16, 2)
#define LCD_BASE_ADDR 0x38900000
#define LCD_WIDTH 320
#define LCD_HEIGHT 480
+#define SHA1_BASE_ADDR 0x38000000
+#define SHA_CONFIG 0x0
+#define SHA_RESET 0x4
+#define SHA_UNKSTAT 0x7c
+#define SHA_HRESULT 0x84
+#define SHA_INSIZE 0x8c
+
#define AES_128_CBC_BLOCK_SIZE 64
#define AES_BASE_ADDR 0x38C00000
- #define IPHONE2G_AES_CONTROL 0x0
- #define IPHONE2G_AES_GO 0x4
- #define IPHONE2G_AES_UNKREG0 0x8
- #define IPHONE2G_AES_STATUS 0xC
- #define IPHONE2G_AES_UNKREG1 0x10
- #define IPHONE2G_AES_KEYLEN 0x14
- #define IPHONE2G_AES_INSIZE 0x18
- #define IPHONE2G_AES_INADDR 0x20
- #define IPHONE2G_AES_OUTSIZE 0x24
- #define IPHONE2G_AES_OUTADDR 0x28
- #define IPHONE2G_AES_AUXSIZE 0x2C
- #define IPHONE2G_AES_AUXADDR 0x30
- #define IPHONE2G_AES_SIZE3 0x34
- #define IPHONE2G_AES_KEY 0x4C
- #define IPHONE2G_AES_TYPE 0x6C
- #define IPHONE2G_AES_IV 0x74
- #define IPHONE2G_AES_KEYSIZE 0x20
- #define IPHONE2G_AES_IVSIZE 0x10
-
-
-
-typedef struct iphone2g_aes_s
+#define AES_CONTROL 0x0
+#define AES_GO 0x4
+#define AES_UNKREG0 0x8
+#define AES_STATUS 0xC
+#define AES_UNKREG1 0x10
+#define AES_KEYLEN 0x14
+#define AES_INSIZE 0x18
+#define AES_INADDR 0x20
+#define AES_OUTSIZE 0x24
+#define AES_OUTADDR 0x28
+#define AES_AUXSIZE 0x2C
+#define AES_AUXADDR 0x30
+#define AES_SIZE3 0x34
+#define AES_KEY_REG 0x4C
+#define AES_TYPE 0x6C
+#define AES_IV_REG 0x74
+#define AES_KEYSIZE 0x20
+#define AES_IVSIZE 0x10
+
+typedef enum AESKeyType {
+ AESCustom = 0,
+ AESGID = 1,
+ AESUID = 2
+} AESKeyType;
+
+typedef enum AESKeyLen {
+ AES128 = 0,
+ AES192 = 1,
+ AES256 = 2
+} AESKeyLen;
+
+typedef struct aes_s
{
AES_KEY decryptKey;
- uint8_t ivec[16];
+ uint32_t ivec[4];
uint32_t insize;
uint32_t inaddr;
uint32_t outsize;
@@ -47,8 +67,10 @@ typedef struct iphone2g_aes_s
uint32_t ctrl;
uint32_t unkreg0;
uint32_t unkreg1;
+ uint32_t operation;
uint32_t keylen;
-} iphone2g_aes_s;
+ uint32_t custkey[8];
+} aes_s;
typedef struct iphone2g_lcd_s {
diff --git a/hw/s5l8900.c b/hw/s5l8900.c
index 9bc97874f..4f361f305 100644
--- a/hw/s5l8900.c
+++ b/hw/s5l8900.c
@@ -42,11 +42,66 @@ typedef struct s5l8900_timer_s
{
uint32_t ticks_high;
uint32_t ticks_low;
+ uint32_t status;
+ uint32_t config;
+ uint32_t bcount1;
+ uint32_t bcount2;
+ uint32_t prescaler;
+ uint32_t irqstat;
+
+ QEMUTimer *st_timer;
+ uint32_t bcreload;
+ uint32_t freq_out;
+ uint64_t tick_interval;
+ uint64_t last_tick;
+ uint64_t next_planned_tick;
+ uint64_t base_time;
+ qemu_irq irq;
} s5l8900_timer_s;
struct s5l8900_gpio_s s5l8900_gpio_state[32];
+static void s5l8900_st_tick(void *opaque);
+
+/* Update tick_interval */
+static void s5l8900_st_update(s5l8900_timer_s *s)
+{
+ s->freq_out = 1000000000 / 100;
+ s->tick_interval = /* bcount1 * get_ticks / freq + ((bcount2 * get_ticks / freq)*/
+ muldiv64((s->bcount1 < 1000) ? 1000 : s->bcount1, get_ticks_per_sec(), s->freq_out);
+ s->next_planned_tick = 0;
+
+ //fprintf(stderr, "%s: freq_out 0x%08x tick_interval %lld ticks per sec %lld\n", __func__, s->freq_out, s->tick_interval, get_ticks_per_sec());
+}
+
+static void s5l8900_st_set_timer(s5l8900_timer_s *s)
+{
+ uint64_t last = qemu_get_clock_ns(vm_clock) - s->base_time;
+
+ s->next_planned_tick = last + (s->tick_interval - last % s->tick_interval);
+ qemu_mod_timer(s->st_timer, s->next_planned_tick + s->base_time);
+ s->last_tick = last;
+}
+
+/* counter step */
+static void s5l8900_st_tick(void *opaque)
+{
+ s5l8900_timer_s *s = (s5l8900_timer_s *)opaque;
+
+ if (s->status & TIMER_STATE_START) {
+ //fprintf(stderr, "%s: Raising irq\n", __func__);
+ qemu_irq_raise(s->irq);
+
+ /* schedule next interrupt */
+ s5l8900_st_set_timer(s);
+ } else {
+ s->next_planned_tick = 0;
+ s->last_tick = 0;
+ qemu_del_timer(s->st_timer);
+ }
+}
+
static uint32_t s5l8900_timer1_read(void *opaque, target_phys_addr_t addr)
{
s5l8900_timer_s *s = (struct s5l8900_timer_s *) opaque;
@@ -62,6 +117,11 @@ static uint32_t s5l8900_timer1_read(void *opaque, target_phys_addr_t addr)
return s->ticks_high;
case TIMER_TICKSLOW:
return s->ticks_low;
+ case TIMER_IRQSTAT:
+ return s->irqstat;
+ case TIMER_IRQLATCH:
+ return 0xffffffff;
+
default:
S5L8900_DEBUG(S5L8900_DEBUG_CLK, S5L8900_DLVL_ERR, "%s: UNMAPPED offset = 0x%02x\n", __FUNCTION__, (int)addr);
}
@@ -70,9 +130,43 @@ static uint32_t s5l8900_timer1_read(void *opaque, target_phys_addr_t addr)
static void s5l8900_timer1_write(void *opaque, target_phys_addr_t addr, uint32_t value)
{
+ s5l8900_timer_s *s = (struct s5l8900_timer_s *) opaque;
+
+ S5L8900_DEBUG(S5L8900_DEBUG_CLK, S5L8900_DLVL_ERR, "%s: offset = 0x%02x value = 0x%08x\n", __FUNCTION__, (int)addr, value);
+ switch(addr){
+
+ case TIMER_IRQSTAT:
+ s->irqstat = value;
+ return;
+ case TIMER_IRQLATCH:
+ //fprintf(stderr, "%s: lowering irq\n", __func__);
+ qemu_irq_lower(s->irq);
+ return;
+ case TIMER_4 + TIMER_CONFIG:
+ s5l8900_st_update(s);
+ s->config = value;
+ break;
+ case TIMER_4 + TIMER_STATE:
+ if ((value & TIMER_STATE_START) > (s->status & TIMER_STATE_START)) {
+ s->base_time = qemu_get_clock_ns(vm_clock);
+ s5l8900_st_update(s);
+ s5l8900_st_set_timer(s);
+ } else if ((value & TIMER_STATE_START) < (s->status & TIMER_STATE_START)) {
+ qemu_del_timer(s->st_timer);
+ }
+ s->status = value;
+ break;
+ case TIMER_4 + TIMER_COUNT_BUFFER:
+ s->bcount1 = s->bcreload = value;
+ break;
+ case TIMER_4 + TIMER_COUNT_BUFFER2:
+ s->bcount2 = value;
+ break;
+ default:
+ break;
+ }
- S5L8900_DEBUG(S5L8900_DEBUG_CLK, S5L8900_DLVL_ERR, "%s: offset = 0x%02x\n", __FUNCTION__, (int)addr);
-
+ return;
}
static CPUReadMemoryFunc *s5l8900_timer1_readfn[] = {
@@ -87,16 +181,19 @@ static CPUWriteMemoryFunc *s5l8900_timer1_writefn[] = {
s5l8900_timer1_write,
};
-static void s5l8900_timer_init(target_phys_addr_t base)
+static void s5l8900_timer_init(target_phys_addr_t base, qemu_irq irq)
{
struct s5l8900_timer_s *timer1 = (struct s5l8900_timer_s *) qemu_mallocz(sizeof(struct s5l8900_timer_s));
int iomemtype = cpu_register_io_memory(s5l8900_timer1_readfn,
s5l8900_timer1_writefn, timer1, DEVICE_LITTLE_ENDIAN);
- S5L8900_OPAQUE("TIMER1", timer1);
- timer1->ticks_high = 0;
- timer1->ticks_low = 0;
+ timer1->irq = irq;
cpu_register_physical_memory(base, 0xFF, iomemtype);
+
+ timer1->base_time = qemu_get_clock_ns(vm_clock);
+
+ timer1->st_timer = qemu_new_timer_ns(vm_clock, s5l8900_st_tick, timer1);
+
}
static uint32_t s5l8900_clk1_read(void *opaque, target_phys_addr_t addr)
@@ -142,48 +239,6 @@ static CPUWriteMemoryFunc *s5l8900_clk1_writefn[] = {
s5l8900_clk1_write,
};
-
-static uint32_t s5l8900_miu_read(void *opaque, target_phys_addr_t addr)
-{
- S5L8900_DEBUG(S5L8900_DEBUG_MIU, S5L8900_DLVL_ERR, "%s: offset = 0x%02x\n", __FUNCTION__, (int)addr);
-
- switch (addr) {
- case POWER_ID:
- return (3 << 24); //for older iboots
- //return (5 << 0x18); // new iboots
- default:
- S5L8900_DEBUG(S5L8900_DEBUG_MIU, S5L8900_DLVL_ERR, "%s: UNMAPPED offset = 0x%02x\n", __FUNCTION__, (int)addr);
- }
- return 0;
-}
-
-static void s5l8900_miu_write(void *opaque, target_phys_addr_t addr, uint32_t value)
-{
-
- S5L8900_DEBUG(S5L8900_DEBUG_MIU, S5L8900_DLVL_ERR, "%s: offset = 0x%02x\n", __FUNCTION__, (int)addr);
-
-}
-
-static CPUReadMemoryFunc *s5l8900_miu_readfn[] = {
- s5l8900_miu_read,
- s5l8900_miu_read,
- s5l8900_miu_read,
-};
-
-static CPUWriteMemoryFunc *s5l8900_miu_writefn[] = {
- s5l8900_miu_write,
- s5l8900_miu_write,
- s5l8900_miu_write,
-};
-
-static void s5l8900_miu_init(target_phys_addr_t base)
-{
- int iomemtype = cpu_register_io_memory(s5l8900_miu_readfn,
- s5l8900_miu_writefn, NULL, DEVICE_LITTLE_ENDIAN);
- cpu_register_physical_memory(base, 0x50, iomemtype);
-}
-
-
static void s5l8900_clk_init(target_phys_addr_t base)
{
struct s5l8900_clk1_s *clk1 = (struct s5l8900_clk1_s *) qemu_mallocz(sizeof(struct s5l8900_clk1_s));
@@ -202,15 +257,55 @@ static uint32_t s5l8900_chipid_read(void *opaque, target_phys_addr_t addr)
switch(addr) {
case 0x04:
- #if 0 /* only enable if your on 3.1.3 */
{
- uint32_t debug_uart = 0xffffffff;
- cpu_physical_memory_write(0x1802765C, (uint8_t *)&debug_uart, 4);
+ uint32_t debug_uart = 0xffffffff;
+ //cpu_physical_memory_write(0x1802765C, (uint8_t *)&debug_uart, 4);
+ //cpu_physical_memory_write(0x18029FE0, (uint8_t *)&debug_uart, 4);
+ cpu_physical_memory_write(0x18022FA0, (uint8_t *)&debug_uart, 4);
}
- #endif
return 0xfffffffc;
case 0x8:
return 0x4;
+ case 0xc:
+ fprintf(stderr, "Loading kernel image\n");
+ {
+ struct stat st;
+ unsigned int size;
+ int ret;
+ uint8_t *buf;
+ uint32_t debug_uart = 0xffffffff;
+ //cpu_physical_memory_write(0x1802765C, (uint8_t *)&debug_uart, 4);
+ //cpu_physical_memory_write(0x18029FE0, (uint8_t *)&debug_uart, 4);
+ cpu_physical_memory_write(0x18022FA0, (uint8_t *)&debug_uart, 4);
+
+ stat("../../ibootfiles/kernelcache.release.s5l8900x.no8900", &st);
+ size = st.st_size;
+
+ FILE *fd = fopen("../../ibootfiles/kernelcache.release.s5l8900x.no8900", "r");
+
+ buf = (uint8_t *)malloc(size);
+ ret = fread(buf, 1, size, fd);
+ fprintf(stderr, "kernel read %d\n", ret);
+ if(ret != size)
+ {
+ fprintf(stderr, "error reading kernel %d ret %d\n", size, ret);
+ }
+ fclose(fd);
+ cpu_physical_memory_write(0x08000000, buf, size);
+ free(buf);
+ stat("../../ibootfiles/ramdisk-1.0.2.dmg", &st);
+ size = st.st_size;
+ fd = fopen("../../ibootfiles/ramdisk-1.0.2.dmg", "r");
+ buf = (uint8_t *)malloc(size);
+ ret = fread(buf, 1, size, fd);
+ if(ret != size)
+ {
+ fprintf(stderr, "error reading ramdisk %d ret %d\n", size, ret);
+ }
+ fclose(fd);
+ cpu_physical_memory_write(0x9340000, buf, size);
+ free(buf);
+ }
default:
S5L8900_DEBUG(S5L8900_DEBUG_CHIPID, S5L8900_DLVL_ERR, "%s: UNMAPPED offset = 0x%02x\n", __FUNCTION__, (int)addr);
@@ -231,18 +326,19 @@ static CPUWriteMemoryFunc *s5l8900_chipid_writefn[] = {
NULL,
};
-static void s5l8900_gpioic_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+static void s5l8900_sysic_write(void *opaque, target_phys_addr_t addr, uint32_t value)
{
//fprintf(stderr, "%s: offset 0x%08x value 0x%08x\n", __func__, addr, value);
}
-static uint32_t s5l8900_gpioic_read(void *opaque, target_phys_addr_t addr)
+static uint32_t s5l8900_sysic_read(void *opaque, target_phys_addr_t addr)
{
//fprintf(stderr, "%s: offset 0x%08x\n", __func__, addr);
switch(addr) {
- case 0x44:
- return 0x5000005;
+ case POWER_ID:
+ //return (3 << 24); //for older iboots
+ return (2 << 0x18);
case 0x7a:
case 0x7c:
return 1;
@@ -251,23 +347,23 @@ static uint32_t s5l8900_gpioic_read(void *opaque, target_phys_addr_t addr)
return 0;
}
-static CPUReadMemoryFunc *s5l8900_gpioic_readfn[] = {
- s5l8900_gpioic_read,
- s5l8900_gpioic_read,
- s5l8900_gpioic_read,
+static CPUReadMemoryFunc *s5l8900_sysic_readfn[] = {
+ s5l8900_sysic_read,
+ s5l8900_sysic_read,
+ s5l8900_sysic_read,
};
-static CPUWriteMemoryFunc *s5l8900_gpioic_writefn[] = {
- s5l8900_gpioic_write,
- s5l8900_gpioic_write,
- s5l8900_gpioic_write,
+static CPUWriteMemoryFunc *s5l8900_sysic_writefn[] = {
+ s5l8900_sysic_write,
+ s5l8900_sysic_write,
+ s5l8900_sysic_write,
};
-static void s5l8900_gpioic_init(target_phys_addr_t base)
+static void s5l8900_sysic_init(target_phys_addr_t base)
{
- int iomemtype = cpu_register_io_memory(s5l8900_gpioic_readfn,
- s5l8900_gpioic_writefn, NULL, DEVICE_LITTLE_ENDIAN);
+ int iomemtype = cpu_register_io_memory(s5l8900_sysic_readfn,
+ s5l8900_sysic_writefn, NULL, DEVICE_LITTLE_ENDIAN);
cpu_register_physical_memory(base, 0x3FF, iomemtype);
}
@@ -349,7 +445,8 @@ static uint32_t s5l8900_usb_phy_read(void *opaque, target_phys_addr_t offset)
return s->usb_ophytune;
default:
- hw_error("%s: read invalid location 0x%08x.\n", __func__, offset);
+ //hw_error("%s: read invalid location 0x%08x.\n", __func__, offset);
+ fprintf(stderr, "%s: read invalid location 0x%08x\n", __func__, offset);
return 0;
}
@@ -379,7 +476,8 @@ static void s5l8900_usb_phy_write(void *opaque, target_phys_addr_t offset, uint3
return;
default:
- hw_error("%s: write invalid location 0x%08x.\n", __func__, offset);
+ //hw_error("%s: write invalid location 0x%08x.\n", __func__, offset);
+ fprintf(stderr, "%s: write invalid location 0x%08x\n", __func__, offset);
}
}
@@ -455,17 +553,14 @@ s5l8900_state *s5l8900_init(void)
/* CLKs */
s5l8900_clk_init(CLOCK1);
- /* MIU */
- s5l8900_miu_init(MIU_BASE);
-
/* Sytem Timer */
- s5l8900_timer_init(S5L8900_TIMER1);
+ s5l8900_timer_init(TIMER1, s5l8900_get_irq(s, IRQ_TIMER0));
/* GPIO */
s5l8900_gpio_init(S5L8900_GPIO_BASE);
- /* GPIOIC */
- s5l8900_gpioic_init(S5L8900_GPIOIC_BASE);
+ /* SYSIC */
+ s5l8900_sysic_init(S5L8900_SYSIC_BASE);
/* Uart */
s5l8900_uart_init(S5L8900_UART0_BASE, 0, 256, s5l8900_get_irq(s, S5L8900_IRQ_UART0), serial_hds[0]);
diff --git a/hw/s5l8900.h b/hw/s5l8900.h
index f1f6b113e..7e3bab8cf 100644
--- a/hw/s5l8900.h
+++ b/hw/s5l8900.h
@@ -4,9 +4,11 @@
#include "qemu-timer.h"
// Devices
+// SYSIC/MIU
+#define S5L8900_SYSIC_BASE 0x39A00000
+#define POWER_ID 0x44
// GPIO
-#define S5L8900_GPIOIC_BASE 0x39A00000
#define S5L8900_GPIO_BASE 0x3E400000
#define S5L8900_IRQ_GPIO0 0x21
#define S5L8900_IRQ_GPIO1 0x20
@@ -32,10 +34,6 @@
#define PCF50633_ADDR_SET 0xe7
#define BUTTONS_IIC_STATE 0x4B
-// MIU
-#define MIU_BASE 0x39A00000
-#define POWER_ID 0x44
-
// Chip ID
#define S5L8900_CHIPID 0x3e500000
@@ -45,10 +43,21 @@
#define S5L8900_IRQ_UART0 24
// TIMERS
-#define S5L8900_IRQ_TIMER0 7
-#define S5L8900_TIMER1 0x3E200000
+#define IRQ_TIMER0 7
+#define TIMER_IRQSTAT 0x10000
+#define TIMER_IRQLATCH 0xF8
+#define TIMER1 0x3E200000
#define TIMER_TICKSHIGH 0x80
#define TIMER_TICKSLOW 0x84
+#define TIMER_STATE_START 1
+#define TIMER_STATE_STOP 0
+#define TIMER_STATE_MANUALUPDATE 2
+#define NUM_TIMERS 7
+#define TIMER_4 0xA0
+#define TIMER_CONFIG 0
+#define TIMER_STATE 0x4
+#define TIMER_COUNT_BUFFER 0x8
+#define TIMER_COUNT_BUFFER2 0xC
// VIC
#define S5l8900_I2C0_BASE 0x3C600000
diff --git a/hw/s5l8900_i2c.c b/hw/s5l8900_i2c.c
index 7fc9f888d..90f9ca5f1 100644
--- a/hw/s5l8900_i2c.c
+++ b/hw/s5l8900_i2c.c
@@ -126,8 +126,8 @@ static uint32_t s5l8900_i2c_read(void *opaque, target_phys_addr_t offset)
return tmp_reg20;
}
default:
- hw_error("s5l8900.i2c: bad read offset 0x" TARGET_FMT_plx "\n",
- offset);
+ //hw_error("s5l8900.i2c: bad read offset 0x" TARGET_FMT_plx "\n", offset);
+ fprintf(stderr, "%s: bad read offset 0x%08x\n", __func__, offset);
}
return 0;
}
@@ -229,8 +229,8 @@ static void s5l8900_i2c_write(void *opaque, target_phys_addr_t offset,
//s->iicreg20 &= ~value;
break;
default:
- hw_error("s5l8900.i2c: bad write offset 0x" TARGET_FMT_plx "\n",
- offset);
+ //hw_error("s5l8900.i2c: bad write offset 0x" TARGET_FMT_plx "\n", offset);
+ fprintf(stderr, "%s: bad write offset 0x%08x\n", __func__, offset);
}
}
diff --git a/hw/usb_synopsys.c b/hw/usb_synopsys.c
index a554dd163..b1cf7fef3 100644
--- a/hw/usb_synopsys.c
+++ b/hw/usb_synopsys.c
@@ -325,7 +325,7 @@ static void synopsys_usb_update_irq(synopsys_usb_state *_state)
if((_state->pcgcctl & 3) == 0 && _state->gintmsk & _state->gintsts)
{
- printf("USB: IRQ triggered 0x%08x & 0x%08x.\n", _state->gintsts, _state->gintmsk);
+ //printf("USB: IRQ triggered 0x%08x & 0x%08x.\n", _state->gintsts, _state->gintmsk);
qemu_irq_raise(_state->irq);
}
else
@@ -354,7 +354,7 @@ static void synopsys_usb_update_in_ep(synopsys_usb_state *_state, uint8_t _ep)
synopsys_usb_update_ep(_state, eps);
if(eps->control & USB_EPCON_ENABLE)
- printf("USB: IN transfer queued on %d.\n", _ep);
+ ;//printf("USB: IN transfer queued on %d.\n", _ep);
}
static void synopsys_usb_update_out_ep(synopsys_usb_state *_state, uint8_t _ep)
@@ -363,7 +363,7 @@ static void synopsys_usb_update_out_ep(synopsys_usb_state *_state, uint8_t _ep)
synopsys_usb_update_ep(_state, eps);
if(eps->control & USB_EPCON_ENABLE)
- printf("USB: OUT transfer queued on %d.\n", _ep);
+ ;//printf("USB: OUT transfer queued on %d.\n", _ep);
}
static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_usb_header_t *_hdr, char *_buffer)
@@ -393,7 +393,7 @@ static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_us
if(eps->control & USB_EPCON_STALL)
{
eps->control &=~ USB_EPCON_STALL; // Should this be EP0 only
- printf("USB: Stall.\n");
+ //printf("USB: Stall.\n");
ret = USB_RET_STALL;
}
else if(eps->control & USB_EPCON_ENABLE)
@@ -417,7 +417,7 @@ static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_us
if(txfs + txfz > sizeof(state->fifos))
hw_error("usb_synopsys: USB transfer would overflow FIFO buffer!\n");
- printf("USB: Starting IN transfer on EP %d (%d)...\n", ep, amtDone);
+ //printf("USB: Starting IN transfer on EP %d (%d)...\n", ep, amtDone);
if(amtDone > 0)
{
@@ -430,7 +430,7 @@ static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_us
memcpy(_buffer, (char*)&state->fifos[txfs], amtDone);
}
- printf("USB: IN transfer complete!\n");
+ //printf("USB: IN transfer complete!\n");
eps->tx_size = (eps->tx_size &~ DEPTSIZ_XFERSIZ_MASK)
| ((sz-amtDone) & DEPTSIZ_XFERSIZ_MASK);
@@ -448,7 +448,7 @@ static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_us
if(eps->control & USB_EPCON_STALL)
{
eps->control &=~ USB_EPCON_STALL; // Should this be EP0 only
- printf("USB: Stall.\n");
+ //printf("USB: Stall.\n");
ret = USB_RET_STALL;
}
else if(eps->control & USB_EPCON_ENABLE)
@@ -468,7 +468,7 @@ static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_us
if(rxfz > sizeof(state->fifos))
hw_error("usb_synopsys: USB transfer would overflow FIFO buffer!\n");
- printf("USB: Starting OUT transfer on EP %d (%d)...\n", ep, amtDone);
+ //printf("USB: Starting OUT transfer on EP %d (%d)...\n", ep, amtDone);
if(amtDone > 0)
{
@@ -486,6 +486,7 @@ static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_us
if(_hdr->flags & tcp_usb_setup)
{
+ /*
printf("USB: Setup %02x %02x %02x %02x %02x %02x %02x %02x\n",
state->fifos[0],
state->fifos[1],
@@ -495,7 +496,7 @@ static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_us
state->fifos[5],
state->fifos[6],
state->fifos[7]);
-
+ */
eps->interrupt_status |= USB_EPINT_SetUp;
}
else
diff --git a/iemu.c b/iemu.c
new file mode 100644
index 000000000..87a243cb7
--- /dev/null
+++ b/iemu.c
@@ -0,0 +1,216 @@
+/*
+ * iEmu
+ *
+ * Written by cmw
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include
+#include "expat.h"
+#include
+#include
+
+#include "hw/boards.h"
+#include "iemu.h"
+
+const static int BUFFER_SIZE = 512;
+
+typedef struct dev_config
+{
+ char *devname;
+ char *skinfile;
+ char *bootname;
+ char *hwid;
+ uint8_t boottype;
+ uint32_t loadaddr;
+ char *fwver;
+} DevConfig;
+
+static DevConfig *curdev = NULL;
+const char *tagval = NULL;
+char fwpath[PATH_MAX];
+
+#define DEFAULT_DEVICE_PATH "devices/"
+
+static int iemu_parse_config(const char *deviceName, char *file);
+
+static inline int value_is(const char *attr, const char *name)
+{
+ return (strcasecmp(attr, name) == 0);
+}
+
+char *iemu_get_skin(void)
+{
+ if(curdev)
+ return curdev->skinfile;
+ return NULL;
+}
+
+void iemu_fw_list(const char *device)
+{
+ DIR *iemufwdir;
+ struct dirent *ep;
+
+ sprintf(fwpath, "%s%s", DEFAULT_DEVICE_PATH, device);
+ iemufwdir = opendir(fwpath);
+
+ if(iemufwdir != NULL)
+ {
+ printf("Available %s firmware versions\n", device);
+ while ((ep = readdir(iemufwdir)) != NULL)
+ {
+ if((strcmp(ep->d_name, ".") != 0) && (strcmp(ep->d_name, "..") != 0) && ep->d_type == DT_DIR)
+ {
+ printf("\tVersion: %s\n", ep->d_name);
+ }
+ }
+ closedir(iemufwdir);
+ } else {
+ fprintf(stderr, "Couldn't open firmware dir %s\n", fwpath);
+ }
+}
+
+int iemu_fw_load(const char *device, const char *iemuVersion)
+{
+ char dflist[PATH_MAX];
+ struct stat st;
+
+ /* Find default device config */
+ sprintf(dflist, "%s%s/config.xml", DEFAULT_DEVICE_PATH, device);
+ if(stat(dflist, &st) < 0)
+ return 0;
+
+ iemu_parse_config(device, dflist);
+
+ /* Check version */
+
+ return 1;
+}
+
+int iemu_fw_init(const char *optarg, const char *device)
+{
+/*
+ if(!iemu_fw_load(device, optarg))
+ return -1;
+*/
+ return 0;
+}
+
+static void parser_char_data (void *data, const XML_Char *s, int len)
+{
+ char *tmp;
+ int i, empty;
+ DevConfig *parserconfig = (DevConfig*)data;
+
+ assert(tmp = (char *) malloc(len+1));
+ strncpy(tmp, s, len);
+ tmp[len] = '\0';
+
+ for(i=0, empty=true; tmp[i]; i++)
+ {
+ if(!isspace(tmp[i]))
+ {
+ empty = false;
+ break;
+ }
+ }
+
+ if(empty || !tagval) {
+ free(tmp);
+ return;
+ }
+
+ if(value_is(tagval, "device"))
+ parserconfig->devname = strdup(tmp);
+
+ if(value_is(tagval, "hwid"))
+ parserconfig->hwid = strdup(tmp);
+
+ if(value_is(tagval, "skin")) {
+ sprintf(fwpath, "%s%s/%s", DEFAULT_DEVICE_PATH, parserconfig->devname, tmp);
+ parserconfig->skinfile = strdup(fwpath);
+ }
+
+ if(value_is(tagval, "boot")) {
+ parserconfig->bootname = strdup(tmp);
+ if(value_is(tmp, "iboot")) {
+ parserconfig->boottype = BOOT_TYPE_IBOOT;
+ }
+ if(value_is(tmp, "openiboot")) {
+ parserconfig->boottype = BOOT_TYPE_OPENIBOOT;
+ }
+ if(value_is(tmp, "vrom")) {
+ parserconfig->boottype = BOOT_TYPE_VROM;
+ }
+ }
+
+ if(value_is(tagval, "loadaddr"))
+ sscanf(tmp, "0x%08x", &parserconfig->loadaddr);
+
+ free(tmp);
+ tagval = NULL;
+}
+
+static void parser_start_hndl(void *data, const char *element, const char **attr)
+{
+ // make sure device is first tag
+ tagval = element;
+}
+
+static void parser_end_hndl(void *data, const char *element)
+{
+ // if device but no data error
+}
+
+static int iemu_parse_config(const char *deviceName, char *file)
+{
+ FILE* device_xml;
+ char buffer[BUFFER_SIZE];
+ int done;
+ XML_Parser parser = XML_ParserCreate(NULL);
+
+ assert(curdev = (DevConfig *) malloc(sizeof(DevConfig)));
+
+ if (parser) {
+ curdev->devname = strdup(deviceName);
+
+ XML_SetUserData(parser, (void*)curdev);
+ XML_SetCharacterDataHandler(parser, parser_char_data);
+ XML_SetElementHandler(parser, parser_start_hndl, parser_end_hndl);
+
+ device_xml = fopen(file, "r");
+ printf("device_xml: iemu_config_file = '%s'\n", file);
+ if (!device_xml) {
+ fprintf(stderr, "Error opening device config file '%s'\n", file);
+ XML_ParserFree(parser);
+ return -1;
+ }
+
+ do {
+ if (fgets(buffer, sizeof(buffer), device_xml) == NULL)
+ done = 1;
+ else {
+ done = feof(device_xml);
+ if (!XML_Parse(parser, buffer, strlen(buffer), done)) {
+ fprintf(stderr, "Parse error at line %d: %s\n",
+ (int)XML_GetCurrentLineNumber(parser),
+ XML_ErrorString(XML_GetErrorCode(parser)));
+ // Continue anyway
+ }
+ }
+ } while (!done);
+
+ if (done && !feof(device_xml)) {
+ fprintf(stderr, "Parse error, unexpected EOF\n");
+ // Continue anyway
+ }
+
+ XML_ParserFree(parser);
+
+ fclose(device_xml);
+ printf("bootname = %s, loadaddr = 0x%08x\n", curdev->bootname, curdev->loadaddr);
+ return 0;
+ }
+ return -1;
+}
diff --git a/iemu.h b/iemu.h
new file mode 100644
index 000000000..f42dbb92d
--- /dev/null
+++ b/iemu.h
@@ -0,0 +1,15 @@
+#ifndef IOS_FW_H
+#define IOS_FW_H
+
+typedef enum {
+ BOOT_TYPE_IBOOT = 1,
+ BOOT_TYPE_OPENIBOOT,
+ BOOT_TYPE_VROM
+} boot_type;
+
+void iemu_fw_list(const char *device);
+int iemu_fw_load(const char *deviceName, const char *iemuVersion);
+int iemu_fw_init(const char *optarg, const char *device);
+char *iemu_get_skin(void);
+
+#endif
diff --git a/qemu-options.hx b/qemu-options.hx
index 76cb4b41f..e264d10f7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -760,6 +760,15 @@ Enable/disable audio stream compression (using celt 0.5.1). Default is on.
@end table
ETEXI
+DEF("firmware", HAS_ARG, QEMU_OPTION_iosfirmware,
+ "-firmware iOS firmware version\n",
+ QEMU_ARCH_ARM)
+STEXI
+@item -firmware @var{firmware}
+@findex -firmware
+iOS firmware version
+ETEXI
+
DEF("portrait", 0, QEMU_OPTION_portrait,
"-portrait rotate graphical output 90 deg left (only PXA LCD)\n",
QEMU_ARCH_ALL)
diff --git a/skin/skin_config.c b/skin/skin_config.c
index fdbb8b9e5..0dfc42f55 100644
--- a/skin/skin_config.c
+++ b/skin/skin_config.c
@@ -171,8 +171,8 @@ int skin_activate_layout(SkinScreen* skin, int rotation)
if (layout->width == 0 || layout->height == 0) {
// No value given in XML, use some default
//printf("Default layout values\n");
- layout->width = 732;
- layout->height = 392;
+ layout->width = 320;
+ layout->height = 480;
}
if (layout->emuscreen_width == 0 || layout->emuscreen_height == 0) {
// No default value given, make it 800x480 then
diff --git a/vl.c b/vl.c
index 2a8b8b02b..75a3051fc 100644
--- a/vl.c
+++ b/vl.c
@@ -145,6 +145,8 @@ int main(int argc, char **argv)
#include "qemu-config.h"
#include "qemu-objects.h"
#include "qemu-options.h"
+#include "iemu.h"
+
#ifdef CONFIG_VIRTFS
#include "fsdev/qemu-fsdev.h"
#endif
@@ -2200,12 +2202,26 @@ int main(int argc, char **argv, char **envp)
exit(1);
#endif
break;
+ case QEMU_OPTION_iosfirmware:
+ if (*optarg == '?') {
+ iemu_fw_list(machine->name);
+ exit(0);
+ } else {
+ if(iemu_fw_init(optarg, machine->name) < 0)
+ {
+ fprintf(stderr, "Invalid firmware version %s for device %s\n", optarg, machine->name);
+ exit(0);
+ }
+ /* Load skin */
+ skin_file = iemu_get_skin();
+ }
+ break;
case QEMU_OPTION_portrait:
graphic_rotate = 1;
break;
- case QEMU_OPTION_landscape:
- graphic_rotate = 0;
- break;
+ case QEMU_OPTION_landscape:
+ graphic_rotate = 0;
+ break;
case QEMU_OPTION_kernel:
kernel_filename = optarg;
break;