📄 linuxld.c
字号:
buart_print("\r\njump to linux code!!\r\n"); funcptr(); } else { buart_print(fail); buart_nl(); } }}/* I really, really, really wanted to use this but it doesn't work all the time. */#if 0void boot_linux_new(){ int status; void (*funcptr) (void); /* MOST TEMPORARY !!! */ char buf[32]; /* Bring into line with Hawking32k_loader.idb "Run_Linux" function */ volatile unsigned long *gpio_conf0, *gpio_conf2; volatile unsigned char *extio1, *flash_addr, *test_addr = 0; int offset, gzinput_len, gzoutput_len = 0; gpio_conf0 = (unsigned long *) (PA2VA(ADM5120_SWCTRL_BASE) + GPIO_conf0_REG); gpio_conf2 = (unsigned long *) (PA2VA(ADM5120_SWCTRL_BASE) + GPIO_conf2_REG); flash_addr = (unsigned char *) PA2VA(ADM5120_SMEM0_BASE); // same definition as LINUXLD_NORFLASH_LOADER_START extio1 = (unsigned char *) PA2VA(ADM5120_EXTIO1_BASE); /* Find CSYS section on flash device */ for (offset = 0x10000; offset < 0x50000; offset += 0x10000) { test_addr = flash_addr + offset; if (memcmp((void *) test_addr, "CSYS", 4) == 0) break; else buart_print("\r\nno sys signature found!!\r\n"); } if (offset < 0x50000) { /* Found CSYS The admboot code copies the flash section to RAM and then deflates it. The Hawking code deflates the data directly from FLASH to RAM. */ /* CSYS wrapper has 2 extra bytes at the end */ gzinput_len = ((IMG_HEADER_Tp) test_addr)->len; /* The length of the ungzipped data is found in the last 4 bytes of the stream which may not be word-aligned. Here, status is used as a loop counter. */ for (status = 3; status < 7; status++) gzoutput_len = 256 * gzoutput_len + test_addr[12 + gzinput_len - status];// CORRECT// ultoa((unsigned long) gzoutput_len, buf);// buart_print("\r\nUncompressed length: ");// buart_print(buf);// buart_print("\r\n"); if (gzoutput_len <= (int) LINUXLD_KERNEL_SIZE) { buart_print("\r\ninflate linux code... "); /* Make use of the Tiny Inflate Library Copyright 2003 by Joergen Ibsen, All Rights Reserved, found at http://www.ibsensoftware.com */ tinf_init(); /* The Hawking routine Unzip_Deflate_ uses a destination address of 0xA0002000 which is the same thing as LINUXLD_KERNEL_START so we'll use that here. The Hawking code also ignores the return code but we don't want to do that. FYI & BTW... TINF_DATA_ERROR = -3 = 0xFFFFFFFD NOTE: CSYS wrapper has 2 extra bytes at the end */ status = tinf_gzip_uncompress((unsigned char *) LINUXLD_KERNEL_START, &gzoutput_len, (unsigned char *) test_addr + 12, gzinput_len - 2); if (status == TINF_OK) { /* PASS */ buart_print(pass); buart_print("\r\njump to linux code!!\r\n"); funcptr = (void *) LINUX_ENTRY_POINT; /* This is in nor_ldrinit.S */ _icache_sync_all(); /* From Hawking32k_loader.idb. The ADM5120 datasheet says bits 15:8 are read-only and bits 7:0 are "reserved" so this is really strange. The actual result of this should be to enable GPIO 0:7 for output and set them all to 0, except for GPIO 5 which is set to 1. */ *gpio_conf0 = (GPIO0_INPUT_MODE | GPIO0_INPUT_MASK | GPIO1_INPUT_MASK | GPIO2_INPUT_MASK | GPIO3_INPUT_MASK | GPIO4_INPUT_MASK | GPIO5_INPUT_MASK | GPIO6_INPUT_MASK | GPIO7_INPUT_MASK | GPIO0_OUTPUT_EN | GPIO1_OUTPUT_EN | GPIO2_OUTPUT_EN | GPIO3_OUTPUT_EN | GPIO4_OUTPUT_EN | GPIO5_OUTPUT_EN | GPIO6_OUTPUT_EN | GPIO7_OUTPUT_EN | GPIO5_OUTPUT_HI); /* From Hawking32k_loader.idb. No freaking idea what it does. */ *extio1 = 0xFF; /* Invoke the function pointer which never returns */ funcptr(); } else { /* FAIL */ buart_print(fail); buart_print("\r\n"); } } else buart_print("\r\nuncompressed size too big!!\r\n"); } else { /* The Hawking bootloader (Hawking32k_loader.idb) code does some strange things if CSYS can't be found. GPIO and EXTIO registers are manipulated as if to search another Flash chip. Or something like that. It also appears as though there's no exit from the code that runs if CSYS isn't found in the first 256K bytes of the flash. Here, nothing fancy like that. Just don't do anything and go back to the menu. */ }}#endif/* * Decompress function */int ungzip(unsigned char *zimg){ int i, err, gzflags; z_stream d_stream; // decompression stream if ( (zimg[0] != gz_magic[0]) || (zimg[1] != gz_magic[1]) || (zimg[2] != Z_DEFLATED)) return (Z_DATA_ERROR); gzflags = zimg[3]; // Skip the gzip header zimg += 10; if ((gzflags & EXTRA_FIELD) != 0) { /* skip the extra field */ i = (*zimg++) + (*zimg++) << 8; while ((i-- != 0) && (*zimg++) != Z_EOF) ; } if ((gzflags & ORIG_NAME) != 0) { /* skip the original file name */ while (*zimg++ != Z_EOF) ; } if ((gzflags & COMMENT) != 0) { /* skip the .gz file comment */ while (*zimg++ != Z_EOF) ; } if ((gzflags & HEAD_CRC) != 0) { /* skip the header crc */ zimg += 2; } /* Decompress the image */ d_stream.zalloc = NULL; d_stream.zfree = NULL; d_stream.opaque = (voidpf) 0; d_stream.next_in = zimg; // address of compressed image d_stream.avail_in = LINUX_IMAGE_SIZE; // size of compressed image /* Size can vary but this is the maximum: 0x3E0000, a shade under 4 MB */ if ((err = inflateInit2(&d_stream, -MAX_WBITS)) != Z_OK) return err; d_stream.next_out = (char *) LINUXLD_KERNEL_START; // address of decompressed data A000_2000 (typ) d_stream.avail_out = LINUXLD_KERNEL_SIZE; // size of decompress space 005F_E000 (typ) if ((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_STREAM_END) return err; err = inflateEnd(&d_stream); return err;}/* * Decompress function with destination specified */int ungzip_to(unsigned char *dst, unsigned char *zimg){ int i, err, gzflags; z_stream d_stream; if ((zimg[0] != gz_magic[0]) || (zimg[1] != gz_magic[1]) || (zimg[2] != Z_DEFLATED)) return (Z_DATA_ERROR); gzflags = zimg[3]; zimg += 10; // skip gzip header if ((gzflags & EXTRA_FIELD) != 0) { i = (*zimg++) + (*zimg++) << 8; // skip extra field while ((i-- != 0) && (*zimg++) != Z_EOF) ; } if ((gzflags & ORIG_NAME) != 0) { while (*zimg++ != Z_EOF) // skip original file name ; } if ((gzflags & COMMENT) != 0) { while (*zimg++ != Z_EOF) // skip comment ; } if ((gzflags & HEAD_CRC) != 0) { zimg += 2; // skip header crc } /* Decompress the image */ d_stream.zalloc = NULL; d_stream.zfree = NULL; d_stream.opaque = (voidpf) 0; d_stream.next_in = zimg; // address of compressed image d_stream.avail_in = LINUX_IMAGE_SIZE; // size of compressed image /* Size can vary but this is the maximum: 0x3E0000, a shade under 4 MB */ if ((err = inflateInit2(&d_stream, -MAX_WBITS)) != Z_OK) return err; d_stream.next_out = (char *) dst; // address of decompressed data d_stream.avail_out = LINUXLD_KERNEL_SIZE; // size of decompress space 005F_E000 (typ) if ((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_STREAM_END) return err; err = inflateEnd(&d_stream); return err;}/* * Find original name of gzipped file */char *gzip_original_name(unsigned char *zimg){ char *pname = 0; int i, gzflags; if ((zimg[0] == gz_magic[0]) && (zimg[1] == gz_magic[1]) && (zimg[2] == Z_DEFLATED)) { gzflags = zimg[3]; /* Skip the gzip header */ zimg += 10; if ((gzflags & EXTRA_FIELD) != 0) { /* Skip the extra field */ i = (*zimg++) + (*zimg++) << 8; while ((i-- != 0) && (*zimg++) != Z_EOF) ; } if ((gzflags & ORIG_NAME) != 0) { /* Here's the original file name */ pname = (char *) zimg; } } return pname;}/* * Because there is no OS support, the memory management functions in * STD C library can't be used. To overcome this problem, a very * simple memory management scheme is implemented here. * * Yeah, twice. This uses LINUXLD_GZIP_HEAP for its base address * while the routines in memlib.c use "_heap_h" which is initialized * to LINUXLD_MEMPOOL_START. * * LINUXLD_MEMPOOL_START is around 6 MB * LINUXLD_GZIP_HEAP is around 12 MB */void * calloc(size_t items, size_t size){ size_t memsize = items * size; size_t bkstart; /* Make sure the memory block is always aligned on a 4-byte boundary */ if (loader_heap & 0x03) loader_heap = (loader_heap + 3) & ~0x03; bkstart = loader_heap; // Allocate right at the current heap pointer loader_heap += memsize; // Bump the heap pointer return (void *) bkstart;}void * malloc(size_t size){ return calloc(1, size);}/* * Dummy 'free' function means nothing is ever really freed */void free(void *ptr){ return;}/* * Jump to no-flash upper 2MB - DE - Huh? */void jump_up_map(){ int i; /* Set GPIO[3](CS) to high */ for (i = 0; i < 10000; i++) // 10 thousand ; ADM5120_SW_REG(GPIO_conf0_REG) = 0x080800F7; for (i = 0; i < 10000; i++) // 10 thousand ;}/* * Jump to no-flash upper 2MB - DE - Say what? */ void jump_low_map(){ int i; /* Set GPIO[3](CS) to low */ for (i = 0; i < 10000; i++) // 10 thousand ; // DE - This is fucked up. Bits 0-7 are GPIO[0:7] input or output // and FF sets them for input. Bits 8 and 9 are READ ONLY so this // makes absolutely no fucking sense whatsoever. ADM5120_SW_REG(GPIO_conf0_REG) = 0x3FF; for (i = 0; i < 10000; i++) // 10 thousand ;}/* * Update 64K Security Sector on MX29LV320B devices */void update_ss(){ char *image = (char *) calloc(MX29LV_SECSEC_SIZE, 1); int len; /* Download new Security Sector contents to memory using Xmodem */ buart_print(xdownloading); if ((len = xmodem(image, MX29LV_SECSEC_SIZE)) > 0) { buart_print (pass); show_dlinfo((UINT32) image, len); /* Erase and re-program the flash security sector */ if (mx29lv320_update_ss(image, len) == 1) buart_print("\r\n\r\nSecurity Sector updated!!"); else buart_print("\r\n\r\nSecurity Sector NOT updated!!"); }} /* * LINUXLD_DOWNLOAD_START defined as * LINUXLD_LOADER_START A0800000 * defined as * LINUXLD_MEMPOOL_START A0600000 * defined as * LINUXLD_KERNEL_START A0002000 * defined as * LINUXLD_SDRAM_START A0000000 * defined as * PA2VA(ADM5120_SDRAM_BASE) * = PA2VA(0) * = 0 + A0000000 * + LINUXLD_EXCEP_SIZE 00002000 * + LINUXLD_KERNEL_SIZE 005FE000 * defined as * 00600000 - LINUXLD_EXCEP_SIZE * = 00600000 - 00002000 * = 005FE000 * + LINUXLD_MEMPOOL_SIZE 00200000 * + LINUXLD_LOADER_SIZE 00020000 * + LINUXLD_RESERVE_SIZE 00000000 * ---------------------------------------------------------------------- * LINUXLD_DOWNLOAD_START A0820000 Kseg1 * 80820000 Kseg0 * 00820000 Kuseg *//* dl_run_plugin This routine downloads a "plugin" via TFTP and runs it. A "plugin" program must be a self-contained subroutine that is gzipped and wrapped in a CSYS header. It is downloaded to the usual location at LINUXLD_DOWNLOAD_START (0082_0000) and gunzipped to the "startAddr" location of its IMG_HEADER_T, which must also be its entry point. If the plugin wants to return to the menu it should save the $gp register on entry and restore it before returning to the caller. */void dl_run_plugin(){ char *image = (char *) LINUXLD_DOWNLOAD_START; UINT32 len; /* Present the current network parameters and, after allowing for changes, continue only if they are acceptable to the user. */ if (tftp_client_menu("PLUGIN")) { buart_print(tdownloading); if ((len = tftpc(image, LINUX_IMAGE_SIZE)) > 0) { int status, offset, gzinput_len, gzoutput_len = 0, is_linux = 0; buart_print (pass); show_dlinfo((UINT32) image, len); buart_nl(); /* In order to continue there needs to be a CSYS section at the very start of the transferred data. */ if (memcmp((void *) image, "CSYS", 4) == 0) { int status; unsigned char *relocate = (unsigned char *) ((IMG_HEADER_Tp) image)->startAddr; buart_print("CSYS signature found.\r\n"); int inlen = (int) ((IMG_HEADER_Tp) image)->len; int outlen = LINUXLD_KERNEL_SIZE; buart_print("Inflate plugin... ");#ifdef TRY_TINF status = tinf_gzip_uncompress((char *) relocate, &outlen, image + 12, inlen - 8); if (status == TINF_OK) {#else status = ungzip_to(relocate, image + 12); if (status == Z_OK) {#endif buart_print(pass); void (*funcptr)(void) = (void *) relocate; /* Invoke the function pointer which SHOULD return */ buart_print("\r\nRun plugin...\r\n"); funcptr(); buart_print("Returned from plugin!"); } else { buart_print(fail); buart_nl(); } } else buart_print("CSYS signature not found.\r\n"); } } else buart_print(cdownload); buart_nl();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -