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

📄 loadlinux.c

📁 st 芯片的bootloader 源代码和编译好的文件
💻 C
字号:
#include "platform.h"
#include "common.h"
#include "71x_lib.h"
#include "string.h"

/*
 * The new way of passing information: a list of tagged entries
 */

/* The list ends with an ATAG_NONE node. */
#define ATAG_NONE	0x00000000

struct tag_header {
	u32 size;
	u32 tag;
};

/* The list must start with an ATAG_CORE node */
#define ATAG_CORE	0x54410001

struct tag_core {
	u32 flags;		/* bit 0 = read-only */
	u32 pagesize;
	u32 rootdev;
};

/* it is allowed to have multiple ATAG_MEM nodes */
#define ATAG_MEM	0x54410002

struct tag_mem32 {
	u32	size;
	u32	start;	/* physical start address */
};

/* VGA text type displays */
#define ATAG_VIDEOTEXT	0x54410003

struct tag_videotext {
	u8		x;
	u8		y;
	u16		video_page;
	u8		video_mode;
	u8		video_cols;
	u16		video_ega_bx;
	u8		video_lines;
	u8		video_isvga;
	u16		video_points;
};

/* describes how the ramdisk will be used in kernel */
#define ATAG_RAMDISK	0x54410004

struct tag_ramdisk {
	u32 flags;	/* bit 0 = load, bit 1 = prompt */
	u32 size;	/* decompressed ramdisk size in _kilo_ bytes */
	u32 start;	/* starting block of floppy-based RAM disk image */
};

/* describes where the compressed ramdisk image lives (virtual address) */
/*
 * this one accidentally used virtual addresses - as such,
 * its depreciated.
 */
#define ATAG_INITRD	0x54410005

/* describes where the compressed ramdisk image lives (physical address) */
#define ATAG_INITRD2	0x54420005

struct tag_initrd {
	u32 start;	/* physical start address */
	u32 size;	/* size of compressed ramdisk image in bytes */
};

/* board serial number. "64 bits should be enough for everybody" */
#define ATAG_SERIAL	0x54410006

struct tag_serialnr {
	u32 low;
	u32 high;
};

/* board revision */
#define ATAG_REVISION	0x54410007

struct tag_revision {
	u32 rev;
};

/* initial values for vesafb-type framebuffers. see struct screen_info
 * in include/linux/tty.h
 */
#define ATAG_VIDEOLFB	0x54410008

struct tag_videolfb {
	u16		lfb_width;
	u16		lfb_height;
	u16		lfb_depth;
	u16		lfb_linelength;
	u32		lfb_base;
	u32		lfb_size;
	u8		red_size;
	u8		red_pos;
	u8		green_size;
	u8		green_pos;
	u8		blue_size;
	u8		blue_pos;
	u8		rsvd_size;
	u8		rsvd_pos;
};

/* command line: \0 terminated string */
#define ATAG_CMDLINE	0x54410009

struct tag_cmdline {
	char	cmdline[1];	/* this is the minimum size */
};


struct tag {
	struct tag_header hdr;
	union {
		struct tag_core		core;
		struct tag_mem32	mem;
		struct tag_videotext	videotext;
		struct tag_ramdisk	ramdisk;
		struct tag_initrd	initrd;
		struct tag_serialnr	serialnr;
		struct tag_revision	revision;
		struct tag_videolfb	videolfb;
		struct tag_cmdline	cmdline;

	} u;
};

#define tag_next(t)	((struct tag *)((u32 *)(t) + (t)->hdr.size))
#define tag_size(type)	((sizeof(struct tag_header) + sizeof(struct type)) >> 2)

#define LINUX_PARAM_OFFSET 0x100	//offset of embedded SRAM
static char linux_cmd[] = "noinitrd root=/dev/rom0";

static void setup_linux_param(u32 param_base)
{
	struct tag *params = (struct tag *)param_base;

	//Printf("Setup linux parameters at 0x%08lx\n", param_base);

	params->hdr.tag = ATAG_CORE;
	params->hdr.size = tag_size(tag_core);

	params->u.core.flags = 0;
	params->u.core.pagesize = 0;
	params->u.core.rootdev = 0;

	params = tag_next(params);

	params->hdr.tag = ATAG_MEM;
	params->hdr.size = tag_size(tag_mem32);

	params->u.mem.start = 0x62000000; 
	params->u.mem.size = 0x400000;

	params = tag_next(params);

	/* set linux command line */
	params->hdr.tag = ATAG_CMDLINE;
	params->hdr.size = (sizeof(struct tag_header) + strlen(linux_cmd)+1+4)>>2;
	memcpy(params->u.cmdline.cmdline, linux_cmd, strlen(linux_cmd) + 1);
	params = tag_next(params);

	params->hdr.tag = ATAG_NONE;
	params->hdr.size = 0;
}

extern void CALL_KERNEL(unsigned int);

void LoadLinux(int argc, const char **argv)
{
	unsigned int srcaddr;
	unsigned int textaddr,textaddr1,endaddr;
	int errno = 0;

	if (argc == 1)
	{
		srcaddr = 0x60010000; //64K offset
	}
	else if (argc == 2)
	{
		if (!errno)
		if (!Str2Int(argv[1],&srcaddr)) errno = 1;
	}
	else
		errno = 1;

	if (errno ==1 )
	{
		PutString("Invalid Command Arguments!\r\n");
		return;
	}
	
	//zimage offset: 
	//0x24: 01 6f 28 18	--magic number
	//0x28: --text address (62 20 00 00	)
	//0x2c: --end address 
	
	if (*((volatile unsigned int *)(srcaddr+0x24)) != 0x016f2818)
	{
		Printf("Not Compressed zimage!\r\n");
		return;
	}
	
	textaddr = *((volatile unsigned int *)(srcaddr+0x28));
	textaddr1 = textaddr;
	endaddr = *((volatile unsigned int *)(srcaddr+0x2C));
	
	Printf("Copying...");
	while (textaddr <= endaddr)
	{
		*((volatile unsigned short *)textaddr) = *((volatile unsigned short*)srcaddr);
		textaddr += 2;
		srcaddr += 2;
	}
	Printf("end \r\n");

	/*set up linux parameters
	* linux kernel will find and parse these parameters if BOOT_PARAMS()is included in MACH_DESC.
	* Otherwise this pre-setting is not used.
	*/
 	setup_linux_param(0x0 + LINUX_PARAM_OFFSET);
	
	//run zimage
	CALL_KERNEL(textaddr1);
}


/*
   This function is for debug purpose.
   Developer may copy uncompressed image into RAM and then jump directory.
*/
void JumpTo(int argc, const char **argv)
{
	unsigned int jmpaddr;
	int errno = 0;

	if (argc == 2)
	{
		if (!errno)
		if (!Str2Int(argv[1],&jmpaddr)) errno = 1;
	}
	else
		errno = 1;

	if (errno ==1 )
	{
		PutString("Invalid Command Arguments!\r\n");
		return;
	}
 	setup_linux_param(0x0 + LINUX_PARAM_OFFSET);

	CALL_KERNEL(jmpaddr);
}

⌨️ 快捷键说明

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