2410loader.c
字号:
/************************************************
* NAME : 2410loader.C *
* DESC : *
* History : 2002.02.25 ver 0.0 *
************************************************/
#include <stdlib.h>
#include <string.h>
#include "option.h"
#include "def.h"
#include "2410addr.h"
#include "2410slib.h"
#include "2410addr.h"
#include "k9s1208.h"
#include "mmu.h"
#include "2410loader.h"
#include "tftpnaive/tftpnaive.h"
#include "tftpnaive/net.h"
extern char Image$$RO$$Base[];
#define BOOTLOADER_RAM_ADDRESS (U32)Image$$RO$$Base
#define LED_ON 0xa
#define LED_OFF 0x0
#define OS_IMAGE_SIZE (2048)
void (*run)(void);
void Port_Init(void);
void Led_Display(int);
void Delay(int);
void ResetSystem(void);
void DefaultConfig(void);
void ShowConfig(void);
int DownloadImage(U32 addr);
volatile unsigned char *downPt;
volatile U32 downloadAddress;
volatile U32 downloadStartBlock;
void LoadAndRunImage(void);
void DownloadAndRunImage(void);
char *hex2char(int val);
char str2hex(char *str);
void dispmac(char *mac);
int setmac(void);
int setip(unsigned int *ipaddr, char *message);
void disphex(long val);
void hexdump(char *buf, long len);
void Loader_Menu(void);
void call_linux(long a0, long a1, long a2);
void ShowLinuxPartition(void);
void ModifyLinuxMTDName(void);
void UpdateLinuxPartition(void);
void ModifyLinuxPartition(void);
void DefaultLinuxPartition(void);
void LinuxPartitionString(char *str);
static LOADER_CONFIG lcf;
void Main(void)
{
register i,j;
MMU_EnableICache();
#if ADS10
__rt_lib_init(); //for ADS 1.0
#endif
ChangeClockDivider(1,1); // 1:2:4
//ChangeMPllValue(0x5c,0x4,0x0); //Fin=12MHz FCLK=200MHz
ChangeMPllValue(0x5c,0x1,0x1); // FCLK=200MHz
//ChangeMPllValue(82,1,1); //FCLK=180.0Mhz
Port_Init();
Uart_Init(PCLK, 115200);
//Uart_Init2(0, 115200);
// Configuration load
CFG_READ(&lcf);
if(lcf.magic!=SYS_MAGIC)
DefaultConfig();
Uart_Printf("\n\n\nS3C2410 Loader Build Date: %s [%d]\n\n", __DATE__, __ARMCC_VERSION);
Uart_SendString("Hold any key before this message to enter menu mode!!\n\n");
Uart_SendString("Bootloader Start 0x");
disphex(BOOTLOADER_RAM_ADDRESS);
Uart_SendString("\n");
// Sense keyin
if(Uart_GetAnyKey())
Loader_Menu();
else
{
if(lcf.bootdown&SYS_BOOT_MENU)
Loader_Menu();
else if(lcf.bootdown&SYS_BOOT_FLASH)
LoadAndRunImage();
else if(lcf.bootdown&SYS_BOOT_DOWNLOAD)
DownloadAndRunImage();
else
{
Uart_Printf("Please clear setting, configuration is invalid!!!!\n");
while(1);
}
}
}
char dischar[]="*|/-";
void LoadAndRunImage(void)
{
register i,j;
int jumpPt;
struct param_struct *pa;
MMU_EnableICache();
#if ADS10
__rt_lib_init(); //for ADS 1.0
#endif
if(lcf.systype==SYS_LINUX)
{
// Setup configuration
pa = (struct param_struct *)lcf.cfgaddr;
memset(pa, 0, sizeof(struct param_struct));
pa->u1.s.page_size = 0x00001000;
pa->u1.s.nr_pages = (0x04000000>>12);
memcpy(pa->commandline, lcf.cmd, strlen(lcf.cmd)+1);
LinuxPartitionString(pa->commandline+strlen(lcf.cmd));
}
else if(lcf.systype==SYS_WINCE)
{
run = (void (*)(void))(lcf.ramaddr);
}
else
{
Uart_SendString("\nUnknown kernel image, please update kernel!!\n");
while(1);
}
downPt=(unsigned char *)(lcf.ramaddr);
jumpPt = (int)downPt;
NF_Init();
Uart_Printf("Loading %s to 0x", (lcf.systype==SYS_LINUX)?"Linux kernel":"WinCE image");
disphex((int)downPt);
Uart_SendString("... ");
j=DOWN_KERNEL_START_BLOCK-1;
Uart_Printf("%c", dischar[j%4]);
while(j<(lcf.imgblk+DOWN_KERNEL_START_BLOCK)) // Read 1~807 block(13635072B) for WinCE image
{
j++;
Led_Display(j%16);
Uart_Printf("\b%c", dischar[j%4]);
for(i=0;i<32;i++) // Read 32 page
{
if(!NF_ReadPage(j, i, (U8 *)downPt)) //(U32 block,U32 page,U8 *buffer)
{
if(i!=0)
{
Led_Display(0x8); // real ECC Error
while(1);
}
break; // ECC error is considered as a bad block.
}
downPt += 512; // Next page
}
}
Uart_SendString("\n");
if(lcf.systype==SYS_LINUX)
call_linux(0, SYS_LINUX, jumpPt);
else
run();
}
void DownloadAndRunImage(void)
{
register i,j;
int jumpPt;
struct param_struct *pa;
int retry=5;
MMU_EnableICache();
#if ADS10
__rt_lib_init(); //for ADS 1.0
#endif
if(lcf.systype==SYS_LINUX)
{
// Setup configuration
pa = (struct param_struct *)lcf.cfgaddr;
memset(pa, 0, sizeof(struct param_struct));
pa->u1.s.page_size = 0x00001000;
pa->u1.s.nr_pages = (0x04000000>>12);
memcpy(pa->commandline, lcf.cmd, strlen(lcf.cmd)+1);
LinuxPartitionString(pa->commandline+strlen(lcf.cmd)-1);
}
else if(lcf.systype==SYS_WINCE)
{
run = (void (*)(void))(lcf.ramaddr);
}
else
{
Uart_SendString("\nUnknown kernel image, please update kernel!!\n");
while(1);
}
downPt=(unsigned char *)(lcf.ramaddr);
jumpPt = (int)downPt;
down_retry:
if(DownloadImage(lcf.ramaddr))
{
if(retry)
{
Uart_Printf("Download failed, retry...\n");
retry--;
goto down_retry;
}
else
{
Uart_Printf("Unable to download image....\n");
while(1);
}
}
Uart_Printf("\n");
if(lcf.systype==SYS_LINUX)
call_linux(0, SYS_LINUX, jumpPt);
else
run();
}
void call_linux(long a0, long a1, long a2){ //cache_clean_invalidate(); //tlb_invalidate();__asm { mov r0, a0 mov r1, a1 mov r2, a2 mov ip, #0 mcr p15, 0, ip, c13, c0, 0 /* zero PID */ mcr p15, 0, ip, c7, c7, 0 /* invalidate I,D caches */ mcr p15, 0, ip, c7, c10, 4 /* drain write buffer */ mcr p15, 0, ip, c8, c7, 0 /* invalidate I,D TLBs */ mrc p15, 0, ip, c1, c0, 0 /* get control register */ bic ip, ip, #0x0001 /* disable MMU */ mcr p15, 0, ip, c1, c0, 0 /* write control register */ //mov pc, r2 nop nop }
run=(void (*)(void))(a2);
run();}
void Loader_Menu(void)
{
extern U32 downloadFileSize;
char cmd[COMMAND_LINE_SIZE+1];
U8 key;
static U8 first=1;
again:
Uart_Printf("\n\n########## Select Menu ###########\n");
Uart_Printf(" [1] Boot Mode [%s]\n", (lcf.bootdown&SYS_BOOT_FLASH)?"Flash":(lcf.bootdown&SYS_BOOT_DOWNLOAD)?"Download":"Menu");
Uart_Printf(" [2] Download Mode [%s]\n", (lcf.bootdown&SYS_DOWNLOAD_USB)?"USB":"NET");
Uart_Printf(" [3] Update Bootloader\n");
Uart_Printf(" [4] Update Kernel/Partition [%s]\n", (lcf.systype==SYS_LINUX?"Linux":(lcf.systype==SYS_WINCE?"WinCE":"None")));
Uart_Printf(" [5] Show Setting\n");
Uart_Printf(" [6] Default Setting\n");
Uart_Printf(" [7] Reset\n");
// suck user's keys
if(first)
{
Uart_RecvUntilNoKey();
first = 0;
}
key = Uart_Getch();
switch(key)
{
case '1': //Uart_Printf("Current Boot From %s\n", (lcf.bootdown&SYS_BOOT_FLASH)?"Flash":"Download");
bootmode_again:
Uart_SendString("\n\n###### Select Menu ######\n");
Uart_SendString(" [1] Flash\n");
Uart_SendString(" [2] Download\n");
Uart_SendString(" [3] Menu\n");
Uart_SendString(" [4] Exit\n");
key = Uart_Getch();
switch(key)
{
case '1': lcf.bootdown &= ~(SYS_BOOT_FLASH|SYS_BOOT_DOWNLOAD|SYS_BOOT_MENU);
lcf.bootdown |= (SYS_BOOT_FLASH);
CFG_WRITE(&lcf); // Write configuration
break;
case '2': lcf.bootdown &= ~(SYS_BOOT_FLASH|SYS_BOOT_DOWNLOAD|SYS_BOOT_MENU);
lcf.bootdown |= (SYS_BOOT_DOWNLOAD);
CFG_WRITE(&lcf); // Write configuration
break;
case '3': lcf.bootdown &= ~(SYS_BOOT_FLASH|SYS_BOOT_DOWNLOAD|SYS_BOOT_MENU);
lcf.bootdown |= (SYS_BOOT_MENU);
CFG_WRITE(&lcf); // Write configuration
break;
case '4': break;
default: goto bootmode_again;
}
break;
case '2': //Uart_Printf("Current Download Through %s\n", (lcf.bootdown&SYS_DOWNLOAD_USB)?"USB":"NET");
downmode_again:
Uart_SendString("\n\n###### Select Menu ######\n");
Uart_SendString(" [1] USB\n");
Uart_SendString(" [2] NET\n");
Uart_SendString(" [3] Exit\n");
key = Uart_Getch();
switch(key)
{
case '1': lcf.bootdown &= ~(SYS_DOWNLOAD_USB|SYS_DOWNLOAD_ETH);
lcf.bootdown |= (SYS_DOWNLOAD_USB);
CFG_WRITE(&lcf); // Write configuration
break;
case '2':
tftp_again:
Uart_SendString("\n\n###### Select Menu ######\n");
Uart_SendString(" [1] BOOTP + TFTP\n");
Uart_SendString(" [2] TFTP\n");
Uart_SendString(" [3] Exit\n");
key = Uart_Getch();
switch(key)
{
case '1': setmac();
lcf.bootdown |= SYS_DOWNLOAD_ETH_BOOTP;
break;
case '2': setmac();
setip(&lcf.rmip, "TFTP Server ");
setip(&lcf.loip, "Local ");
Uart_Printf("Current filename %s\n", lcf.file);
Uart_Printf("Input: ");
Uart_RecvString(cmd, COMMAND_LINE_SIZE);
if(strlen(cmd))
memcpy(lcf.file, cmd, strlen(cmd)+1);
lcf.bootdown |= SYS_DOWNLOAD_ETH_TFTP;
break;
case '3': goto again;
default: goto tftp_again;
}
lcf.bootdown &= ~(SYS_DOWNLOAD_USB|SYS_DOWNLOAD_ETH);
lcf.bootdown |= (SYS_DOWNLOAD_ETH);
CFG_WRITE(&lcf); // Write configuration
break;
case '3': break;
default: goto downmode_again;
}
break;
case '3': DownloadImage(DOWN_RAM_ADDR);
if((downloadFileSize/BLOCK_SIZE)>=DOWN_KERNEL_START_BLOCK)
Uart_SendString("\nWarning!!! Image too big, write image will overwrite kernel...\n");
ask_loader_again:
Uart_SendString("\nDownload finish, write to flash? [Y/N] ");
key = Uart_Getch();
if(key=='y' || key=='Y')
u241test_easy(DOWN_LOADER);
else if(key!='n' && key!='N')
goto ask_loader_again;
break;
case '4':
kernel_again:
Uart_SendString("\n\n######### Select Menu #########\n");
Uart_SendString(" [1] WinCE Image\n");
Uart_SendString(" [2] Linux Kernel\n");
Uart_SendString(" [3] Linux Command Line\n");
Uart_SendString(" [4] Linux Partition Configure\n");
Uart_SendString(" [5] Linux Partition Update\n");
Uart_SendString(" [6] Exit\n");
key = Uart_Getch();
switch(key)
{
case '1': memcpy(lcf.cmd, CMD_WINCE, strlen(cmd)+1);
lcf.systype = SYS_WINCE;
lcf.ramaddr = RAM_WINCE;
lcf.cfgaddr = CFG_WINCE;
break;
case '2':
#if 0
Uart_Printf("Linux %s kernel command: [Press Enter to use this command]\n", (strlen(lcf.cmd)>0)?"current":"default");
Uart_Printf("%s\n", (strlen(lcf.cmd)>0)?lcf.cmd:CMD_LINUX);
Uart_Printf("Input: ");
Uart_RecvString(cmd, COMMAND_LINE_SIZE);
if(strlen(cmd))
memcpy(lcf.cmd, cmd, strlen(cmd)+1);
else if(strlen(lcf.cmd)==0)
memcpy(lcf.cmd, CMD_LINUX, strlen(CMD_LINUX)+1);
#endif
lcf.systype = SYS_LINUX;
lcf.ramaddr = RAM_LINUX;
lcf.cfgaddr = CFG_LINUX;
CFG_WRITE(&lcf); // Write configuration
goto again;
case '3':
if(lcf.systype!=SYS_LINUX)
{
Uart_Printf("\n\nCurrent configuration is not for Linux kernel!!\n");
goto again;
}
Uart_SendString("\nCurrent Linux kernel command: [Press Enter to use current command]\n");
Uart_Printf("%s\n", lcf.cmd);
Uart_Printf("Input: ");
Uart_RecvString(cmd, COMMAND_LINE_SIZE);
if(strlen(cmd))
{
memcpy(lcf.cmd, cmd, strlen(cmd)+1);
CFG_WRITE(&lcf); // Write configuration
}
goto again;
case '4': if(lcf.systype!=SYS_LINUX)
{
Uart_Printf("\n\nCurrent configuration is not for Linux kernel!!\n");
goto again;
}
else
Uart_SendString("\n");
ModifyLinuxMTDName();
Uart_Printf("\n");
ModifyLinuxPartition();
CFG_WRITE(&lcf); // Write configuration
goto again;
case '5': if(lcf.systype!=SYS_LINUX)
{
Uart_Printf("\n\nCurrent configuration is not for Linux kernel!!\n");
goto again;
}
else
Uart_SendString("\n");
ShowLinuxPartition();
Uart_Printf("\n");
UpdateLinuxPartition();
goto again;
case '6': goto again;
default: goto kernel_again;
}
if(lcf.bootdown&SYS_BOOT_FLASH)
{
DownloadImage(DOWN_RAM_ADDR);
lcf.imgblk = (((downloadFileSize/(0x4000))*(0x4000))+((downloadFileSize%(0x4000))?(0x4000):0))/BLOCK_SIZE;
ask_kernel_again:
Uart_SendString("\nDownload finish, write to flash? [Y/N] ");
key = Uart_Getch();
if(key=='y' || key=='Y')
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -