| Index: embios/trunk/init.c | 
| — | — | @@ -44,6 +44,9 @@ | 
| 45 | 45 | #include "disk.h" | 
| 46 | 46 | #include "file.h" | 
| 47 | 47 | #endif | 
|  | 48 | +#ifdef HAVE_BOOTFLASH | 
|  | 49 | +#include "bootflash.h" | 
|  | 50 | +#endif | 
| 48 | 51 |  | 
| 49 | 52 |  | 
| 50 | 53 | struct bootinfo_t | 
| — | — | @@ -58,7 +61,7 @@ | 
| 59 | 62 | bool bootflashflags; | 
| 60 | 63 | bool trymemmapped; | 
| 61 | 64 | void* memmappedaddr; | 
| 62 |  | -    uint32_t memmappedsize;
 | 
|  | 65 | +    int memmappedsize; | 
| 63 | 66 | bool memmappedflags; | 
| 64 | 67 | }; | 
| 65 | 68 |  | 
| — | — | @@ -86,12 +89,13 @@ | 
| 87 | 90 | { | 
| 88 | 91 | int fd = file_open(bootinfo.dataflashpath, O_RDONLY); | 
| 89 | 92 | if (fd < 0) goto dataflashfailed; | 
| 90 |  | -        uint32_t size = filesize(fd);
 | 
|  | 93 | +        int size = filesize(fd); | 
|  | 94 | +        if (size < 0) goto dataflashfailed; | 
| 91 | 95 | if (bootinfo.dataflashflags & 1) | 
| 92 | 96 | { | 
| 93 | 97 | void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1)); | 
| 94 | 98 | if (read(fd, addr, size) != size) goto dataflashfailed; | 
| 95 |  | -            if (ucl_decompress(addr, size, &_initstart, &size)) goto dataflashfailed;
 | 
|  | 99 | +            if (ucl_decompress(addr, size, &_initstart, (uint32_t*)&size)) goto dataflashfailed; | 
| 96 | 100 | } | 
| 97 | 101 | else if (read(fd, &_initstart, size) != size) goto dataflashfailed; | 
| 98 | 102 | if (execimage(&_initstart) < 0) return; | 
| — | — | @@ -101,13 +105,14 @@ | 
| 102 | 106 | #ifdef HAVE_BOOTFLASH | 
| 103 | 107 | if (bootinfo.trybootflash) | 
| 104 | 108 | { | 
| 105 |  | -        uint32_t size = bootflash_filesize(bootinfo.bootimagename);
 | 
|  | 109 | +        int size = bootflash_filesize(bootinfo.bootimagename); | 
| 106 | 110 | if (size < 0) goto bootflashfailed; | 
| 107 | 111 | #ifdef BOOTFLASH_IS_MEMMAPPED | 
| 108 | 112 | void* addr = bootflash_getaddr(bootinfo.bootimagename); | 
|  | 113 | +        if (!addr) goto bootflashfailed; | 
| 109 | 114 | if (bootinfo.bootflashflags & 1) | 
| 110 | 115 | { | 
| 111 |  | -            if (ucl_decompress(addr, size, &_initstart, &size)) goto bootflashfailed;
 | 
|  | 116 | +            if (ucl_decompress(addr, size, &_initstart, (uint32_t*)&size)) goto bootflashfailed; | 
| 112 | 117 | if (execimage(&_initstart) < 0) return; | 
| 113 | 118 | } | 
| 114 | 119 | else if (bootinfo.bootflashflags & 2) | 
| — | — | @@ -120,10 +125,12 @@ | 
| 121 | 126 | if (bootinfo.bootflashflags & 1) | 
| 122 | 127 | { | 
| 123 | 128 | void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1)); | 
| 124 |  | -            bootflash_read(bootinfo.bootimagename, addr, 0, size);
 | 
| 125 |  | -            if (ucl_decompress(addr, size, &_initstart, &size)) goto bootflashfailed;
 | 
