project : startup Linux in ViVi
struction : the code for startup Linux in ViVi.
(1) first, we look at the memory map as following chart:
-- _________________________________0x3400_0000 ( total: 64 M )
-- | ViVi (1M) |
-- |___________________________|____0x33F0_0000 ( ViViRAM_BASE)
-- | Heap (1M) |
-- |___________________________|____0x33E0_0000 ( Heap_BASE )
-- | MMU Table (16K) |
-- |___________________________|____0x33DF_C000 ( MMU_Table_BASE )
-- | Priviate Data(16K x 3) |
-- |___________________________|____0x33DF_0000 ( ViVi_Priv_RAM_BASE )
-- | Stack (32K) |
-- |___________________________|____0x33DE_8000 ( STACK_BASE )
-- | |
-- | 61.90625 (M) |
-- | |
-- |___________________________|____0x3000_0000 ( RAM_BASE )
vivi Priviate Data && Linux Command Line && MTD Param Arrange :
-- _______________________________0x33DF_C000 ( MMU_Table_BASE )
-- | Linux_cmd_line |--> 16K linux cmd
-- |___________________________|__0x33DF_8000
-- | |
-- | |
-- | vivi_parameter_t [] |
-- |___________________________|____0x33DF_4016
-- | nb_params |--->number of params (8 bytes)
-- |___________________________|___ 0x33DF_4008
-- | "VIVIPARA" |--->vivi_param_magic (8 bytes)
-- |___________________________|____0x33DF_4000 (VIVI PARAMETER TABLE)
-- | |
-- | |
-- | mtd_partiton [] |
-- |___________________________|____0x33DF_0016
-- | nb_mtd_parts |--->number of mtd parts (8 bytes)
-- |___________________________|___ 0x33DF_0008
-- | "VIVIMTDP" |--->mtd__part_magic (8 bytes)
-- |___________________________|____0x33DF_0000 (VIVI MTD PARAM)
Linux Kernel Starting ADDR && Startup Param &&
-- |___________________________|____0x33DE_8000 ( STACK_BASE )
-- | |
-- | |
-- | |
-- | |
-- |___________________________|_____0x3020_8000
-- | Kernel Size |
-- | |----> (2M bytes)
-- |___________________________|_____0x3000_8000 ( Linux kernel offset )
-- | param_struct |
-- | (as below struct) |
-- |___________________________|____0x3000_0100 ( Linux startup Param )
-- | |
-- |___________________________|____0x3000_0000 ( RAM_BASE )
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/* This is the old deprecated way to pass parameters to the kernel */
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];
};
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
(2) Code fragment for starup Linux_kernel in ViVi.
int boot_kernel(ulong from, size_t size, int media_type)
{
int ret;
ulong boot_mem_base; /* base address of bootable memory*/
ulong to;
ulong mach_type;
boot_mem_base = get_param_value("boot_mem_base", &ret); // here boot_mem_base=0x3000_0000
if (ret) {
printk("Can't get base address of bootable memory\n");
printk("Get default DRAM address. (0x%08lx\n", DRAM_BASE);
boot_mem_base = DRAM_BASE;
}
/* copy kerne image */
to = boot_mem_base + LINUX_KERNEL_OFFSET; //here to=0x3000_8000
printk("Copy linux kernel from 0x%08lx to 0x%08lx, size = 0x%08lx ... ",
from, to, size);
ret = copy_kernel_img(to, (char *)from, size, media_type); // "from" addr is the kernel area in nand flash
if (ret) {
printk("failed\n");
return -1;
} else {
printk("done\n");
}
if (*(ulong *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) { // Compressed or not
printk("Warning: this binary is not compressed linux kernel image\n");
printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
} else {
printk("zImage magic = 0x%08lx\n", *(ulong *)(to + 9*4));
}
/* Setup linux parameters and linux command line */
setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET); // see function setup_linux_param
/* Get machine type */
mach_type = get_param_value("mach_type", &ret); //see default_vivi_parameters[]
printk("MACH_TYPE = %d\n", mach_type);
/* Go Go Go */
printk("NOW, Booting Linux......\n");
call_linux(0, mach_type, to); //see function call_linux, r0=0; r1=mach_type; r2=to(here is linux kernel addr)
return 0;
}
vivi_parameter_t default_vivi_parameters[] = {
{ "mach_type", MACH_TYPE, NULL },
{ "media_type", MT_S3C2440, NULL },
{ "boot_mem_base", 0x30000000, NULL },
{ "baudrate", UART_BAUD_RATE, NULL },
{ "xmodem", 1, NULL },
{ "xmodem_one_nak", 0, NULL },
{ "xmodem_initial_timeout", 300000, NULL },
{ "xmodem_timeout", 1000000, NULL },
{ "boot_delay", 0x1000000, NULL }
};
static void setup_linux_param(ulong param_base)
{
struct param_struct *params = (struct param_struct *)param_base; // param_base=0x3000_0100
char *linux_cmd;
printk("Setup linux parameters at 0x%08lx\n", param_base);
memset(params, 0, sizeof(struct param_struct));
params->u1.s.page_size = LINUX_PAGE_SIZE; // LINUX_PAGE_SIZE=4K
params->u1.s.nr_pages = (DRAM_SIZE >> LINUX_PAGE_SHIFT); // nr_pages: 0x4000=(64K >> 12)
/* set linux command line */
linux_cmd = get_linux_cmd_line(); // the command lied at 0x33DF_8000~0x33DF_C000 (16K)
if (linux_cmd == NULL) {
printk("Wrong magic: could not found linux command line\n");
} else {
memcpy(params->commandline, linux_cmd, strlen(linux_cmd) + 1);
printk("linux command line is: \"%s\"\n", linux_cmd);
}
}
void call_linux(long a0, long a1, long a2)
{
cache_clean_invalidate();
tlb_invalidate();
__asm__(
"mov r0, %0\n"
"mov r1, %1\n"
"mov r2, %2\n"
"mov ip, #0\n"
"mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */
"mcr p15, 0, ip, c7, c7, 0\n" /* invalidate I,D caches */
"mcr p15, 0, ip, c7, c10, 4\n" /* drain write buffer */
"mcr p15, 0, ip, c8, c7, 0\n" /* invalidate I,D TLBs */
"mrc p15, 0, ip, c1, c0, 0\n" /* get control register */
"bic ip, ip, #0x0001\n" /* disable MMU */
"mcr p15, 0, ip, c1, c0, 0\n" /* write control register */
"mov pc, r2\n"
"nop\n"
"nop\n"
: /* no outpus */
: "r" (a0), "r" (a1), "r" (a2)
);
}
阅读(1132) | 评论(0) | 转发(0) |