/** \file * Minimal ML - for debugging */ #include "dryos.h" #include "vram.h" #include "bmp.h" #include "font_direct.h" /** These are called when new tasks are created */ static int my_init_task(int a, int b, int c, int d); /** This just goes into the bss */ #define RELOCSIZE 0x3000 // look in HIJACK macros for the highest address, and subtract ROMBASEADDR static uint8_t _reloc[ RELOCSIZE ]; #define RELOCADDR ((uintptr_t) _reloc) /** Translate a firmware address into a relocated address */ #define INSTR( addr ) ( *(uint32_t*)( (addr) - ROMBASEADDR + RELOCADDR ) ) /** Fix a branch instruction in the relocated firmware image */ #define FIXUP_BRANCH( rom_addr, dest_addr ) \ INSTR( rom_addr ) = BL_INSTR( &INSTR( rom_addr ), (dest_addr) ) /** Specified by the linker */ extern uint32_t _bss_start[], _bss_end[]; static inline void zero_bss( void ) { uint32_t *bss = _bss_start; while( bss < _bss_end ) *(bss++) = 0; } void __attribute__((noreturn,noinline,naked)) copy_and_restart( int offset ) { zero_bss(); // Copy the firmware to somewhere safe in memory const uint8_t * const firmware_start = (void*) ROMBASEADDR; const uint32_t firmware_len = RELOCSIZE; uint32_t * const new_image = (void*) RELOCADDR; blob_memcpy( new_image, firmware_start, firmware_start + firmware_len ); /* * in entry2() (0xff010134) make this change to * return to our code before calling cstart(). * This should be a "BL cstart" instruction. */ INSTR( HIJACK_INSTR_BL_CSTART ) = RET_INSTR; /* * in cstart() (0xff010ff4) make these changes: * calls bzero(), then loads bs_end and calls * create_init_task */ // Reserve memory after the BSS for our application INSTR( HIJACK_INSTR_BSS_END ) = (uintptr_t) _bss_end; // Fix the calls to bzero32() and create_init_task() FIXUP_BRANCH( HIJACK_FIXBR_BZERO32, bzero32 ); FIXUP_BRANCH( HIJACK_FIXBR_CREATE_ITASK, create_init_task ); // Set our init task to run instead of the firmware one INSTR( HIJACK_INSTR_MY_ITASK ) = (uint32_t) my_init_task; // Make sure that our self-modifying code clears the cache sync_caches(); // We enter after the signature, avoiding the // relocation jump that is at the head of the data thunk reloc_entry = (thunk)( RELOCADDR + 0xC ); reloc_entry(); /* * We're back! * The RAM copy of the firmware startup has: * 1. Poked the DMA engine with what ever it does * 2. Copied the rw_data segment to 0x1900 through 0x20740 * 3. Zeroed the BSS from 0x20740 through 0x47550 * 4. Copied the interrupt handlers to 0x0 * 5. Copied irq 4 to 0x480. * 6. Installed the stack pointers for CPSR mode D2 and D3 * (we are still in D3, with a %sp of 0x1000) * 7. Returned to us. * * Now is our chance to fix any data segment things, or * install our own handlers. */ // This will jump into the RAM version of the firmware, // but the last branch instruction at the end of this // has been modified to jump into the ROM version // instead. void (*ram_cstart)(void) = (void*) &INSTR( cstart ); ram_cstart(); // Unreachable while(1) ; } #if 0 /* ROM dumper */ extern FILE* _FIO_CreateFile(const char* filename ); /* this cannot run from init_task */ static void run_test() { /* change to A:/ for CF cards */ FILE * f = _FIO_CreateFile("B:/FF000000.BIN"); if (f != (void*) -1) { FIO_WriteFile(f, (void*) 0xFF000000, 0x1000000); FIO_CloseFile(f); } } #endif /** Initial task setup. * * This is called instead of the task at 0xFF811DBC. * It does all of the stuff to bring up the debug manager, * the terminal drivers, stdio, stdlib and armlib. */ static int my_init_task(int a, int b, int c, int d) { init_task(a,b,c,d); /* wait for display to initialize */ while (!bmp_vram_info[1].vram2) { msleep(100); } while(1) { MEM(CARD_LED_ADDRESS) = LEDON; msleep(500); MEM(CARD_LED_ADDRESS) = LEDOFF; msleep(500); font_draw(100, 75, COLOR_WHITE, 3, "Hello, World!"); } return 0; } /* used by font_draw */ void disp_set_pixel(int x, int y, int c) { uint8_t* bmp = bmp_vram_info[1].vram2; bmp[x + y * 960] = c; }