|  | 129 | +            if (bootflash_read(bootinfo.bootimagename, addr, 0, size) != size) | 
|  | 130 | +                goto bootflashfailed; | 
|  | 131 | +            if (ucl_decompress(addr, size, &_initstart, (uint32_t*)&size)) goto bootflashfailed; | 
| 126 | 132 | } | 
| 127 |  | -        else bootflash_read(bootinfo.bootimagename, &_initstart, 0, size);
 | 
|  | 133 | +        else if (bootflash_read(bootinfo.bootimagename, &_initstart, 0, size) != size) | 
|  | 134 | +            goto bootflashfailed; | 
| 128 | 135 | if (execimage(&_initstart) < 0) return; | 
| 129 | 136 | #endif | 
| 130 | 137 | } | 
| — | — | @@ -131,10 +138,10 @@ | 
| 132 | 139 | #endif | 
| 133 | 140 | if (bootinfo.trymemmapped) | 
| 134 | 141 | { | 
| 135 |  | -        uint32_t size = bootinfo.memmappedsize;
 | 
|  | 142 | +        int size = bootinfo.memmappedsize; | 
| 136 | 143 | if (bootinfo.bootflashflags & 1) | 
| 137 | 144 | { | 
| 138 |  | -            if (ucl_decompress(bootinfo.memmappedaddr, size, &_initstart, &size))
 | 
|  | 145 | +            if (ucl_decompress(bootinfo.memmappedaddr, size, &_initstart, (uint32_t*)&size)) | 
| 139 | 146 | goto memmappedfailed; | 
| 140 | 147 | if (execimage(&_initstart) < 0) return; | 
| 141 | 148 | } | 
| Index: embios/trunk/SOURCES | 
| — | — | @@ -12,6 +12,7 @@ | 
| 13 | 13 | target/ipodnano2g/ftl.c | 
| 14 | 14 | target/ipodnano2g/storage_nand.c | 
| 15 | 15 | target/ipodnano2g/clockgates.c | 
|  | 16 | +target/ipodnano2g/bootflash.c | 
| 16 | 17 | usb/synopsysotg.c | 
| 17 | 18 | #endif | 
| 18 | 19 |  | 
| Index: embios/trunk/target/ipodnano2g/bootflash.c | 
| — | — | @@ -0,0 +1,129 @@ | 
|  | 2 | +// | 
|  | 3 | +// | 
|  | 4 | +//    Copyright 2010 TheSeven | 
|  | 5 | +// | 
|  | 6 | +// | 
|  | 7 | +//    This file is part of emBIOS. | 
|  | 8 | +// | 
|  | 9 | +//    emBIOS is free software: you can redistribute it and/or | 
|  | 10 | +//    modify it under the terms of the GNU General Public License as | 
|  | 11 | +//    published by the Free Software Foundation, either version 2 of the | 
|  | 12 | +//    License, or (at your option) any later version. | 
|  | 13 | +// | 
|  | 14 | +//    emBIOS is distributed in the hope that it will be useful, | 
|  | 15 | +//    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 16 | +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|  | 17 | +//    See the GNU General Public License for more details. | 
|  | 18 | +// | 
|  | 19 | +//    You should have received a copy of the GNU General Public License along | 
|  | 20 | +//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 21 | +// | 
|  | 22 | +// | 
|  | 23 | + | 
|  | 24 | + | 
|  | 25 | +#include "global.h" | 
|  | 26 | +#include "bootflash.h" | 
|  | 27 | +#include "contextswitch.h" | 
|  | 28 | +#include "util.h" | 
|  | 29 | + | 
|  | 30 | + | 
|  | 31 | +#define nor ((uint8_t*)0x24000000) | 
|  | 32 | +#define norword ((uint32_t*)0x24000000) | 
|  | 33 | +#define norflsh ((volatile uint16_t*)0x24000000) | 
|  | 34 | + | 
|  | 35 | + | 
|  | 36 | +extern void control_nor_cache(bool enable); | 
|  | 37 | + | 
|  | 38 | + | 
|  | 39 | +static void* findflashfile(const char* filename, uint32_t* size) | 
|  | 40 | +{ | 
|  | 41 | +    uint32_t i; | 
|  | 42 | +    for (i = 0; i < 0x1000; i += 0x10) | 
|  | 43 | +        if (memcmp(&nor[i], filename, 8) == 0) | 
|  | 44 | +        { | 
|  | 45 | +            *size = norword[(i + 0xc) >> 2]; | 
|  | 46 | +            return &nor[norword[(i + 0x8) >> 2]]; | 
|  | 47 | +        } | 
|  | 48 | +    return 0; | 
|  | 49 | +} | 
|  | 50 | + | 
|  | 51 | +int bootflash_filesize(const char* filename) | 
|  | 52 | +{ | 
|  | 53 | +    uint32_t size; | 
|  | 54 | +    if (findflashfile(filename, &size)) return size & 0xfffff; | 
|  | 55 | +    else return -1; | 
|  | 56 | +} | 
|  | 57 | + | 
|  | 58 | +int bootflash_attributes(const char* filename) | 
|  | 59 | +{ | 
|  | 60 | +    uint32_t size; | 
|  | 61 | +    if (findflashfile(filename, &size)) return size >> 20; | 
|  | 62 | +    else return -1; | 
|  | 63 | +} | 
|  | 64 | + | 
|  | 65 | +void* bootflash_getaddr(const char* filename) | 
|  | 66 | +{ | 
|  | 67 | +    uint32_t size; | 
|  | 68 | +    return findflashfile(filename, &size); | 
|  | 69 | +} | 
|  | 70 | + | 
|  | 71 | +int bootflash_read(const char* filename, void* addr, int offset, int size) | 
|  | 72 | +{ | 
|  | 73 | +    uint32_t fsize; | 
|  | 74 | +    uint8_t* file = (uint8_t*)findflashfile(filename, &fsize); | 
|  | 75 | +    if (!file) return -1; | 
|  | 76 | +    fsize &= 0xfffff; | 
|  | 77 | +    if (offset + size > fsize) size = fsize - offset; | 
|  | 78 | +    if (size > 0) memcpy(addr, &file[offset], size); | 
|  | 79 | +    return size; | 
|  | 80 | +} | 
|  | 81 | + | 
|  | 82 | +void bootflash_readraw(void* addr, int offset, int size) | 
|  | 83 | +{ | 
|  | 84 | +    memcpy(addr, &nor[offset], size); | 
|  | 85 | +} | 
|  | 86 | + | 
|  | 87 | +void bootflash_writeraw(void* addr, int offset, int size) | 
|  | 88 | +{ | 
|  | 89 | +    uint32_t mode = enter_critical_section(); | 
|  | 90 | +    control_nor_cache(false); | 
|  | 91 | + | 
|  | 92 | +    while (size > 0) | 
|  | 93 | +    { | 
|  | 94 | +        int remainder = MIN(0x1000 - (offset & 0xfff), size); | 
|  | 95 | +        if (memcmp(&nor[offset], addr, remainder)) | 
|  | 96 | +        { | 
|  | 97 | +            bool needserase = false; | 
|  | 98 | +            int i; | 
|  | 99 | +            for (i = 0; i < remainder; i += 2) | 
|  | 100 | +                if (norflsh[(offset + i) >> 1] != 0xffff) | 
|  | 101 | +                    needserase = true; | 
|  | 102 | +            if (needserase) | 
|  | 103 | +            { | 
|  | 104 | +                norflsh[0x5555] = 0xaa; | 
|  | 105 | +                norflsh[0x2aaa] = 0x55; | 
|  | 106 | +                norflsh[0x5555] = 0x80; | 
|  | 107 | +                norflsh[0x5555] = 0xaa; | 
|  | 108 | +                norflsh[0x2aaa] = 0x55; | 
|  | 109 | +                norflsh[(offset & ~0xfff) >> 1] = 0x30; | 
|  | 110 | +                while (norflsh[(offset & ~0xfff) >> 1] != 0xffff); | 
|  | 111 | +            } | 
|  | 112 | +            norflsh[0x5555] = 0xaa; | 
|  | 113 | +            norflsh[0x2aaa] = 0x55; | 
|  | 114 | +            norflsh[0x5555] = 0xa0; | 
|  | 115 | +            norflsh[offset >> 1] = ((uint16_t*)addr)[offset >> 1]; | 
|  | 116 | +            while (norflsh[offset >> 1] != ((uint16_t*)addr)[offset >> 1]); | 
|  | 117 | +        } | 
|  | 118 | +        addr = (void*)(((uint32_t)addr) + remainder); | 
|  | 119 | +        offset += remainder; | 
|  | 120 | +        size -= remainder; | 
|  | 121 | +    } | 
|  | 122 | + | 
|  | 123 | +    control_nor_cache(true); | 
|  | 124 | +    leave_critical_section(mode); | 
|  | 125 | +} | 
|  | 126 | + | 
|  | 127 | +void* bootflash_getrawaddr(int offset) | 
|  | 128 | +{ | 
|  | 129 | +    return &nor[offset]; | 
|  | 130 | +} | 
| Index: embios/trunk/target/ipodnano2g/bootflash.h | 
| — | — | @@ -0,0 +1,40 @@ | 
|  | 2 | +// | 
|  | 3 | +// | 
|  | 4 | +//    Copyright 2010 TheSeven | 
|  | 5 | +// | 
|  | 6 | +// | 
|  | 7 | +//    This file is part of emBIOS. | 
|  | 8 | +// | 
|  | 9 | +//    emBIOS is free software: you can redistribute it and/or | 
|  | 10 | +//    modify it under the terms of the GNU General Public License as | 
|  | 11 | +//    published by the Free Software Foundation, either version 2 of the | 
|  | 12 | +//    License, or (at your option) any later version. | 
|  | 13 | +// | 
|  | 14 | +//    emBIOS is distributed in the hope that it will be useful, | 
|  | 15 | +//    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 16 | +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|  | 17 | +//    See the GNU General Public License for more details. | 
|  | 18 | +// | 
|  | 19 | +//    You should have received a copy of the GNU General Public License along | 
|  | 20 | +//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 21 | +// | 
|  | 22 | +// | 
|  | 23 | + | 
|  | 24 | + | 
|  | 25 | +#ifndef __BOOTFLASH_H__ | 
|  | 26 | +#define __BOOTFLASH_H__ | 
|  | 27 | + | 
|  | 28 | + | 
|  | 29 | +#include "global.h" | 
|  | 30 | + | 
|  | 31 | + | 
|  | 32 | +int bootflash_filesize(const char* filename); | 
|  | 33 | +int bootflash_attributes(const char* filename); | 
|  | 34 | +void* bootflash_getaddr(const char* filename); | 
|  | 35 | +int bootflash_read(const char* filename, void* addr, int offset, int size); | 
|  | 36 | +void bootflash_readraw(void* addr, int offset, int size); | 
|  | 37 | +void bootflash_writeraw(void* addr, int offset, int size); | 
|  | 38 | +void* bootflash_getrawaddr(int offset); | 
|  | 39 | + | 
|  | 40 | + | 
|  | 41 | +#endif | 
| Index: embios/trunk/target/ipodnano2g/crt0.S | 
| — | — | @@ -216,3 +216,42 @@ | 
| 217 | 217 |  | 
| 218 | 218 | val_3c700000: | 
| 219 | 219 | .word	0x3c700000 | 
|  | 220 | + | 
|  | 221 | + | 
|  | 222 | +.section .text.control_nor_cache, "ax", %progbits | 
|  | 223 | +.align 2 | 
|  | 224 | +.global control_nor_cache | 
|  | 225 | +.type control_nor_cache, %function | 
|  | 226 | +control_nor_cache: | 
|  | 227 | +	mrc	p15, 0, r3,c1,c0 | 
|  | 228 | +	bic	r1, r3, #1 | 
|  | 229 | +	mcr	p15, 0, r1,c1,c0 | 
|  | 230 | +	mov	r1, #0 | 
|  | 231 | +	mcr	p15, 0, r1,c7,c5 | 
|  | 232 | +cnc_flushcache_loop: | 
|  | 233 | +	mcr	p15, 0, r1,c7,c14,2 | 
|  | 234 | +	add	r2, r1, #0x10 | 
|  | 235 | +	mcr	p15, 0, r2,c7,c14,2 | 
|  | 236 | +	add	r2, r2, #0x10 | 
|  | 237 | +	mcr	p15, 0, r2,c7,c14,2 | 
|  | 238 | +	add	r2, r2, #0x10 | 
|  | 239 | +	mcr	p15, 0, r2,c7,c14,2 | 
|  | 240 | +	adds	r1, r1, #0x04000000 | 
|  | 241 | +	bne	cnc_flushcache_loop | 
|  | 242 | +	mcr	p15, 0, r1,c7,c10,4 | 
|  | 243 | +	ands	r0, r0, r0 | 
|  | 244 | +	mrc	p15, 0, r1,c2,c0, 1 | 
|  | 245 | +	biceq	r1, r1, #0x10 | 
|  | 246 | +	orrne	r1, r1, #0x10 | 
|  | 247 | +	mcr	p15, 0, r1,c2,c0, 1 | 
|  | 248 | +	mrc	p15, 0, r1,c2,c0, 0 | 
|  | 249 | +	biceq	r1, r1, #0x10 | 
|  | 250 | +	orrne	r1, r1, #0x10 | 
|  | 251 | +	mcr	p15, 0, r1,c2,c0, 0 | 
|  | 252 | +	mrc	p15, 0, r1,c3,c0, 0 | 
|  | 253 | +	biceq	r1, r1, #0x10 | 
|  | 254 | +	orrne	r1, r1, #0x10 | 
|  | 255 | +	mcr	p15, 0, r1,c3,c0, 0 | 
|  | 256 | +	mcr	p15, 0, r3,c1,c0 | 
|  | 257 | +	mov	pc, lr | 
|  | 258 | +.size control_nor_cache, .-control_nor_cache | 
| Index: embios/trunk/target/ipodnano2g/target.h | 
| — | — | @@ -44,6 +44,9 @@ | 
| 45 | 45 |  | 
| 46 | 46 | #define HAVE_I2C | 
| 47 | 47 |  | 
|  | 48 | +#define HAVE_BOOTFLASH | 
|  | 49 | +#define BOOTFLASH_IS_MEMMAPPED | 
|  | 50 | + | 
| 48 | 51 | #define HAVE_STORAGE | 
| 49 | 52 | #define HAVE_FLASH_STORAGE | 
| 50 | 53 | #define HAVE_STORAGE_FLUSH | 
| Index: embios/trunk/usb/usb.c | 
| — | — | @@ -37,6 +37,9 @@ | 
| 38 | 38 | #ifdef HAVE_I2C | 
| 39 | 39 | #include "i2c.h" | 
| 40 | 40 | #endif | 
|  | 41 | +#ifdef HAVE_BOOTFLASH | 
|  | 42 | +#include "bootflash.h" | 
|  | 43 | +#endif | 
| 41 | 44 |  | 
| 42 | 45 |  | 
| 43 | 46 | static uint8_t ctrlresp[2] CACHEALIGN_ATTR; | 
| — | — | @@ -55,7 +58,9 @@ | 
| 56 | 59 | DBGACTION_CWRITE, | 
| 57 | 60 | DBGACTION_CREAD, | 
| 58 | 61 | DBGACTION_CFLUSH, | 
| 59 |  | -    DBGACTION_EXECIMAGE
 | 
|  | 62 | +    DBGACTION_EXECIMAGE, | 
|  | 63 | +    DBGACTION_READBOOTFLASH, | 
|  | 64 | +    DBGACTION_WRITEBOOTFLASH | 
| 60 | 65 | }; | 
| 61 | 66 |  | 
| 62 | 67 | static uint32_t dbgstack[0x100] STACK_ATTR; | 
| — | — | @@ -65,6 +70,7 @@ | 
| 66 | 71 | static int dbgi2cbus; | 
| 67 | 72 | static int dbgi2cslave; | 
| 68 | 73 | static int dbgactionaddr; | 
|  | 74 | +static int dbgactionoffset; | 
| 69 | 75 | static int dbgactionlength; | 
| 70 | 76 | static int dbgactionconsoles; | 
| 71 | 77 | static int dbgactiontype; | 
| — | — | @@ -513,6 +519,20 @@ | 
| 514 | 520 | if (set_dbgaction(DBGACTION_EXECIMAGE, 0)) break; | 
| 515 | 521 | dbgactionaddr = dbgrecvbuf[1]; | 
| 516 | 522 | break; | 
|  | 523 | +#ifdef HAVE_BOOTFLASH | 
|  | 524 | +        case 22:  // READ BOOT FLASH | 
|  | 525 | +            if (set_dbgaction(DBGACTION_READBOOTFLASH, 0)) break; | 
|  | 526 | +            dbgactionaddr = dbgrecvbuf[1]; | 
|  | 527 | +            dbgactionoffset = dbgrecvbuf[2]; | 
|  | 528 | +            dbgactionlength = dbgrecvbuf[3]; | 
|  | 529 | +            break; | 
|  | 530 | +        case 23:  // WRITE BOOT FLASH | 
|  | 531 | +            if (set_dbgaction(DBGACTION_WRITEBOOTFLASH, 0)) break; | 
|  | 532 | +            dbgactionaddr = dbgrecvbuf[1]; | 
|  | 533 | +            dbgactionoffset = dbgrecvbuf[2]; | 
|  | 534 | +            dbgactionlength = dbgrecvbuf[3]; | 
|  | 535 | +            break; | 
|  | 536 | +#endif | 
| 517 | 537 | default: | 
| 518 | 538 | dbgsendbuf[0] = 2; | 
| 519 | 539 | size = 16; | 
| — | — | @@ -601,6 +621,18 @@ | 
| 602 | 622 | dbgasyncsendbuf[1] = execimage((void*)dbgactionaddr); | 
| 603 | 623 | usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16); | 
| 604 | 624 | break; | 
|  | 625 | +#ifdef HAVE_BOOTFLASH | 
|  | 626 | +            case DBGACTION_READBOOTFLASH: | 
|  | 627 | +                bootflash_readraw((void*)dbgactionaddr, dbgactionoffset, dbgactionlength); | 
|  | 628 | +                dbgasyncsendbuf[0] = 1; | 
|  | 629 | +                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16); | 
|  | 630 | +                break; | 
|  | 631 | +            case DBGACTION_WRITEBOOTFLASH: | 
|  | 632 | +                bootflash_writeraw((void*)dbgactionaddr, dbgactionoffset, dbgactionlength); | 
|  | 633 | +                dbgasyncsendbuf[0] = 1; | 
|  | 634 | +                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16); | 
|  | 635 | +                break; | 
|  | 636 | +#endif | 
| 605 | 637 | } | 
| 606 | 638 | dbgaction = DBGACTION_IDLE; | 
| 607 | 639 | } |