📄 bios.c
字号:
#include "types.h"#include "bios.h"#include "bioscall.h"#include "board.h"#include "config.h"#include "console.h"#include "utils.h"#include "bootloader.h"extern const unsigned long _rom_base;extern const unsigned long system_table_offset;extern const unsigned long default_table_offset;extern const unsigned char sysinit_data[];extern const unsigned char biosapi_data[];extern const unsigned char setup_data[];extern const unsigned char fdisk_data[];extern const unsigned char tftp_data[];extern const unsigned char gunzip_data[];#define gunzip(inbuf, insize, outbuf, outsize) \ ((GUNZIP *)GUNZIP_ADDR)(inbuf, insize, outbuf, outsize)int sys_init(struct system_table_struct *system_table, unsigned long rom_base, unsigned long dram_base){ typedef int (SYSINIT)(struct system_table_struct *, unsigned long, unsigned long); SYSINIT *sys_init_ptr; memcpy((char *)SRAM_BASE, sysinit_data, 1024 * 3); sys_init_ptr = (SYSINIT *)SRAM_BASE; sys_init_ptr(system_table, rom_base, dram_base); return 0;}int biosapi_init(struct system_table_struct *system_table){ unsigned char *inbuf; unsigned long insize; unsigned char *outbuf; unsigned long outsize; struct biosapi_init_struct init_param; BIOSCALL *fp; /* load gunzip */ memcpy((char *)GUNZIP_ADDR, gunzip_data, 1024 * 10); inbuf = (unsigned char *)biosapi_data; outbuf = (unsigned char *)BIOS_API_ADDR; insize = 0x7fffffff; outsize = 0x7fffffff; gunzip(inbuf, &insize, outbuf, &outsize); init_param.rom_base = _rom_base; init_param.dram_base = DRAM_BASE; init_param.system_table_offset = system_table_offset; init_param.system_table = system_table; fp = (BIOSCALL *)outbuf; return (*fp)(BIOSCALL_INIT, (unsigned long)&init_param); // Init BIOS call}int load_setup(void){ typedef int (SETUP)(void); unsigned char *inbuf; unsigned long insize; unsigned char *outbuf; unsigned long outsize; SETUP *setup_ptr; inbuf = (unsigned char *)setup_data; outbuf = (unsigned char *)SETUP_ADDR; insize = 0x7fffffff; outsize = 0x7fffffff; gunzip(inbuf, &insize, outbuf, &outsize); setup_ptr = (SETUP *)SETUP_ADDR; setup_ptr(); return 0;}int load_fdisk(void){ typedef int (FDISK)(void); unsigned char *inbuf; unsigned long insize; unsigned char *outbuf; unsigned long outsize; FDISK *fdisk_ptr; inbuf = (unsigned char *)fdisk_data; outbuf = (unsigned char *)FDISK_ADDR; insize = 0x7fffffff; outsize = 0x7fffffff; gunzip(inbuf, &insize, outbuf, &outsize); fdisk_ptr = (FDISK *)FDISK_ADDR; fdisk_ptr(); return 0;}int load_tftp(unsigned long mode, unsigned long param){ typedef int (TFTP)(unsigned long, unsigned long); unsigned char *inbuf; unsigned long insize; unsigned char *outbuf; unsigned long outsize; TFTP *tftp_ptr; inbuf = (unsigned char *)tftp_data; outbuf = (unsigned char *)TFTP_ADDR; insize = 0x7fffffff; outsize = 0x7fffffff; gunzip(inbuf, &insize, outbuf, &outsize); tftp_ptr = (TFTP *)TFTP_ADDR; return tftp_ptr(mode, param);}int check_partition(struct partition_struct *partition){ if (partition->flag == PART_FLAG_NONE) { printf("Non-exist Partition!\r\n"); return -1; } if (partition->flag == PART_FLAG_NET) { printf("Network Partition!\r\n"); return -1; } if (partition->type == PART_TYPE_RO) { printf("Read-only Partition!\r\n"); return -1; } return 0;}struct partition_struct *select_partition(struct partition_table_struct *partition_table){ struct partition_struct *partition; int i; printf("\r\n"); for (i = 0; i < PART_MAX_NUM; i++) { partition = &partition_table->partition[i]; printf("Partition %d : ", i + 1); if (partition->flag == PART_FLAG_NONE) { printf("None"); } else { printf("0x%08lx - 0x%08lx" , partition->offset, partition->offset + partition->size - 1); } printf("\r\n"); } do { printf("\r\nUpdate image on which partition (1 - 8) "); i = get_select('1', '8'); printf("\r\n"); if (i < 0) return NULL; partition = &partition_table->partition[i]; } while (check_partition(partition)); return partition;}int setup_uclinux_cmdline(struct partition_struct *partition){ struct tag *tag; char *s; tag = (struct tag *)(partition->param_addr); tag->hdr.tag = ATAG_CORE; tag->hdr.size = 2; if (partition->command_line[0] != '\0') { tag = (struct tag *)((u32 *)tag + tag->hdr.size); tag->hdr.tag = ATAG_CMDLINE; tag->hdr.size = 2 + CMD_LENGTH/sizeof(u32); s = (char *)&(tag->u); memcpy(s, partition->command_line, CMD_LENGTH); s[CMD_LENGTH - 1] = '\0'; } tag = (struct tag *)((u32 *)tag + tag->hdr.size); tag->hdr.tag = ATAG_NONE; tag->hdr.size = 0; return 0;}unsigned char *load_image(struct partition_table_struct *partition_table, struct boot_param_struct *boot_param){ char *inbuf; char *outbuf; char *exec_addr; unsigned long insize; unsigned long outsize; struct partition_struct *partition; int i; i = partition_table->boot_partition; if (i < 0 || i > PART_MAX_NUM) { printf("\r\nNo BOOT partition found!\r\n"); return NULL; } /* prepare buffers */ partition = &partition_table->partition[i]; exec_addr = (char *)(partition->exec_addr); if (partition->flag == PART_FLAG_NET) { printf("\r\nLoading Image From Net ................ \r\n"); insize = load_tftp(BOOT_LOAD_IMAGE, 0); insize = ((insize + 3) & ~0x00000003); if (insize == 0) { printf("\r\nCancel\r\n"); return NULL; } outsize = 0x7fffffff; inbuf = (char *)BUF_ADDR; outbuf = inbuf + insize; if (outbuf < (char *)exec_addr) outbuf = (char *)exec_addr; } else if (partition->flag == PART_FLAG_DISK) { printf("\r\nLoading Image From Disk ............... "); insize = partition->size; if (insize == 0) { printf("Cancel\r\n"); return NULL; } outsize = 0x7fffffff; inbuf = (char *)(_rom_base + partition->offset); outbuf = (char *)BUF_ADDR; if (outbuf < (char *)exec_addr) outbuf = (char *)exec_addr; } else { printf("\r\nNo BOOT partition found!\r\n"); return NULL; } /* load image to ram */ if (partition->gzipped_image) { if (!gunzip(inbuf, &insize, outbuf, &outsize)) { outsize = ((outsize + 3) & ~0x00000003); if (outbuf != (char *)exec_addr) memmove((char *)exec_addr, outbuf, outsize); } else { printf("Gunzip error!\r\n"); return NULL; } } else { if (inbuf != (char *)exec_addr) memmove((char *)exec_addr, inbuf, insize); } printf("Done\r\n"); /* setup boot parameters */ if (partition->image_type == IMAGE_UCLINUX) { boot_param->r0 = 0; boot_param->r1 = MACH_TYPE_SAMSUNG; boot_param->r2 = partition->param_addr; boot_param->r3 = 0; setup_uclinux_cmdline(partition); } else { boot_param->r0 = 0; boot_param->r1 = 0; boot_param->r2 = 0; boot_param->r3 = 0; } return (unsigned char *)(partition->exec_addr);}int main_menu(const char *password){ int list[] = { BOOT_BIOS_SETUP, BOOT_RUN_FDISK, BOOT_LOAD_IMAGE, BOOT_UPDATE_IMAGE, BOOT_REBOOT }; int select; if ((password != NULL) && (password[0] != '\0')) { char s[PASSWD_LENGTH]; printf("\r\n"); do { printf("Password: "); getpass(s, PASSWD_LENGTH, '*'); printf("\r\n"); } while (strncmp(password, s, PASSWD_LENGTH)); } printf("\r\n\r\nMain Menu\r\n\r\n"); printf("1 - BIOS Setup\r\n"); printf("2 - Run Fdisk\r\n"); printf("3 - Load Image\r\n"); printf("4 - Update Image\r\n"); printf("5 - Reboot\r\n"); printf("\r\nPlease Select "); while ( (select = get_select('1', '5')) < 0); printf("\r\n"); return list[select];}/* * Main BIOS functions */unsigned char *bios_main(struct boot_param_struct *boot_param){ struct system_table_struct *system_table; struct partition_table_struct *partition_table; struct partition_struct *partition; unsigned char *exec_addr; unsigned long startup_mode; int i, ch, first_menu; console_init(); printf("\r\n\r\n"); printf("Compex BIOS for SAMSUNG S3C4510B v1.20-lt72\r\n\r\n"); system_table = (struct system_table_struct *) (_rom_base + system_table_offset); printf("Press Enter for Menu, Esc for Safe Mode\r\n"); startup_mode = 0; for (i = 0; i < 10000; i++) { if (!kbhit()) continue; ch = getch(); if (ch == KEY_ENTER) { startup_mode = 1; break; } else if (ch == KEY_ESC) { system_table = (struct system_table_struct *) (_rom_base + default_table_offset); printf("Chosen Safe Mode\r\n"); break; } } partition_table = (struct partition_table_struct *) (_rom_base + system_table->partition_table_offset); printf("\r\nInitializing system .... "); sys_init(system_table, _rom_base, DRAM_BASE); printf("Done\r\n"); biosapi_init(system_table); if (startup_mode) startup_mode = BOOT_MENU; else startup_mode = bios_startup_mode(); first_menu = 1; while (1) { bios_set_userflag(USERFLAG_NONE); switch (startup_mode) { case BOOT_MENU: if (first_menu) { first_menu = 0; startup_mode = main_menu(system_table->password); } else startup_mode = main_menu(NULL); break; case BOOT_BIOS_SETUP: load_setup(); startup_mode = BOOT_MENU; break; case BOOT_RUN_FDISK: load_fdisk(); startup_mode = BOOT_MENU; break; case BOOT_LOAD_IMAGE: exec_addr = load_image(partition_table, boot_param); if (exec_addr != NULL) { /* setup CPU parameters */ boot_param->reg_clkcon = system_table->cpu.reg_clkcon; boot_param->reg_syscfg = system_table->cpu.reg_syscfg; return exec_addr; } startup_mode = BOOT_MENU; break; case BOOT_UPDATE_IMAGE: partition = select_partition(partition_table); if (partition != NULL) load_tftp(startup_mode, (unsigned long)partition); startup_mode = BOOT_MENU; break; case BOOT_REBOOT: bios_reboot(); startup_mode = BOOT_MENU; break; default: startup_mode = BOOT_MENU; break; } switch (bios_get_userflag()) { case USERFLAG_MEMORY: printf("\r\nMemory configuration changed, reboot? (Y/n) "); if (get_yes_no(1)) { printf("\r\n"); bios_reboot(); } else printf("\r\n"); break; case USERFLAG_BIOS: printf("\r\nBIOS default loaded, reboot? (Y/n) "); if (get_yes_no(1)) { printf("\r\n"); bios_reboot(); } else printf("\r\n"); break; default: break; } } return (unsigned char *)_rom_base;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -