📄 2410loader.c
字号:
u241test_easy(DOWN_KERNEL);
CFG_WRITE(&lcf); // Write configuration
}
else if(key!='n' && key!='N')
goto ask_kernel_again;
}
else
CFG_WRITE(&lcf); // Write configuration
break;
case '5': ShowConfig();
goto again;
break;
case '6': DefaultConfig();
goto again;
break;
case '7': ResetSystem();
while(1);
}
goto again;
}
#define WATCHDOG_TIME (128) // [usec], Max=65535*128us.
void ResetSystem(void)
{
rWTCON = (1<<8) | (1<<5) | (1<<0);
// rWTCON = ((PCLK/1000000-1)<<8) | (3<<3) | 1<<2 | 1<<0; //Prescaler=0x31(49),Clock division 128,Reset enable
// rWTDAT = WATCHDOG_TIME/128;
// rWTCNT = WATCHDOG_TIME/128; // (xsec/128us)
// rWTCON = rWTCON | (1<<5); //Watch-dog timer enable
}
int DownloadImage(U32 addr)
{
if(lcf.bootdown&SYS_DOWNLOAD_USB)
return u241mon_easy(addr);
else
{
TFTPDownload tftp;
tftp.mode = (lcf.bootdown >> 6) & 0x3;
tftp.local_ip = lcf.loip;
tftp.remote_ip = lcf.rmip;
tftp.downaddr = addr;
memcpy(tftp.mac, lcf.mac, 6);
strcpy(tftp.file, lcf.file);
return tftpnaive(&tftp);
}
}
void DefaultConfig(void)
{
memset(&lcf, 0, sizeof(LOADER_CONFIG));
lcf.magic = SYS_MAGIC;
lcf.bootdown = SYS_BOOT_FLASH | SYS_DOWNLOAD_USB;
memcpy(lcf.mac, SYS_MAC_ADDR, 6);
lcf.loip = SYS_DFT_LOIP;
lcf.rmip = SYS_DFT_RMIP;
strcpy(lcf.file, SYS_BOOT_FILE);
memcpy(lcf.cmd, CMD_LINUX, strlen(CMD_LINUX)+1);
DefaultLinuxPartition();
CFG_WRITE(&lcf);
}
void hexdump(char *buf, long len)
{
long idx, val;
for(idx=0; idx<len; idx++)
{
if(idx%16==0)
{
Uart_SendString("\n");
disphex(idx);
Uart_SendString(": ");
}
Uart_SendString(hex2char((buf[idx]&0xf0)>>4));
Uart_SendString(hex2char((buf[idx]&0x0f)>>0));
Uart_SendString(" ");
}
}
void dispmac(char *mac)
{
Uart_Printf("%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
}
int setmac(void)
{
char cmd[COMMAND_LINE_SIZE+1];
Uart_Printf("\nCurrent MAC: ");
dispmac((char *)lcf.mac);
Uart_Printf("\nExample: 001122334455\n");
Uart_Printf("Input: ");
Uart_RecvString(cmd, COMMAND_LINE_SIZE);
if(strlen(cmd)==12)
{
lcf.mac[0] = str2hex(&cmd[0]);
lcf.mac[1] = str2hex(&cmd[2]);
lcf.mac[2] = str2hex(&cmd[4]);
lcf.mac[3] = str2hex(&cmd[6]);
lcf.mac[4] = str2hex(&cmd[8]);
lcf.mac[5] = str2hex(&cmd[10]);
return 0;
}
return -1;
}
void dispip(unsigned int ipaddr)
{
Uart_Printf("%d.%d.%d.%d",
(ipaddr&0xff000000) >> 24,
(ipaddr&0x00ff0000) >> 16,
(ipaddr&0x0000ff00) >> 8,
(ipaddr&0x000000ff));
}
unsigned char
_atoi(char *str)
{
unsigned char val=0, len, idx, round;
len = strlen(str);
for(idx=0; idx<len; idx++)
{
switch(idx)
{
case 0: val += (str[len-idx-1]-'0')*1; break;
case 1: val += (str[len-idx-1]-'0')*10; break;
case 2: val += (str[len-idx-1]-'0')*100; break;
default: return 0;
}
}
return val;
}
int str2ip( char *szIp, unsigned char *ucIp)
{
int i=0, j=0, nIpIdx=0;
char temp[4];
int err=FALSE;
U32 *coIP = (U32 *)ucIp;
memset( ucIp, 0, 4);
memset( temp, 0, 4);
while( szIp[i] && !err)
{
if( szIp[i]=='.')
{
if( nIpIdx<4)
ucIp[nIpIdx++]=(unsigned char)(_atoi(temp));
else
err=TRUE;
memset( temp, 0, 4);
j=0;
i++;
}
else
if(j<3)
temp[j++]= szIp[i++];
else
err=TRUE;
}
if(!err)
if(nIpIdx<4)
ucIp[nIpIdx++]= (unsigned char)(_atoi(temp));
*coIP = hton4(*coIP);
return err;
}
int setip(unsigned int *ipaddr, char *message)
{
char cmd[COMMAND_LINE_SIZE+1];
U32 myip;
Uart_Printf("\nCurrent %sIP: ", message);
dispip(*ipaddr);
Uart_Printf("\nExample: 192.168.0.3\n");
Uart_Printf("Input: ");
Uart_RecvString(cmd, COMMAND_LINE_SIZE);
if(strlen(cmd)>=7 && strlen(cmd)<=15)
{
if(!str2ip(cmd, (unsigned char *)&myip))
{
*ipaddr = myip;
return 0;
}
}
return -1;
}
void disphex(long val)
{
int cnt;
cnt = (val>>16);
Uart_SendString(hex2char((cnt&0xf000)>>12));
Uart_SendString(hex2char((cnt&0x0f00)>>8));
Uart_SendString(hex2char((cnt&0x00f0)>>4));
Uart_SendString(hex2char((cnt&0x000f)>>0));
cnt = (val&0xffff);
Uart_SendString(hex2char((cnt&0xf000)>>12));
Uart_SendString(hex2char((cnt&0x0f00)>>8));
Uart_SendString(hex2char((cnt&0x00f0)>>4));
Uart_SendString(hex2char((cnt&0x000f)>>0));
}
char *hex2char(int val)
{
static char str[2];
str[1]='\0';
if(val<=9)str[0]='0'+val;
else str[0]=('A'+val-10);
return str;
}
char str2hex(char *str)
{
char ret;
if(str[0]>='A')
ret = (str[0]-'A'+10)<<4;
else if(str[0]>='a')
ret = (str[0]-'a'+10)<<4;
else
ret = (str[0]-'0')<<4;
if(str[1]>='A')
ret |= (str[1]-'A'+10);
else if(str[1]>='a')
ret |= (str[1]-'a'+10);
else
ret |= (str[1]-'0');
return ret;
}
void ShowConfig(void)
{
Uart_SendString("\n\n###### System Configuration ######\n");
Uart_Printf("Boot Mode\t: %s\n", (lcf.bootdown&SYS_BOOT_FLASH)?"Flash":(lcf.bootdown&SYS_BOOT_DOWNLOAD)?"Download":"Menu");
Uart_Printf("Download Mode\t: %s\n", (lcf.bootdown&SYS_DOWNLOAD_USB)?"USB":(lcf.bootdown&SYS_DOWNLOAD_ETH_BOOTP)?"NET [BOOTP+TFTP]":"NET [TFTP]");
if(lcf.bootdown & SYS_DOWNLOAD_ETH) { Uart_Printf("MAC Address\t: "); dispmac((char *)lcf.mac); Uart_Printf("\n"); }
if(lcf.bootdown & SYS_DOWNLOAD_ETH_TFTP)
{
Uart_Printf("Local IP\t: ");
dispip(lcf.loip);
Uart_Printf("\nServer IP\t: ");
dispip(lcf.rmip);
Uart_Printf("\nFilename\t: %s\n", lcf.file);
}
Uart_Printf("System\t\t: %s\n", (lcf.systype==SYS_LINUX?"Linux":(lcf.systype==SYS_WINCE?"WinCE":"None")));
if(lcf.systype==SYS_LINUX)
{
Uart_Printf("Kernel Command\t: %s\n", lcf.cmd);
Uart_Printf("Linux Partition :\n");
ShowLinuxPartition();
}
Uart_Printf("\nPress any key to continue...\n");
Uart_Getch();
}
void ShowLinuxPartition(void)
{
int nr_part;
if(lcf.systype==SYS_LINUX)
for(nr_part=0; nr_part<PARTITION_TOTAL; nr_part++)
{
if(lcf.part[nr_part].mask&PARTITION_VALID)
{
if(lcf.part[nr_part].size==PARTITION_RESTSIZE)
Uart_Printf("[%d] %10s: %08x-REST (%s)\n", nr_part+1, lcf.part[nr_part].name,
lcf.part[nr_part].offset,
(lcf.part[nr_part].mask&PARTITION_FIXED)?"FIXED":
(lcf.part[nr_part].mask&PARTITION_RO)?"RO":
(lcf.part[nr_part].mask&PARTITION_RW)?"RW":"NONE");
else
Uart_Printf("[%d] %10s: %08x-%08x (%d) (%s)\n", nr_part+1, lcf.part[nr_part].name,
lcf.part[nr_part].offset,
lcf.part[nr_part].offset+lcf.part[nr_part].size,
lcf.part[nr_part].size,
(lcf.part[nr_part].mask&PARTITION_FIXED)?"FIXED":
(lcf.part[nr_part].mask&PARTITION_RO)?"RO":
(lcf.part[nr_part].mask&PARTITION_RW)?"RW":"NONE");
}
//else
// Uart_Printf("[%d] Invalid Partition\n", nr_part);
}
}
void ModifyLinuxMTDName(void)
{
char str[PARTITION_NAMESIZE+1];
Uart_Printf("Current MTD Name: %s\n", lcf.mtdname);
Uart_Printf("New MTD Name: ");
Uart_RecvString(str, PARTITION_NAMESIZE);
if(strlen(str)>0)
strcpy(lcf.mtdname, str);
}
void ModifyLinuxPartition(void)
{
int nr_part;
char str[PARTITION_NAMESIZE+1];
for(nr_part=0; nr_part<PARTITION_TOTAL; nr_part++)
{
if(lcf.part[nr_part].size==PARTITION_RESTSIZE)
Uart_Printf("\n[%d] %10s: %08x-REST (%s)\n", nr_part+1, lcf.part[nr_part].name,
lcf.part[nr_part].offset,
(lcf.part[nr_part].mask&PARTITION_FIXED)?"FIXED":
(lcf.part[nr_part].mask&PARTITION_RO)?"RO":
(lcf.part[nr_part].mask&PARTITION_RW)?"RW":"NONE");
else
Uart_Printf("\n[%d] %10s: %08x-%08x (%d) (%s)\n", nr_part+1, lcf.part[nr_part].name,
lcf.part[nr_part].offset,
lcf.part[nr_part].offset+lcf.part[nr_part].size,
lcf.part[nr_part].size,
(lcf.part[nr_part].mask&PARTITION_FIXED)?"FIXED":
(lcf.part[nr_part].mask&PARTITION_RO)?"RO":
(lcf.part[nr_part].mask&PARTITION_RW)?"RW":"NONE");
if(lcf.part[nr_part].mask&PARTITION_FIXED)
Uart_Printf("Partition can't be modified!!\n");
else
{
if(nr_part==1)
Uart_Printf("Notice: The second partition will be taken as kernel!!\n");
Uart_Printf("Name: ");
Uart_RecvString(str, PARTITION_NAMESIZE);
if(strlen(str)>0)
strcpy(lcf.part[nr_part].name, str);
Uart_Printf("%s\n", lcf.part[nr_part].name);
op_again:
Uart_Printf("Option [1]Read-Only [2]Read-Write: ");
Uart_RecvString(str, PARTITION_NAMESIZE);
if(strlen(str)!=0 && (str[0]!='1' && str[0]!='2'))
goto op_again;
else if(strlen(str)!=0)
lcf.part[nr_part].mask = (str[0]=='1')?PARTITION_RO:PARTITION_RW;
Uart_Printf("\n");
#if PARTITION_OFFSET
Uart_Printf("Offset[Hex]: ");
Uart_RecvString(str, PARTITION_NAMESIZE);
if(strlen(str)>0)
lcf.part[nr_part].offset = strtol(str, NULL, 16);
Uart_Printf("\n");
#else
if(nr_part>0)
lcf.part[nr_part].offset = lcf.part[nr_part-1].offset+lcf.part[nr_part-1].size;
else
lcf.part[nr_part].offset = 0;
#endif
Uart_Printf("Size [16K*n, '-' for rest]: n = "); // Linux requires PAGE(4K) aligned, but NAND takes block(16K)
Uart_RecvString(str, PARTITION_NAMESIZE);
Uart_Printf("\n");
if(strlen(str)>0)
{
if(str[0]=='-')
{
lcf.part[nr_part].size = PARTITION_RESTSIZE;
break;
}
else
lcf.part[nr_part].size = strtol(str, NULL, 10) * 1024 * 16;
}
Uart_Printf("Next Partition? ");
Uart_RecvString(str, PARTITION_NAMESIZE);
Uart_Printf("\n");
if(str[0]!='Y' && str[0]!='y')
break;
}
}
}
void DefaultLinuxPartition(void)
{
int nr_part;
memset(&lcf.part[0], 0, sizeof(PARTITION)*PARTITION_TOTAL);
// The first partition is used by bootloader
strcpy(lcf.mtdname, "s3c2410-nand");
strcpy(lcf.part[0].name, "Bootloader");
lcf.part[0].offset = 0;
lcf.part[0].size = DOWN_KERNEL_START_BLOCK*BLOCK_SIZE;
lcf.part[0].mask = PARTITION_FIXED;
}
char *strcopyshift(char *str, char *dup)
{
strcpy(str, dup);
return (str+strlen(dup));
}
void UpdateLinuxPartition(void)
{
int real_part, key;
part_again:
Uart_Printf("Which partition to update [1-%d]: ", PARTITION_TOTAL);
real_part = Uart_Getch()-'0'-1;
Uart_Printf("\n");
if(real_part>=PARTITION_TOTAL || real_part<0)
goto part_again;
if(lcf.part[real_part].mask&PARTITION_RO || lcf.part[real_part].mask&PARTITION_RW)
{
DownloadImage(DOWN_RAM_ADDR);
if(real_part==1)
{
lcf.imgblk = (((downloadFileSize/(0x4000))*(0x4000))+((downloadFileSize%(0x4000))?(0x4000):0))/BLOCK_SIZE;
CFG_WRITE(&lcf); // Write configuration
}
downloadStartBlock = lcf.part[real_part].offset/BLOCK_SIZE;
Uart_SendString("\nDownload finish, write to flash? [Y/N] ");
key = Uart_Getch();
if(key=='y' || key=='Y')
u241test_easy(DOWN_VARIABLE);
}
else
Uart_Printf("Partition is unable to update!!\n");
}
void LinuxPartitionString(char *str)
{
int nr_part, fpart;
char temp[PARTITION_NAMESIZE+1];
if(lcf.systype!=SYS_LINUX) return;
str = strcopyshift(str, " mtdparts=");
str = strcopyshift(str, lcf.mtdname);
str = strcopyshift(str, ":");
for(nr_part=0,fpart=1; nr_part<PARTITION_TOTAL; nr_part++)
{
if(lcf.part[nr_part].mask&PARTITION_VALID)
{
if(fpart)
fpart=0;
else
str = strcopyshift(str, ",");
#if PARTITION_OFFSET
if(lcf.part[nr_part].size==PARTITION_RESTSIZE)
sprintf(temp, "-@%d%s(%s)%s", (lcf.part[nr_part].offset%SIZE_1M==0)?lcf.part[nr_part].offset/SIZE_1M:lcf.part[nr_part].offset/SIZE_1K,
(lcf.part[nr_part].offset%SIZE_1M==0)?"M":"K",
lcf.part[nr_part].name,
(lcf.part[nr_part].mask&PARTITION_RW)?"":"ro");
else
sprintf(temp, "%d%s@%d%s(%s)%s", (lcf.part[nr_part].size%SIZE_1M==0)?lcf.part[nr_part].size/SIZE_1M:lcf.part[nr_part].size/SIZE_1K,
(lcf.part[nr_part].size%SIZE_1M==0)?"M":"K",
(lcf.part[nr_part].offset%SIZE_1M==0)?lcf.part[nr_part].offset/SIZE_1M:lcf.part[nr_part].offset/SIZE_1K,
(lcf.part[nr_part].offset%SIZE_1M==0)?"M":"K",
lcf.part[nr_part].name,
(lcf.part[nr_part].mask&PARTITION_RW)?"":"ro");
#else
if(lcf.part[nr_part].size==PARTITION_RESTSIZE)
sprintf(temp, "-(%s)%s", lcf.part[nr_part].name,
(lcf.part[nr_part].mask&PARTITION_RW)?"":"ro");
else
sprintf(temp, "%d%s(%s)%s", (lcf.part[nr_part].size%SIZE_1M==0)?lcf.part[nr_part].size/SIZE_1M:lcf.part[nr_part].size/SIZE_1K,
(lcf.part[nr_part].size%SIZE_1M==0)?"M":"K",
lcf.part[nr_part].name,
(lcf.part[nr_part].mask&PARTITION_RW)?"":"ro");
#endif
str = strcopyshift(str, temp);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -