| 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 | }
|