📄 boot.c
字号:
/***************************************** Copyright (c) 2002-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader */#include "config.h"#include "util.h"#include "uart.h"#include "hardware.h"#include "em86xxapi.h"#include "io.h"#include "romfs.h"#include "flash.h"#include "ide.h"#include "bootcd.h"#include "net.h"#include "net_ipv4.h"#include "bootmenu.h"#include "bootconfig.h"#include "memcfg.h"#ifdef CONFIG_ENABLE_FIP#include "fip.h"extern const char *fiptext;#endif#ifdef CONFIG_ENABLE_DVI#define ALLOW_OS_CODE 1#include "../../rmdef/rmdef.h"#include "../../emhwlib_hal/i2c/include/i2c_hal.h"#endifextern unsigned long dram0_size;extern memcfg_t *memcfg_ptr;extern void do_boot_prog(unsigned int) __attribute__ ((noreturn));//// function prototypes// // every functions return 0 if failed. otherwise they don't return control to caller. //int doboot_romfs_rom(unsigned int loadaddr);int doboot_romfs_ram(unsigned int loadaddr);int doboot_ide(int drive, int part, int subpart, unsigned int loadaddr);int doboot_idedisk(unsigned int loadaddr);int doboot_cd(int drive, unsigned int loadaddr);int doboot_idecd(unsigned int loadaddr);int doboot_net(unsigned int loadaddr, char *filename);void do_boot(unsigned int addr) __attribute__ ((noreturn));extern unsigned long loadaddr_kernel, loadaddr_kernelfs, loadaddr_romfs;static const char *copy_msg = "Copying binary from 0x%08x to 0x%08x, size %d(0x%x)\n";void do_boot(unsigned int addr) {#if defined(CONFIG_ENABLE_FIP) && defined(CONFIG_ENABLE_IDE) unsigned long key;#endif#ifdef CONFIG_ENABLE_NETWORK extern int net_dev_down(void); net_dev_down();#endif#if defined(CONFIG_ENABLE_FIP) && defined(CONFIG_ENABLE_IDE) key = fip_readkey(); /* See if any buttons is pressed */ if (key == FIP_KEY_EJECT) /* Ejecting the CD */ ide_cdrom_eject(0, key); fip_write_text(0, fiptext = "BOOT", FIP_CENTER);#endif do_boot_prog(addr);}//// Boot from ROMFS//int doboot_romfs_rom(unsigned int loadaddr){ unsigned int addr = loadaddr ? loadaddr : loadaddr_kernel; if (boot_romfs(addr, LOADER_FLASH_ROMFSADDR, LOADER_FLASH_ROMFSADDR + 0x00040000)) { uart_printf("Boot kernel at 0x%08x with ROMFS at 0x%08x\n", addr, LOADER_FLASH_ROMFSADDR); do_boot(addr); } return 0;}int doload_installablefile(unsigned int loadaddr, unsigned int len, int docksum, int doadj){ unsigned int checksum = 0; if (docksum != 0) checksum = binfile_crc_check((void *)loadaddr, len); if (checksum != 0) return 0; else { unsigned int dest = *((unsigned int *)loadaddr); uart_printf(copy_msg, loadaddr + 2 * sizeof(unsigned long), dest, len - sizeof(void *), len - sizeof(void *)); /* Strip off the header 8 bytes: 4 = dest addr, 4 = checksum */ memcpy((void *)UNCACHED(dest), (void *)(loadaddr + 2 * sizeof(unsigned long)), len - 2 * sizeof(unsigned long)); /* If adjustment of memcfg need to be made */ if (doadj != 0) { memcfg_ptr->dram0_fixed_topreserved = memcfg_ptr->dram0_size + DRAM0_BASE - dest; if (memcfg_ptr->dram0_removable_topreserved != 0) memcfg_ptr->dram0_removable_topreserved -= memcfg_ptr->dram0_fixed_topreserved; gen_memcfg_checksum(memcfg_ptr); /* Compute and set the checksum value */ } } return 1;}int doload_romfs_installablefile(char *name, unsigned int loadaddr, int doadj){ unsigned int len = load_romfs_file(name, loadaddr, LOADER_FLASH_ROMFSADDR, LOADER_FLASH_ROMFSADDR + 0x00040000, 1); if (len == 0) return 0; return(doload_installablefile(loadaddr, len, 1, doadj));}#if defined(CONFIG_ENABLE_FLASH) && defined(CONFIG_ENABLE_VSYNCPARAM)int doload_vsyncparam(unsigned int dest, int docksum){ unsigned int checksum = 0; unsigned int startaddr; flash_probe(LOADER_FLASHBASE, 1, 0); /* In case the flash hasn't been probed */ startaddr = LOADER_FLASHBASE + flash_getsize() - (MAX_USERPREF_SIZE / 2); /* Last 32KB of flash */ if (docksum != 0) checksum = binfile_crc_check((void *)startaddr, MAX_USERPREF_SIZE / 2); if ((checksum == 0) && (dest != 0)) { uart_printf(copy_msg, startaddr, dest, MAX_USERPREF_SIZE / 2, MAX_USERPREF_SIZE / 2); memcpy((void *)dest, (void *)startaddr, MAX_USERPREF_SIZE / 2); return 1; } return 0;}#endif#ifdef CONFIG_ENABLE_IRQHANDLERextern const char *irqhandler_init_msg;int doload_irqhandler(unsigned int loadaddr, unsigned int len, int docksum){ unsigned int checksum = 0; if (docksum != 0) checksum = binfile_crc_check((void *)loadaddr, len); if (checksum == 0) { typedef void (*FUNCPTR)(void); unsigned long dest = *(unsigned int *)(loadaddr + sizeof(unsigned int)); FUNCPTR irqhandler_entry = (FUNCPTR)dest; /* Offset by 4 */ if (dest == 0) return 0; uart_printf(irqhandler_init_msg, (unsigned long)irqhandler_entry); (*irqhandler_entry)(); return 1; } return 0;}int doload_romfs_irqhandler(unsigned int loadaddr){ unsigned int len = load_romfs_file(DEFAULT_IRQHANDLER_FILENAME, loadaddr, LOADER_FLASH_ROMFSADDR, LOADER_FLASH_ROMFSADDR + 0x00040000, 1); if (len == 0) return 0; return(doload_irqhandler(loadaddr, len, 1));}#endif#ifdef CONFIG_ENABLE_BITMAPSint doload_bitmap(unsigned int loadaddr, unsigned int len, int docksum){ unsigned int checksum = 0; if (docksum != 0) checksum = binfile_crc_check((void *)loadaddr, len); if (checksum != 0) return 0; else { unsigned int *newaddr = (unsigned int *)(loadaddr); unsigned int i; unsigned int top_removable_size = 0; while (newaddr < (unsigned int *)(loadaddr + len) - sizeof(unsigned int)) { unsigned long dest, len, type; type = (unsigned long)*newaddr; newaddr++; dest = (unsigned long)*newaddr; newaddr++; len = (unsigned long)*newaddr; newaddr++; if (dest > UNCACHED(DRAM0_BASE)) { unsigned int dram0_base = UNCACHED(DRAM0_BASE); if (dest > DRAM0_BASE) dram0_base = DRAM0_BASE; if (dram0_base + memcfg_ptr->dram0_size - dest > top_removable_size) top_removable_size = UNCACHED(DRAM0_BASE) + memcfg_ptr->dram0_size - dest; } switch(type) { case 0x44454c52: //RLED uart_printf("Decompressing RLED section to 0x%08lx, from 0x%08lx, size %d (0x%x)\n", dest, newaddr, len, len); uart_printf("Decompressed size of RLED section is 0x%08lx\n", bmp_inflate((unsigned char*)newaddr, (unsigned char*)dest, len)); newaddr += ((len+sizeof(unsigned int)-1) / sizeof(unsigned int)); break; case 0x44574152: //RAWD uart_printf("Copying RAWD section to 0x%08lx, from 0x%08lx, size %d (0x%x)\n", dest, newaddr, len, len); if (dest < UNCACHED(DRAM0_BASE)) { for (i = 0; i < len/sizeof(unsigned int); i++) { __raw_writel(*newaddr, dest); newaddr++; dest+=sizeof(unsigned int); } } else { if ((UNCACHED(dest) + len) > (UNCACHED(DRAM0_BASE) + memcfg_ptr->dram0_size - memcfg_ptr->dram0_fixed_topreserved)) { uart_puts("Warning: section too big ("); if (memcfg_ptr->dram0_fixed_topreserved) uart_puts("override top fixed reserved area).\n"); else uart_puts("beyond DRAM0 boundary).\n"); } memcpy((void *)dest, (void *)newaddr, len); newaddr += len/sizeof(unsigned int); } break; default: uart_printf("Inavalid section identifier found at 0x%08lx\n", newaddr-3); return 0; } } memcfg_ptr->dram0_removable_topreserved = top_removable_size; gen_memcfg_checksum(memcfg_ptr); /* Compute and set the checksum value */ } return 1;}int doload_romfs_bitmap(char *name, unsigned int loadaddr){ unsigned int len = load_romfs_file(name, loadaddr, LOADER_FLASH_ROMFSADDR, LOADER_FLASH_ROMFSADDR + 0x00040000, 1); if (len == 0) return 0; return(doload_bitmap(loadaddr, len, 1));}#endif#ifdef CONFIG_ENABLE_UCODESint doload_ucode(unsigned int loadaddr, unsigned int len, int docksum){ unsigned int checksum = 0; unsigned int dest; if (docksum != 0) checksum = binfile_crc_check((void *)loadaddr, len); if (checksum != 0) return 0; dest = DRAM0_BASE + memcfg_ptr->dram0_size - len; uart_printf(copy_msg, loadaddr, dest, len, len); memcpy((void *)UNCACHED(dest), (void *)(loadaddr), len); memcfg_ptr->dram0_fixed_topreserved = len; gen_memcfg_checksum(memcfg_ptr); /* Compute and set the checksum value */ return 1;}int doload_romfs_ucode(char *name, unsigned int loadaddr){ unsigned int len = load_romfs_file(name, loadaddr, LOADER_FLASH_ROMFSADDR, LOADER_FLASH_ROMFSADDR + 0x00040000, 1); if (len == 0) return 0; return(doload_ucode(loadaddr, len, 1));}#endif#ifdef CONFIG_ENABLE_DVIint doload_dvi(unsigned int loadaddr, unsigned int len, int docksum){ unsigned int checksum = 0; unsigned int *newaddr = (unsigned int *)(loadaddr); struct i2c i2c_info; RMstatus err; if (docksum != 0) checksum = binfile_crc_check((void *)loadaddr, len); if (checksum != 0) return 0; i2c_info.pGBus = (struct gbus *) 1; i2c_info.RegBase = REG_BASE_SYSTEM; i2c_info.PioClock = (unsigned char)*newaddr; newaddr++; i2c_info.PioData = (unsigned char)*newaddr; newaddr++; i2c_info.DelayUs = (unsigned long)*newaddr; newaddr++; i2c_info.WrAddr = (unsigned char)*newaddr; newaddr++; i2c_info.RdAddr = (unsigned char)*newaddr; newaddr++; while (newaddr < (unsigned int *) (loadaddr + len - 4)) { unsigned char addr, val; addr = (unsigned char)*newaddr; newaddr++; val = (unsigned char)*newaddr; newaddr++; err = I2C_Write(&i2c_info, addr, &val, 1); if (RMFAILED(err)) { uart_printf("I2C_Write fails: addr: 0x%02x, val: 0x%02x\n", addr, val); return 0; } } return 1;}int doload_romfs_dvi(char *name, unsigned int loadaddr){ unsigned int len = load_romfs_file(name, loadaddr, LOADER_FLASH_ROMFSADDR, LOADER_FLASH_ROMFSADDR + 0x00040000, 1); if (len == 0) return 0; return(doload_dvi(loadaddr, len, 1));}#endif#ifdef CONFIG_ENABLE_FULLFUNCTIONint doboot_romfs_ram(unsigned int loadaddr){ unsigned int addr = loadaddr ? loadaddr : loadaddr_kernelfs; if (boot_romfs(addr, loadaddr_romfs, loadaddr_kernelfs)) { uart_printf("Boot kernel at 0x%08x with ROMFS at 0x%08lx\n", addr, loadaddr_romfs); do_boot(addr); } return 0;}#endif#ifdef CONFIG_ENABLE_IDE//// Boot from IDE device//int doboot_ide(int drive, int part, int subpart, unsigned int loadaddr){ unsigned int addr = loadaddr ? loadaddr : 0; int doboot = 0, type; image_infoblock_t info; type = ide_check_image(drive, part, subpart, &info); switch (type) { case IMAGE_TYPE_NONE : uart_puts("No bootable image found\n"); break; case IMAGE_TYPE_KERNEL : if (addr == 0) addr = loadaddr_kernel; uart_printf("Loading kernel from IDE device, size = %dKB\n", info.u.len >> 10); if (ide_read_image(type, drive, part, subpart, (unsigned char *) addr)) uart_puts("Failed to load kernel image\n"); else { doboot = 1; uart_printf("Boot kernel at 0x%08x with IDE\n", addr); } break; case IMAGE_TYPE_ROMFS : if (addr == 0) addr = loadaddr_kernelfs; uart_printf("Loading ROMFS from IDE device, size = %dKB\n", info.u.len >> 10); if (ide_read_image(type, drive, part, subpart, (unsigned char *) loadaddr_romfs)) uart_puts("Failed to load romfs image\n"); else { if (boot_romfs(addr, loadaddr_romfs, addr)) { doboot = 1; uart_printf("Boot kernel at 0x%08x with ROMFS at 0x%08lx\n", addr, loadaddr_romfs); } } break; } if (doboot) do_boot(addr); return doboot;}int doboot_idedisk(unsigned int loadaddr){ int drive, drives, part; if ((drives = ide_found(IDE_ATA)) == 0) { ide_probe(0x03, 0); drives = ide_found(IDE_ATA); } if (drives == 0) { uart_puts("No IDE device found\n"); return 0; } for (drive = 0; drive < MAX_DRIVES; ++drive) { if (drives & (1 << drive)) { if (ide_probe_image(drive, &part, NULL) != IMAGE_TYPE_NONE) { uart_printf("Found bootable image at drive %d partition %d\n", drive, part); doboot_ide(drive, part, 0, loadaddr); } } } uart_puts("No bootable image found\n"); return 0;}int doboot_cd(int drive, unsigned int loadaddr){ if (loadaddr == 0) loadaddr = loadaddr_kernel; if (bootcd_load_image(drive, loadaddr, NULL) == 0) do_boot(loadaddr); return 0;}int doboot_idecd(unsigned int loadaddr){ int drive, drives; if ((drives = ide_found(IDE_ATAPI)) == 0) { ide_probe(IDE_ALL, 0); drives = ide_found(IDE_ATAPI); } if (drives == 0) { uart_puts("No ATAPI device found\n"); return 0; } for (drive = 0; drive < MAX_DRIVES; ++drive) { if (drives & (1 << drive)) { if (doboot_cd(drive, loadaddr)) break; } } return 0;}#endif#ifdef CONFIG_ENABLE_NETWORK//// Boot from Network//int doboot_net(unsigned loadaddr, char *filename){ extern int bootmenu_net_up(int force); int len; char *fname; if (loadaddr == 0) loadaddr = loadaddr_kernel; if (bootmenu_net_up(0) != 0) return 0; if (!ipv4_ipaddr_valid(g_bootconfig.server)) { uart_puts("Server address is invalid\n"); return 0; } if (filename != NULL) fname = filename; else fname = g_bootconfig.kernel_filename; if (ipv4_tftp(g_bootconfig.server, fname, loadaddr, &len) == 0) { uart_printf("Loaded kernel to 0x%08x, size = %d bytes\n", loadaddr, len); do_boot(loadaddr); } return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -