⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linuxld.c

📁 Boot code for ADM5120 with serial console for Edimax router.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************;    Project : Common platform;    Creator : Sumei Chung;    File    : loader.C;    Abstract: ;;*****************************************************************************/#include <ctype.h>#include <mips4kc.h>#include <adm5120.h>#include <hw_profile.h>#include <helpers.h>#include <bconfig.h>#include <mx29lv320.h>#include <flash.h>#include <img_header.h>#include <xmodem.h>#include <uartdrv.h>#include <buart_extra.h>#include <stdlib.h>#include <zlib.h>#include <linuxld.h>#include <test_def.h>//#define TRY_TINF	1#ifdef TRY_TINF/*	Some problems with this */#include "tinf.h"#endif/* 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 bytes */#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 *//* LINUXLD_GZIP_HEAP = LINUXLD_DOWNLOAD_START + LINUXLD_DOWNLOAD_SIZE *//* See 'param.c' for details of how LINUXLD_DOWNLOAD_START = A0820000 *//* With LINUXLD_DOWNLOAD_SIZE = 400000 (4 MB) in 'linuxld.h', this    *//* makes LINUXLD_GZIP_HEAP = A0C20000 (Kseg1) = 00C20000 (Kuseg)       */unsigned int loader_heap = LINUXLD_GZIP_HEAP;char *pass = "PASS";char *fail = "FAIL";char *xdownloading = "\r\n\r\nDownloading via Xmodem........ ";char *tdownloading = "\r\n\r\nDownloading via TFTP........";char *cdownload = "\r\n\r\nDownload canceled!";int ungzip(unsigned char *);char *gzip_original_name(unsigned char *);int tftp_client_menu(char *);UINT32 tftpc(char *, int);extern void _icache_sync_all(void);/* *	Show download information */  void show_dlinfo(UINT32 memloc, UINT32 size) { 	char digitstr[12];	ultoa(size, digitstr);	buart_print("\r\nTransferred: ");	buart_print(digitstr);	ultoa(memloc, digitstr);	buart_print(" bytes\r\nTo address : ");	buart_print(digitstr); }/* *	Common function to erase and program flash */int erase_and_write_flash(void *flash, char *image, UINT32 len){	int rc = -1;	/* Erase flash */#if PRESERVE_FLASH == 1	buart_print("\r\nWould erase flash here....... ");	if (1) {#else	buart_print("\r\nErasing flash................ ");	if (nf_erase(flash, len) == 0) {#endif		buart_print (pass);		/* Write flash */#if PRESERVE_FLASH == 1		buart_print("\r\nWould program flash here..... ");		if (1) {#else		buart_print("\r\nProgramming flash............ ");		if (nf_write(flash, image, len) == 0) {#endif			buart_print (pass);			rc = 0;		}	}	return rc;}/* *	Update bootloader */int update_bootloader(){	void *flash = (void *) LINUXLD_FLASH_LOADER_START;	char *image	= (char *) LINUXLD_DOWNLOAD_START;	int rc = -1;	UINT32 len;	buart_print("\r\nUPDATE_BOOTLOADER() CALLED BUT NOT RUN\r\n");	/* Download new bootloader to memory using Xmodem *///	buart_print(xdownloading);//	if ((len = xmodem(image, LINUXLD_FLASH_LOADER_SIZE)) > 0) {//		buart_print (pass);//		show_dlinfo((UINT32) image, len);		/* Erase and re-program the flash memory *///		rc = erase_and_write_flash(flash, image, len);//	}//	if (rc < 0)//		buart_print(fail);	return rc;}/* *	Download linux image to flash using TFTP client */#ifdef SECSECTORint tftpc_download_to_flash(){	void *flash = (void *) LINUXLD_FLASH_KERNEL_START;    char *image	= (char *) LINUXLD_DOWNLOAD_START;	int rc = -1;	UINT32 len;	/*	Present the current network parameters and, after		allowing for changes, continue only if they are		acceptable to the user. */	/* THIS ROUTINE BRICKED THE ROUTER SO FIX IT */	return rc;	if (tftp_client_menu("FLASH")) {		buart_print(tdownloading);		if ((len = tftpc(image, LINUX_IMAGE_SIZE)) > 0) {			buart_print (pass);			show_dlinfo((UINT32) image, len);			buart_nl();			/*	Erase and re-program the flash memory */			rc = erase_and_write_flash(flash, image, len);			if (rc < 0)				buart_print(fail);	// erase_and_write_flash writes its own "PASS"		} else {			buart_print(fail);		}	} else		buart_print(cdownload);	buart_nl();	return rc;}int tftpc_download_to_sdram(){    char *image	= (char *) LINUXLD_DOWNLOAD_START;	int rc = -1;	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("SDRAM")) {		buart_print(tdownloading);		if ((len = tftpc(image, LINUX_IMAGE_SIZE)) > 0) {			int status, offset, gzinput_len, gzoutput_len = 0, is_linux = 0;			volatile unsigned char *test_addr = 0;			char *orig_file_name;			void (*funcptr) (void);			show_dlinfo((UINT32) image, len);			buart_nl();			/*	In order to continue there needs to be a CSYS section in				the first 256K of transferred data.  Unlike booting out				of flash, we start searching at the very beginning of				the data for CSYS. */			for (offset = 0; offset < 0x50000; offset += 0x10000) {				test_addr = image + offset;				if (memcmp((void *) test_addr, "CSYS", 4) == 0) {					buart_print("CSYS signature found!\r\n");					break;				} else					buart_print("CSYS signature not found...\r\n");			}			if (offset < 0x50000) {				int namelen;				/*	Found CSYS					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.  Cannot determine that length a priori because					the CSYS length might be off by one due to padding.  We'll just have to wing					it and depend on the inflate routine to signal a problem if there's not					enough space for all the output. */				gzoutput_len = LINUXLD_KERNEL_SIZE;				/*	Make at least a half-assed effort to determine					it this is a Linux kernel or not. */				orig_file_name = gzip_original_name((unsigned char *) test_addr + 12);				if (orig_file_name) {					namelen = strlen(orig_file_name);					int i;					/*	See if it's got "vmlinu" anywhere in it */					for (i = 0; i < namelen; i++) {						if (strncmp(orig_file_name, "vmlinu", 6) == 0) {							is_linux = 1;							break;						}					}				}				if (is_linux)					buart_print("\r\ninflate linux code... ");				else					buart_print("\r\ninflate code... ");#ifdef TRY_TINF				/*	The input length could actually be -9 but we don't know beforehand					whether or not the padding byte is present. */				status = tinf_gzip_uncompress((char *) LINUXLD_KERNEL_START, &gzoutput_len,												(unsigned char *) test_addr + 12, gzinput_len - 8);				if (status == TINF_OK) {#else				status = ungzip((unsigned char *) test_addr + 12);				if (status == Z_OK) {#endif					int i, namelen = 0;					char ok_key = '\0';					volatile unsigned long *gpio_conf0 = (unsigned long *) (PA2VA(ADM5120_SWCTRL_BASE) + GPIO_conf0_REG);					volatile unsigned char *extio1 = (unsigned char *) PA2VA(ADM5120_EXTIO1_BASE);					buart_print(pass);					buart_print("\r\n\r\nPress 'Y' to jump to Linux or any other key to return to the menu: ");					ok_key = buart_getchar();					buart_put(ok_key);					buart_nl();					if ((ok_key == 'Y') || (ok_key == 'y')) {						buart_nl();						funcptr = (void *) LINUX_ENTRY_POINT;						buart_print("\r\njump to ");						if (is_linux) {							/*	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.								Value verified as 20FF_FF01 which matches Hawking32k_loader.idb								in function Run_Linux. */							*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;							buart_print("linux ");						}						/********************************/						/*	Invoke the code entry point	*/						/********************************/						buart_pair((unsigned int) funcptr, "code at");						funcptr();					}				} else {					buart_print(fail);					buart_nl();				}			}		} else {			buart_print(fail);			buart_print(" (received len = 0)\r\n");		}	} else		buart_print(cdownload);	buart_nl();	return rc;}#endif/* *	Download linux image to flash using Xmodem */ int xmodem_download(){	void *flash = (void *) LINUXLD_FLASH_KERNEL_START;	char *image = (char *) LINUXLD_DOWNLOAD_START;	int rc = -1;	UINT32 len;	/* Download Linux image to memory using Xmodem */	buart_print(xdownloading);	if ((len = xmodem(image, LINUX_IMAGE_SIZE)) > 0) {		buart_print (pass);		show_dlinfo((UINT32) image, len);		/* Erase and re-program the flash memory */		rc = erase_and_write_flash(flash, image, len);	}	if (rc < 0)		buart_print(fail);	return rc;}/* *	Boot Linux *		LINUXLD_DOWNLOAD_SIZE is 4 MB (0x00400000) *		LINUXLD_DOWNLOAD_START is...							[0xA0820000] (value used in Hawking32k_loader.idb) *			LINUXLD_LOADER_START (LINUXLD_MEMPOOL_START + LINUXLD_MEMPOOL_SIZE)		[0xA0800000]	(at 8 MB) *				(mempool start is LINUXLD_KERNEL_START + LINUXLD_KERNEL_SIZE)		[0xA0600000]	(at 6 MB) *					(kernel start is LINUXLD_SDRAM_START + LINUXLD_EXCEP_SIZE)		[0xA0002000] *						(LINUXLD_SDRAM_START = 0xA0000000) *						(LINUXLD_EXCEP_SIZE  = 0x2000 [64K]) *					(kernel size is 0x00600000 - 0x2000) (i.e. just under 6 MB)		[0x005FE000] *				(mempool size is 0x00200000) *			plus LINUXLD_LOADER_SIZE (64K)	[0x00002000]	<==== BOGUS AND NOT USED FOR ANYTHING !!! *			plus LINUXLD_RESERVE_SIZE (0) *		LINUXLD_GZIP_HEAP is LINUXLD_DOWNLOAD_START + 4 MB * *		LINUXLD_NORFLASH_BOOTPARAM_SIZE		=	0x00018000	(HS01, CS01 and DS01) *		LINUXLD_NORFLASH_BOOTPARAM_START	=	0xBFC08000 *			LINUXLD_NORFLASH_LOADER_START							= 0xBFC00000 *			LINUXLD_NORFLASH_LOADER_SIZE							= 0x00008000 * *		LINUXLD_FLASH_KERNEL_START = LINUXLD_NORFLASH_KERNEL_START *		= bootparam_start + bootparam_size	=	0xBFC20000 * */void boot_linux(){	volatile unsigned long *gpio_conf0, *gpio_conf2;	volatile unsigned char *extio1, *flash_addr, *test_addr = 0;	int status, offset, gzinput_len, gzoutput_len = 0;	void (*funcptr) (void);	flash_addr = (unsigned char *) PA2VA(ADM5120_SMEM0_BASE);		// same definition as LINUXLD_NORFLASH_LOADER_START	gpio_conf0 = (unsigned long *) (PA2VA(ADM5120_SWCTRL_BASE) + GPIO_conf0_REG);	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.  Cannot determine that length a priori because			the CSYS length might be off by one due to padding.  We'll just have to wing			it and depend on the inflate routine to signal a problem if there's not			enough space for all the output. */		gzoutput_len = LINUXLD_KERNEL_SIZE;		buart_print("\r\ninflate linux code... ");#ifdef TRY_TINF		/*	The input length could actually be -9 but we don't know beforehand			whether or not the padding byte is present. */		status = tinf_gzip_uncompress((char *) LINUXLD_KERNEL_START, &gzoutput_len,										(unsigned char *) test_addr + 12, gzinput_len - 8);		if (status == TINF_OK) {#else		status = ungzip((unsigned char *) test_addr + 12);		if (status == Z_OK) {#endif			buart_print(pass);			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.				Value verified as 20FF_FF01 */			*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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -