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

📄 nand.c

📁 s3c2440的bootloader 可以加载linux wince
💻 C
字号:
#include <string.h>
#include <stdio.h>

#include "def.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "Nand.h"

//suppport boot params
//#define	GLOBAL_PARAMS
#include "bootpara.h"

//可更改删除分区,分区名字不可改
static struct Partition NandPart[] = {
	{0, 		 	0x00100000, "boot"},		//128K
	{0x00100000, 0x00040000, "bootParam"},//two blocks
	{0x00140000, 0x003c0000, "MyApp"},		//4M512K
	{0x00500000, 0x00300000, "kernel"},		//3M128K
	//{0x00800000, 0x01400000, "fs_cramfs"},	//20M
	{0x00800000, 0x03c00000, "fs_yaffs"},	//40M
	{0x04400000, 0x03c00000, "wince"},		//60M
	{0,			 0         , 0}
};
/*
static struct Partition NandPart[] = {
	{0, 		 	0x00100000, "boot"},		//128K
	{0x00100000, 0x00040000, "bootParam"},//two blocks
	{0x00140000, 0x003c0000, "MyApp"},		//4M512K
	{0x00500000, 0x00300000, "kernel"},		//3M128K
	{0x00800000, 0x01400000, "fs_cramfs"},	//20M
	{0x01c00000, 0x02800000, "fs_yaffs"},	//40M
	{0x04400000, 0x03c00000, "wince"},		//60M
	{0,			 0         , 0}
};
*/

#define	puts	Uart_Printf
#define	printf	Uart_Printf
#define	getch	Uart_Getch
#define	putch	Uart_SendByte
#define	EnNandFlash()	(rNFCONT |= 1)
#define	DsNandFlash()	(rNFCONT &= ~1)
struct Partition * NandSelPart(char *info)
{
	U16 i, max_sel;
	struct Partition *ptr = NandPart;
	
	printf("\nPlease select which region to %s : Esc to abort\n", info);
	
	for(i=0; ptr->size!=0; i++, ptr++)
		printf("%d : offset 0x%08x, size 0x%08x [%s]\n", i, ptr->offset, ptr->size, ptr->name);
		
	max_sel = i;
	
	while(1) {
		i = getch();
		if(i==0x1b)
			return NULL;
		if((i>='0')&&(i<(max_sel+'0'))) {
			i -= '0';
			//StartPage = NandPart[i].offset>>11;
			//BlockCnt  = NandPart[i].size>>17;
			//return i;
			return &NandPart[i];
		}
	}	
}

struct Partition * NandSelPart_2(char *info)
{
	U16 i, max_sel;
	struct Partition *ptr = NandPart;
	
	//printf("\nPlease select which region to %s : Esc to abort\n", info);
	
	for(i=0; ptr->size!=0; i++, ptr++)
		//printf("%d : offset 0x%08x, size 0x%08x [%s]\n", i, ptr->offset, ptr->size, ptr->name);
		if(!strcmp(ptr->name,info))
			return ptr;

	printf(" ERROR:there is no %s part\n",info);
	return NULL;
		

}

/************** boot linux ***************************/

#define LINUX_PAGE_SHIFT	12
#define LINUX_PAGE_SIZE		(1<<LINUX_PAGE_SHIFT)
#define COMMAND_LINE_SIZE 	1024

struct param_struct {
    union {
	struct {
	    unsigned long page_size;			/*  0 */
	    unsigned long nr_pages;				/*  4 */
	    unsigned long ramdisk_size;			/*  8 */
	    unsigned long flags;				/* 12 */
#define FLAG_READONLY	1
#define FLAG_RDLOAD		4
#define FLAG_RDPROMPT	8
	    unsigned long rootdev;				/* 16 */
	    unsigned long video_num_cols;		/* 20 */
	    unsigned long video_num_rows;		/* 24 */
	    unsigned long video_x;				/* 28 */
	    unsigned long video_y;				/* 32 */
	    unsigned long memc_control_reg;		/* 36 */
	    unsigned char sounddefault;			/* 40 */
	    unsigned char adfsdrives;			/* 41 */
	    unsigned char bytes_per_char_h;		/* 42 */
	    unsigned char bytes_per_char_v;		/* 43 */
	    unsigned long pages_in_bank[4];		/* 44 */
	    unsigned long pages_in_vram;		/* 60 */
	    unsigned long initrd_start;			/* 64 */
	    unsigned long initrd_size;			/* 68 */
	    unsigned long rd_start;				/* 72 */
	    unsigned long system_rev;			/* 76 */
	    unsigned long system_serial_low;	/* 80 */
	    unsigned long system_serial_high;	/* 84 */
	    unsigned long mem_fclk_21285;       /* 88 */
	} s;
	char unused[256];
    } u1;
    union {
	char paths[8][128];
	struct {
	    unsigned long magic;
	    char n[1024 - sizeof(unsigned long)];
	} s;
    } u2;
    char commandline[COMMAND_LINE_SIZE];
};

extern void  call_linux(U32 a0, U32 a1, U32 a2);

/*************************************************************/
static __inline void cpu_arm920_cache_clean_invalidate_all(void)
{
	__asm{
		mov	r1, #0		
		mov	r1, #7 << 5			  	/* 8 segments */
cache_clean_loop1:		
		orr	r3, r1, #63UL << 26	  	/* 64 entries */
cache_clean_loop2:	
		mcr	p15, 0, r3, c7, c14, 2	/* clean & invalidate D index */
		subs	r3, r3, #1 << 26
		bcs	cache_clean_loop2		/* entries 64 to 0 */
		subs	r1, r1, #1 << 5
		bcs	cache_clean_loop1		/* segments 7 to 0 */
		mcr	p15, 0, r1, c7, c5, 0	/* invalidate I cache */
		mcr	p15, 0, r1, c7, c10, 4	/* drain WB */
	}
}
void cache_clean_invalidate(void)
{
	cpu_arm920_cache_clean_invalidate_all();
}

static __inline void cpu_arm920_tlb_invalidate_all(void)
{
	__asm{
		mov	r0, #0
		mcr	p15, 0, r0, c7, c10, 4	/* drain WB */
		mcr	p15, 0, r0, c8, c7, 0	/* invalidate I & D TLBs */
	}
}

void tlb_invalidate(void)
{
	cpu_arm920_tlb_invalidate_all();
}

void disable_irq(void);

void call_linux(U32 a0, U32 a1, U32 a2)
{
	void (*goto_start)(U32, U32);
	
	rINTMSK=BIT_ALLMSK;
	
	cache_clean_invalidate();
	tlb_invalidate();	

	__asm{
//		mov	r0, a0//%0
//		mov	r1, a1//%1
//		mov	r2, a2//%2
		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
		/* no outpus */
		//: "r" (a0), "r" (a1), "r" (a2)
	}
//	SetClockDivider(1, 1);
//	SetSysFclk(FCLK_200M);		//start kernel, use 200M
	//SET_IF();
	goto_start = (void (*)(U32, U32))a2;
	(*goto_start)(a0, a1);	
}

extern int sprintf(char * /*s*/, const char * /*format*/, ...);
extern int CheckBadBlk(U32 addr);
static void LoadRun(void)
{
	U32 i, ram_addr, buf = boot_params.run_addr.val;
	struct param_struct *params = (struct param_struct *)0x30000100;
	struct Partition *nf_part;
	int size;
	
	memset(params, 0, sizeof(struct param_struct));


	if(boot_params.start.val) {
		char parameters[512];
		char *rootfs;
		char initrd[32];
		char *tty_sel;
		char *devfs_sel;
		char *display_sel;
		
		switch (boot_params.root_sel.val) {
		case 0:
			rootfs = "/dev/ram";
			break;
		case 1:
			rootfs = "nfs";
			break;
		case 2:
			rootfs = "/dev/mtdblock2"; //    by pht.
			break;
		case 3:
			rootfs = "/dev/mtdblock3";
			break;
		case 4:
			rootfs = "/dev/mtdblock4";
			break;
		default:
			rootfs="";	//user define
			break;
		}
		
		switch (boot_params.display_sel.val) {
		case 0:
			display_sel = "display=sam320";
			break;
		case 1:
			display_sel = "display=vga640";
			break;
		case 2:
			display_sel = "display=vga800";
			break;			
		default:
			display_sel = "display=sam640";	
			break;
		}
	
	
	
	
	
		if(boot_params.root_sel.val)
			sprintf(initrd, "load_ramdisk=0");
		else
			sprintf(initrd, "initrd=0x%08x,0x%08x",
						boot_params.initrd_addr.val,
						boot_params.initrd_len.val);
	
		switch (boot_params.tty_sel.val) {
		case 0:
			tty_sel="ttySAC0";
			break;
		case 1:
			tty_sel="ttySAC1";
			break;
		case 2:
			tty_sel="ttyS0";
			break;
		case 3:
			tty_sel="ttyS1";
			break;
		default:
			tty_sel="ttySAC0";	//user define
			break;
		}
	

		devfs_sel = "devfs=mount";

		
		memset(parameters, 0, sizeof(parameters));
		sprintf(parameters,
					"root=%s init=/linuxrc %s console=%s,%d mem=%dK %s %s %s",
					rootfs,
					initrd,
					tty_sel,
					boot_params.serial_baud.val,
					boot_params.mem_cfg.val>>10,
					devfs_sel,
					display_sel,
					boot_params.string);
		
		params->u1.s.page_size = LINUX_PAGE_SIZE;
		params->u1.s.nr_pages = (boot_params.mem_cfg.val >> LINUX_PAGE_SHIFT);
		memcpy(params->commandline, parameters, strlen(parameters));
	
		printf("Set boot params = %s\n", params->commandline);
	}

	printf("Load Kernel...\n");	

	
	
	nf_part = NandSelPart_2("kernel");	
	if(!nf_part)
		return;	
	StartPage = nf_part->offset>>11;
	size = nf_part->size;
	ram_addr = buf;	

	for(i=0; size>0; ) {
		if(!(i&0x3f)) {
			if(CheckBadBlk(i+StartPage)) {
				printf("Skipped bad block at 0x%x\n", i+StartPage);
				i += 64;
				size -= 64<<11;
				continue;
			}
		}
		ReadPage((i+StartPage), (U8 *)ram_addr);
		i++;
		size -= 2048;
		ram_addr += 2048;
	}

	
	if(!boot_params.root_sel.val) {
		int ramdisk_sz;
		
		printf("Load Ramdisk...\n");
		
		StartPage = NandPart[3].offset>>11;
		size = NandPart[3].size;
		
		ram_addr = boot_params.initrd_addr.val;
		ramdisk_sz = boot_params.initrd_len.val;
		
		for(i=0; size>0&&ramdisk_sz>0; ) {
			if(!(i&0x3f)) {
				if(CheckBadBlk(i+StartPage)) {
					printf("Skipped bad block at 0x%x\n", i+StartPage);
					i += 64;
					size -= 64<<9;
					continue;
				}
			}
			ReadPage((i+StartPage), (U8 *)ram_addr);
			i++;
			size -= 2048;
			ram_addr += 2048;
			ramdisk_sz -= 2048;
		}
	}
	
	DsNandFlash();

		//ChangeClockDivider(13,12);
		//ChangeMPllValue(67,1,1);	//300MHz,2440A!
		//rCLKCON = 0x7fff0;
	call_linux(0, boot_params.machine.val, buf);
}

/***************** boot wince ***********************/
extern MemoryTest(void);
int RelocateNKBIN(U32 img_src, U32 *pStart, U32 *pLength, U32 *pLaunch);


static void LoadRunApp()
{
	U32 i, ram_addr, buf = boot_params.initrd_addr.val;
	int size;
	struct Partition *nf_part;
	
	MemoryTest();
	printf("Load Application...\n");	

	
	
	nf_part = NandSelPart_2("MyApp");	
	if(!nf_part)
		return;	
	StartPage = nf_part->offset>>11;
	size = nf_part->size;
	//StartPage = NandPart[1].offset>>11;	//part 2,3...
	//size = NandPart[1].size;//NandPart[boot_params.root_sel.val].size;
	ram_addr = boot_params.AppRun_addr.val;

	for(i=0; size>0; ) {
		if(!(i&0x3f)) {
			if(CheckBadBlk(i+StartPage)) {
				printf("Skipped bad block at 0x%x\n", i+StartPage);
				i += 64;
				//size -= 32<<9;
				continue;
			}
		}
		ReadPage((i+StartPage), (U8 *)ram_addr);
		i++;
		size -= 2048;
		ram_addr += 2048;
	}

	
	printf("run 0x%08x...\n",boot_params.AppRun_addr.val);
	//RelocateNKBIN(buf, &buf, &i, &boot_params.run_addr.val);
	call_linux(0, 0, boot_params.AppRun_addr.val);
}


static void LoadRunWince(void)
{
	U32 i, ram_addr, buf = boot_params.initrd_addr.val;
	int size;
	struct Partition *nf_part;
	
	MemoryTest();
	printf("Load Kernel...\n");	

	
	nf_part = NandSelPart_2("wince");	
	if(!nf_part)
		return;	
	StartPage = nf_part->offset>>11;
	//size = nf_part->size;
	//StartPage = NandPart[5].offset>>11;	//part 2,3...
	size = boot_params.initrd_len.val;//NandPart[boot_params.root_sel.val].size;
	ram_addr = buf;

	for(i=0; size>0; ) {
		if(!(i&0x3f)) {
			if(CheckBadBlk(i+StartPage)) {
				printf("Skipped bad block at 0x%x\n", i+StartPage);
				i += 64;
				//size -= 32<<9;
				continue;
			}
		}
		ReadPage((i+StartPage), (U8 *)ram_addr);
		i++;
		size -= 2048;
		ram_addr += 2048;
	}

	
	printf("run 0x%08x...\n", boot_params.run_addr.val);
	//RelocateNKBIN(buf, &buf, &i, &boot_params.run_addr.val);
	call_linux(0, 0, boot_params.run_addr.val);
}

void NandLoadRun(void)
{
	InitNandFlash(1);
	LoadRun();
	
}
void NandLoadRun_wince(void)
{
	InitNandFlash(1);
	LoadRunWince();
}

void NandLoadRun_App()
{
	InitNandFlash(1);
	LoadRunApp();
}

void AutoNandLoadRun()
{
	InitNandFlash(0);
	switch(boot_params.start.val){
	case 1:
		LoadRunApp();
		break;
	case 2:
		LoadRun();
		break;
	case 3:
		LoadRunWince();	
		break;
	default:
		break;
	}

		
}

⌨️ 快捷键说明

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