📄 linuxld.c
字号:
/*****************************************************************************;; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.;; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.;;------------------------------------------------------------------------------;; Project : Common platform; Creator : Sumei Chung; File : loader.C; Abstract: ;;Modification History:; ;;*****************************************************************************/#include <ctype.h>#include <mips4kc.h>#include <adm5120.h>#include <hw_profile.h>#include <bconfig.h>#ifdef NOR_FLASH#include <mx29lv160.h>#include <mx29lv320.h>#include <flash.h>#else#include <nand.h>#endif#include <img_header.h>#include <xmodem.h>#include <uartdrv.h>#include <stdlib.h>#include <zlib.h>#include <linuxld.h>#define AM5120_VINETIC 0/* linux boot defined *//* Address of "_start" in System.map */#define LINUX_ENTRY_POINT 0x800026D8#define LINUX_IMAGE_SIZE LINUXLD_FLASH_KERNEL_SIZE/* gzip defined */#define _OFFSET(_t, _m) ((u_int) &(((_t *) 0)->_m))#define Z_EOF 0/* gzip flag byte */#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */#define ORIG_NAME 0x08 /* bit 3 set: original file name present */#define COMMENT 0x10 /* bit 4 set: file comment present */#define RESERVED 0xE0 /* bits 5..7: reserved */static int gz_magic[2] = { 0x1f, 0x8b }; /* gzip magic header */unsigned int loader_heap = LINUXLD_GZIP_HEAP;char *pass = "PASS";char *fail = "FAIL";int ungzip(Byte * compr);extern void _icache_sync_all(void);void jump_up_map();void jump_low_map();/* * Update bootloader */int update_bootloader(){ void *flash = (void *) LINUXLD_FLASH_LOADER_START; char *image = (char *) LINUXLD_DOWNLOAD_START; int len, rc = 0; /* download loader image to temp using xmodem */ buart_print("\n\rDownloading.........."); if ((len = xmodem(image, LINUXLD_FLASH_LOADER_SIZE)) == -1) goto fail; else buart_print(pass); /* erase flash */ buart_print("\n\rErasing flash......."); if (nf_erase(flash, len) != 0) goto fail; else buart_print(pass); /* write flash */ buart_print("\n\rProgramming flash...."); if (nf_write_boot((UINT8 *) flash, image, len) != 0) goto fail; else buart_print(pass); goto ok; fail: buart_print(fail); rc = -1; ok: return (rc);}int tftpc_download(void){ void *flash = (void *) LINUXLD_FLASH_KERNEL_START; char *image = (char *) LINUXLD_DOWNLOAD_START; char lenstr[9]; UINT32 len; buart_print("\n\rStarting the TFTP download(ESC to stop).."); if ((len = tftpc(image, LINUX_IMAGE_SIZE)) == 0) goto fail; else buart_print(pass); //print image length and starting address in sdram. //ultoa(len,lenstr); //lenstr[8]=0; //buart_print("\n\rImage Total Length: "); //buart_print(lenstr); //ultoa(image,lenstr); //buart_print(" Starting Address: "); //buart_print(lenstr); //erase flash buart_print("\n\r\n\rErasing flash.......");#ifdef AM5120_VINETIC { int remain; if ((remain = len - LINUXLD_NORFLASH_REMAIN) > 0) { jump_low_map(); if (nf_erase(flash, LINUXLD_NORFLASH_REMAIN) != 0) goto fail; jump_up_map(); if (nf_erase(LINUXLD_NORFLASH_LOADER_START, remain) != 0) goto fail; jump_low_map(); goto ERASE_PASS; } }#endif if (nf_erase(flash, len) != 0) goto fail; ERASE_PASS: buart_print(pass); //write flash buart_print("\n\rProgramming flash....");#ifdef AM5120_VINETIC { int remain; if ((remain = len - LINUXLD_NORFLASH_REMAIN) > 0) { jump_low_map(); if (nf_write(flash, image, LINUXLD_NORFLASH_REMAIN) != 0) goto fail; jump_up_map(); if (nf_write(LINUXLD_NORFLASH_LOADER_START, image + LINUXLD_NORFLASH_REMAIN, remain) != 0) goto fail; jump_low_map(); goto WRITE_PASS; } }#endif if (nf_write(flash, image, len) != 0) goto fail; WRITE_PASS: buart_print(pass); goto ok; fail: jump_low_map(); buart_print(fail); return -1; ok: return 0;}/* * download linux image to flash using xmodem */int xmodem_download(void){ void *flash = (void *) LINUXLD_FLASH_KERNEL_START; char *image = (char *) LINUXLD_DOWNLOAD_START; int len, rc = 0; /* download linux image to temp using xmodem */ buart_print("\n\rDownloading.........."); if ((len = xmodem(image, LINUX_IMAGE_SIZE)) == -1) goto fail; else buart_print(pass); /* erase flash */ buart_print("\n\rErasing flash.......");#ifdef AM5120_VINETIC { int remain; if ((remain = len - LINUXLD_NORFLASH_REMAIN) > 0) { jump_low_map(); if (nf_erase(flash, LINUXLD_NORFLASH_REMAIN) != 0) goto fail; jump_up_map(); if (nf_erase(LINUXLD_NORFLASH_LOADER_START, remain) != 0) goto fail; jump_low_map(); goto ERASE_PASS; } }#endif if (nf_erase(flash, len) != 0) goto fail; ERASE_PASS: buart_print(pass); /* write flash */ buart_print("\n\rProgramming flash....");#ifdef AM5120_VINETIC { int remain; if ((remain = len - LINUXLD_NORFLASH_REMAIN) > 0) { jump_low_map(); if (nf_write(flash, image, LINUXLD_NORFLASH_REMAIN) != 0) goto fail; jump_up_map(); if (nf_write(LINUXLD_NORFLASH_LOADER_START, image + LINUXLD_NORFLASH_REMAIN, remain) != 0) goto fail; jump_low_map(); goto WRITE_PASS; } }#endif if (nf_write(flash, image, len) != 0) goto fail; WRITE_PASS: buart_print(pass); goto ok; fail: buart_print(fail); rc = -1; ok: return (rc);}/* * linux boot function */void boot_linux(){ int status; void (*funcptr) (void); buart_print("\n\rBooting Linux... "); // NAND flash cannot ungzip kernel as directly as NOR flash. // NAND flash "must" copy kernel to sdram first.#ifdef NOR_FLASH // decompressing buart_print("\n\rKernel decompress ... ");#ifdef AM5120_VINETIC { char *image = (char *) LINUXLD_DOWNLOAD_START; char *flash = (char *) LINUXLD_NORFLASH_KERNEL_START; jump_low_map(); memcpy(image, flash, LINUXLD_NORFLASH_REMAIN); jump_up_map(); image += LINUXLD_NORFLASH_REMAIN; flash = (char *) LINUXLD_NORFLASH_LOADER_START; memcpy(image, flash, LINUXLD_NORFLASH_MAP_SIZE); jump_low_map(); status = ungzip((unsigned char *) LINUXLD_DOWNLOAD_START); }#else status = ungzip((unsigned char *) LINUXLD_NORFLASH_KERNEL_START);#endif#else nf_read((UINT8 *) LINUXLD_DOWNLOAD_START, (UINT8 *) LINUXLD_FLASH_KERNEL_START, LINUX_IMAGE_SIZE); // decompressing buart_print("\n\rKernel decompress ... "); //okay!"); status = ungzip((unsigned char *) LINUXLD_DOWNLOAD_START);#endif if (status != Z_OK) // failed in unzipping { buart_print(fail); return; // return if cannot boot } else buart_print(pass); DisableTimer(); funcptr = (void *) LINUX_ENTRY_POINT; _icache_sync_all(); funcptr();}/* * 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])) return (Z_DATA_ERROR); if (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 now */ d_stream.zalloc = NULL; d_stream.zfree = NULL; d_stream.opaque = (voidpf) 0; d_stream.next_in = zimg; // address of compress image d_stream.avail_in = LINUX_IMAGE_SIZE; // size of compress image if ((err = inflateInit2(&d_stream, -MAX_WBITS)) != Z_OK) { return err; } d_stream.next_out = (char *) LINUXLD_KERNEL_START; // address of decompress image d_stream.avail_out = LINUXLD_KERNEL_SIZE; // size of decompress space if ((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_STREAM_END) { return err; } err = inflateEnd(&d_stream); return err;}/* * Because there is no OS support, the memory management functions in * STD C libray cann't be used. To overcome the problem, a very simple * memory management skime is implemented here. */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 4-byte boundry */ if (loader_heap & 0x03) loader_heap = (loader_heap + 3) & ~0x03; bkstart = loader_heap; loader_heap += memsize; return (void *) bkstart;}/* * dummy function */void free(void *ptr){ return;}/* * Jump to no-flash upper 2MB */void jump_up_map(){ int i; /* Set GPIO[3](CS) to high */ for (i = 0; i < 10000; i++); ADM5120_SW_REG(GPIO_conf0_REG) = 0x080800f7; for (i = 0; i < 10000; i++);}/* * Jump to no-flash upper 2MB */void jump_low_map(){ int i; /* Set GPIO[3](CS) to low */ for (i = 0; i < 10000; i++); ADM5120_SW_REG(GPIO_conf0_REG) = 0x3ff; for (i = 0; i < 10000; i++);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -