/* * Load kernel image into entry point address. Assumes that the fs buffer has * been filled. */ static u32 load_kernel(char *cmdline) { u32 entry_point; struct image_header *hdr; if(tfs_load_file("uImage", (u32 *)(0x8000-sizeof(image_header_t))) != 0) return 0; build_params(cmdline, (struct tag *)params_buffer); hdr = (struct image_header *)(0x8000-sizeof(image_header_t)); if(ntohl(hdr->ih_magic) != IH_MAGIC) { db_puts("ERROR: bad magic number\n"); return 0; } #ifdef CHECK_KERNEL_CRC do { u32 checksum; checksum = ntohl(hdr->ih_hcrc); hdr->ih_hcrc = 0; /* check uImage header CRC */ if(crc32(0, (u8 *)hdr, sizeof(image_header_t)) != checksum) { db_puts("ERROR: header CRC mismatch\n"); } /* check uImage data CRC */ checksum = crc32(0, (u8 *)hdr+sizeof(image_header_t), ntohl(hdr->ih_size)); if(checksum != ntohl(hdr->ih_dcrc)) { db_puts("ERROR: bad data CRC\n"); return 0; } } while(0); #endif entry_point = ntohl(hdr->ih_ep); /* Retrieve the kernel image's contents in such a way that the image * header is skipped and the actual start of the kernel sits at the * entry point. */ return entry_point; }
void main(void) { u32 rootfs; char *rfs_txt; u32 image = 0; struct jffs2_raw_inode *node, *mfg_node; char *cmdline = 0, *altcmdline = 0; u32 kernel_nand_addr = 0, alt_kernel_nand_addr = 0; int board_id; int done = 0; u32 ret = 0; #ifdef CPU_LF1000 /* disable the USB controller */ BIT_SET(REG16(LF1000_UDC_BASE+UDC_PCR), PCE); #endif adc_init(); board_id = load_board_id(); display_backlight(board_id); clock_init(); db_init(); display_init(); fbcon_init(); db_displaytee(1); db_puts("************************************************\n"); db_puts("* *\n"); db_puts("* OpenDidj lightning-boot 1.1 / 12 Mar 2010 *\n"); db_puts("* *\n"); db_puts("************************************************\n"); db_puts("\n\n"); #ifdef CONFIG_MACH_LF_LF1000 /* now that backlight is on, see if we have enough battery to boot */ if(gpio_get_val(LOW_BATT_PORT, LOW_BATT_PIN) == 0 && ADC_TO_MV(adc_get_reading(LF1000_ADC_VBATSENSE)) < BOOT_MIN_MV){ db_puts("PANIC: battery voltage too low!\n"); die(); } #endif /* CONFIG_MACH_LF_LF1000 */ #ifdef UBOOT_SUPPORT if(((REG32(LF1000_GPIO_BASE+GPIOCPAD) & BUTTON_MSK) == BUTTON_MSK)) { do { db_puts("xmodem download mode\n"); timer_init(); offset = 0; xmodemInit(db_putchar,db_getc_async); tmr_poll_start(2000); db_puts("Switch to 115200 baud and press any button\n"); db_puts("to start XModem download...\n"); /* set the baud rate */ #define UART16(r) REG16(LF1000_SYS_UART_BASE+r) UART16(BRD) = 1; /* FIXME (for now "1" sets 115200 baud , "11" sets 19200 baud) */ UART16(UARTCLKGEN) = ((UARTDIV-1)<<UARTCLKDIV)|(UART_PLL<<UARTCLKSRCSEL); if(tfs_load_summary(sum_buffer, BOOT0_ADDR) != 0) { db_puts("trying BOOT1\n"); if(tfs_load_summary(sum_buffer, BOOT1_ADDR)) { db_puts("u-boot not found\n"); break; } } while (!done) { if (tmr_poll_has_expired()){ if(((REG32(LF1000_GPIO_BASE+GPIOCPAD) & BUTTON_MSK) != BUTTON_MSK)) { db_displaytee(0); ret = xmodemReceive(ubcopy); db_displaytee(1); if ( ret >= 0 ) break; } if (ret == -1) db_puts("XMODEM_ERROR : REMOTECANCEL\n"); if (ret == -2) db_puts("XMODEM_ERROR : OUTOFSYNC\n"); if (ret == -3) db_puts("XMODEM_ERROR : RETRYEXCEED\n"); if ( ret < 0 ) continue; /* db_puts("Loaded : "); db_int(ret); db_puts("bytes\n"); */ } } db_puts("\n\nXModem download complete.\n"); db_puts("Transferring control to U-Boot.\n"); /* jump to u-boot */ ((void (*)( int r0, int r1, int r2))UBOOT_ADDR) (0, MACH_TYPE_LF1000, 0); /* never get here! */ die(); } while(0); } #endif /* UBOOT_SUPPORT */ /* Set up the kernel command line */ /* read entire /flags partition */ nand_read(fs_buffer, BOOT_FLAGS_ADDR, BOOT_FLAGS_SIZE); /* find rootfs file */ node = jffs2_cat((char *)fs_buffer, BOOT_FLAGS_SIZE, "rootfs"); rootfs = RFS0; if(node == 0) { db_puts("warning: failed to find rootfs flags!\n"); } else { rfs_txt = (char*)node+sizeof(struct jffs2_raw_inode)-4; if(!strncmp(rfs_txt, "RFS1", 4)) { db_puts("booting RFS1\n"); rootfs = RFS1; } #ifdef NFS_SUPPORT else if(!strncmp(rfs_txt, "NFS0", 4)) { db_puts("booting NFS0\n"); rootfs = NFS0; } else if(!strncmp(rfs_txt, "NFS1", 4)) { db_puts("booting NFS1\n"); rootfs = NFS1; } #endif /* NFS_SUPPORT */ else { db_puts("booting RFS0\n"); } } /* Find the mfcart file */ mfg_node = jffs2_cat((char *)fs_buffer, BOOT_FLAGS_SIZE, "mfcart"); if(mfg_node != 0) { db_puts("Booting with mfg cartridge layout.\n"); } /* construct the command line */ if(mfg_node == 0) { if(rootfs == RFS0) { cmdline = CMDLINE_BASE CMDLINE_RFS0 CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS1 CMDLINE_UBI; kernel_nand_addr = BOOT0_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } else if(rootfs == RFS1) { cmdline = CMDLINE_BASE CMDLINE_RFS1 CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS0 CMDLINE_UBI; kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT0_ADDR; } #ifdef NFS_SUPPORT else if(rootfs == NFS0) { cmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; kernel_nand_addr = BOOT0_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } else if(rootfs == NFS1) { cmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT0_ADDR; } #endif /* NFS_SUPPORT */ } else { if(rootfs == RFS0) { cmdline = CMDLINE_BASE CMDLINE_RFS0 CMDLINE_MFG CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS1 CMDLINE_MFG CMDLINE_UBI; kernel_nand_addr = BOOT0_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } else if(rootfs == RFS1) { cmdline = CMDLINE_BASE CMDLINE_RFS1 CMDLINE_MFG CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS0 CMDLINE_MFG CMDLINE_UBI; kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT0_ADDR; } #ifdef NFS_SUPPORT else if(rootfs == NFS0) { cmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_MFG CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_MFG CMDLINE_UBI; kernel_nand_addr = BOOT0_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } else if(rootfs == NFS1) { cmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_MFG CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_MFG CMDLINE_UBI; kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT0_ADDR; } #endif /* NFS_SUPPORT */ } if(tfs_load_summary(sum_buffer, kernel_nand_addr)) { db_puts("warning: booting alternative kernel!\n"); if(tfs_load_summary(sum_buffer, alt_kernel_nand_addr)) { db_puts("PANIC: unable to load alt summary\n"); die(); } } db_stopwatch_start("LOAD KERNEL"); image = load_kernel(cmdline); db_stopwatch_stop(); if(image == 0) { db_puts("Warning: booting alternative kernel!\n"); if(tfs_load_summary(sum_buffer, alt_kernel_nand_addr) != 0) { die(); } image = load_kernel(altcmdline); if(image == 0) { db_puts("PANIC: nothing to boot\n"); die(); } } #ifdef DISPLAY_SUPPORT db_stopwatch_start("SPLASH"); db_puts("Loading bootsplash\n"); tfs_load_file("bootsplash.rgb", (u32 *)FRAME_BUFFER_ADDR); display_init(); db_stopwatch_stop(); #endif load_cart_id(); db_puts("Starting the kernel...\n"); cleanup_for_linux(); /* jump to image (void, architecture ID, atags pointer) */ ((void(*)(int r0, int r1, unsigned int r2))image) (0, MACH_TYPE_LF1000, (unsigned int)params_buffer); /* never get here! */ die(); }
int main(void) { u32 rootfs; u8 *load_address; char *rfs_txt; u32 image = 0; struct jffs2_raw_inode *node, *mfg_node; char *cmdline = 0, *altcmdline = 0; u32 kernel_nand_addr = 0, alt_kernel_nand_addr = 0; int board_id; u32 ret = 0; u32 ret2 = 0; u8 selection = 0; u8 displayOn = 0; unsigned char cSel; #ifdef CPU_LF1000 /* disable the USB controller */ BIT_SET(REG16(LF1000_UDC_BASE+UDC_PCR), PCE); #endif adc_init(); board_id = load_board_id(); display_backlight(board_id); clock_init(); db_init(); #ifdef CONFIG_MACH_LF_LF1000 /* now that backlight is on, see if we have enough battery to boot */ if(gpio_get_val(LOW_BATT_PORT, LOW_BATT_PIN) == 0 && ADC_TO_MV(adc_get_reading(LF1000_ADC_VBATSENSE)) < BOOT_MIN_MV){ display_init(); db_puts("PANIC: battery voltage too low!\n"); guru_med(0xBA77DEAD,0x0BAD0BAD); // die(); } #endif /* CONFIG_MACH_LF_LF1000 */ #ifdef UBOOT_SUPPORT if(((REG32(LF1000_GPIO_BASE+GPIOCPAD) & BUTTON_MSK) == BUTTON_MSK)) { display_init(); displayOn = 1; fbinit(); fbclear(); renderString(5,2,"OpenDidj lightning-boot " LB_VERSION " / " __DATE__ ); renderString(5,4,"Select an option:"); db_puts("OpenDidj lightning-boot " LB_VERSION " / " __DATE__ ); db_puts("\n"); make_crc_table(); timer_init(); offset = 0; // tmr_poll_start(2000); db_puts("Switch to 115200 baud\n"); /* set the baud rate */ UART16(BRD) = 1; /* FIXME (for now "1" sets 115200 baud , "11" sets 19200 baud) */ UART16(UARTCLKGEN) = ((UARTDIV-1)<<UARTCLKDIV)|(UART_PLL<<UARTCLKSRCSEL); // Reggie added for julspower, autoboot if zimage is present on the SD card. ret2 = check_autoboot(&cSel); if ( ret2 == 0 ) { selection=cSel; db_puts("\nAutobooting zImage from SD\n"); goto selection_section; } selection = do_menu(); selection_section: load_address = (u8 *)(UBOOT_ADDR); switch ( selection ) { case 0: goto normal_boot; case 1: goto normal_boot; case 2: goto normal_boot; case 3: xmodemInit(db_putchar,db_getc_async); ret = xmodemReceive(ubcopy); break; case 4: ret = sd_load("u-boot.bin",load_address); break; case 5: ret = sd_load("zImage",load_address); break; case 6: // Reggie added, feature to load lightning-boot.bin from SD // filename *must* be 8.3 or it will fail to load, so lets // make it easy on ourselves and name it lb.bin on the sd load_address = (u8 *)(UBOOT_ADDR2); ret = sd_load("lb.bin",load_address); db_puts("\nLoading Lightning Boot from SD\n"); break; } if ( ret != 0 ) guru_med(selection,ret); db_puts("\nboot jmp\n"); /* jump to u-boot */ ((void (*)( int r0, int r1, int r2))load_address) (0, MACH_TYPE_LF1000, 0); /* never get here! */ guru_med(0x000000F0,0); // die(); } #endif /* UBOOT_SUPPORT */ normal_boot: /* Set up the kernel command line */ /* read entire /flags partition */ nand_read(fs_buffer, BOOT_FLAGS_ADDR, BOOT_FLAGS_SIZE); /* find rootfs file */ node = jffs2_cat((char *)fs_buffer, BOOT_FLAGS_SIZE, "rootfs"); rootfs = RFS0; if(node == 0) { db_puts("warning: failed to find rootfs flags!\n"); } else { rfs_txt = (char*)node+sizeof(struct jffs2_raw_inode)-4; if(!strncmp(rfs_txt, "RFS1", 4)) { db_puts("booting RFS1\n"); // this should be made to use RFS2? rootfs = RFS1; } // Reggie added to check cmdline options, if /flags/rootfs has been set to > RFS1 if (selection==1){ // set to the default SD config just in case the rootfs flag is set for didj(RFS0/1) rootfs = RFS2; db_puts("nand/SD boot\n"); { // if(!strncmp(rfs_txt, "RFS2", 4)) { // db_puts("booting SDRFS\n"); // rootfs = RFS2; // } // else if(!strncmp(rfs_txt, "RFS3", 4)) { if(!strncmp(rfs_txt, "RFS3", 4)) { db_puts("booting nand/SD DEBUG\n"); rootfs = RFS3; } } } #ifdef NFS_SUPPORT else if(!strncmp(rfs_txt, "NFS0", 4)) { db_puts("booting NFS0\n"); rootfs = NFS0; } else if(!strncmp(rfs_txt, "NFS1", 4)) { db_puts("booting NFS1\n"); rootfs = NFS1; } #endif /* NFS_SUPPORT */ else { db_puts("booting RFS0\n"); } } /* Find the mfcart file */ mfg_node = jffs2_cat((char *)fs_buffer, BOOT_FLAGS_SIZE, "mfcart"); if(mfg_node != 0) { db_puts("Booting with mfg cartridge layout.\n"); } else { // Reggie added, setup for custom command line read from /flags/cmdline // try and keep some sanity for the mfcart flag to trump everything, not // sure we really need to worry about the carts at all and could remove // the code? same with the NFS support, although that might come with // future developments if (selection == 2){ rootfs = RFS4; } } /* construct the command line */ if(mfg_node == 0) { if(rootfs == RFS0) { cmdline = CMDLINE_BASE CMDLINE_RFS0 CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS1 CMDLINE_UBI; kernel_nand_addr = BOOT0_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } else if(rootfs == RFS1) { cmdline = CMDLINE_BASE CMDLINE_RFS1 CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS0 CMDLINE_UBI; // Reggie changed, we want to boot the kernel from // kernel0 but the rootfs from RFS1 kernel_nand_addr = BOOT0_ADDR; alt_kernel_nand_addr = BOOT0_ADDR; } // Reggie added, just a copy of the RFS1 boot commands. // the kernel that boots the SD rootfs should be burnt // to kernel1 partition, this way if the SD kernel fails // it will fall back to booting the original kernel0/RFS0 // well, in theory // both RFS2/3 functions boot from the same kernel parition(kernel1) // and the same SD partition (mmcpblk0p2, ext3) // so alt_/kernel_nand_addr are set to BOOT1_ADDR, altcmdline falls // back to the other SD based RFS option else if(rootfs == RFS2) { cmdline = CMDLINE_BASE CMDLINE_RFS2 CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS3 CMDLINE_UBI; kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } else if(rootfs == RFS3) { cmdline = CMDLINE_BASE CMDLINE_RFS3 CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_RFS2 CMDLINE_UBI; kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } // Reggie also added this, code to read custom cmdline from // a file called "cmdline" on the vfat SD partition, mmcblk0p1 else if (rootfs == RFS4){ // look for cmdline in the root of the vfat partition on the // uSD card and load the contents into cmdline_txt cmdline_load("cmdline", (u8 *)cmdline_txt); db_puts(cmdline_txt); cmdline = (char *)cmdline_txt; altcmdline = CMDLINE_BASE CMDLINE_RFS2 CMDLINE_UBI; // always boot the explorer kernel (BOOT1_ADDR) no matter // how the cmdline is constructed kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } #ifdef NFS_SUPPORT else if(rootfs == NFS0) { cmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; kernel_nand_addr = BOOT0_ADDR; alt_kernel_nand_addr = BOOT1_ADDR; } else if(rootfs == NFS1) { cmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; altcmdline = CMDLINE_BASE CMDLINE_NFS CMDLINE_UBI; kernel_nand_addr = BOOT1_ADDR; alt_kernel_nand_addr = BOOT0_ADDR; } #endif /* NFS_SUPPORT */ } if(tfs_load_summary(sum_buffer, kernel_nand_addr)) { db_puts("warning: booting alternative kernel!\n"); if(tfs_load_summary(sum_buffer, alt_kernel_nand_addr)) { db_puts("PANIC: unable to load alt summary\n"); guru_med(0xA0000000,1); //die(); } } db_stopwatch_start("LOAD KERNEL"); if (rootfs==RFS4){ db_puts("RFS4 loading\n"); image = load_kernel(cmdline); } else{ db_puts("normal cmdline\n"); db_puts(cmdline); image = load_kernel(cmdline); } db_stopwatch_stop(); if(image == 0) { db_puts("Warning: booting alternative kernel!\n"); if(tfs_load_summary(sum_buffer, alt_kernel_nand_addr) != 0) { guru_med(0xA0000000,2); //die(); } image = load_kernel(altcmdline); if(image == 0) { db_puts("PANIC: nothing to boot\n"); guru_med(0xA0000000,3); //die(); } } #ifdef DISPLAY_SUPPORT db_stopwatch_start("SPLASH"); db_puts("Loading bootsplash\n"); tfs_load_file("bootsplash.rgb", (u32 *)FRAME_BUFFER_ADDR); if ( !displayOn ) display_init(); mlc_set_video_mode(); //display_init(); db_stopwatch_stop(); #endif load_cart_id(); db_puts("Starting kernel...\n"); cleanup_for_linux(); /* jump to image (void, architecture ID, atags pointer) */ ((void(*)(int r0, int r1, unsigned int r2))image) (0, MACH_TYPE_LF1000, (unsigned int)params_buffer); /* never get here! */ guru_med(0x000000F0,0); //die(); }