📄 bootflash.c
字号:
/***************************************** Copyright (c) 2001-2002 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This is file is part of the Jasper DVD boot loader */#include "config.h"#include "errors.h"#include "uart.h"#include "kunzip.h"/* extract from linux's romfs.txt :The layout of the filesystem is the following:offset content +---+---+---+---+ 0 | - | r | o | m | \ +---+---+---+---+ The ASCII representation of those bytes 4 | 1 | f | s | - | / (i.e. "-rom1fs-") +---+---+---+---+ 8 | full size | The number of accessible bytes in this fs. +---+---+---+---+ 12 | checksum | The checksum of the FIRST 512 BYTES. +---+---+---+---+ 16 | volume name | The zero terminated name of the volume, : : padded to 16 byte boundary. +---+---+---+---+ xx | file | : headers :[...] The following bytes are now part of the file system; each file header must begin on a 16 byte boundary. offset content +---+---+---+---+ 0 | next filehdr|X| The offset of the next file header +---+---+---+---+ (zero if no more files) 4 | spec.info | Info for directories/hard links/devices +---+---+---+---+ 8 | size | The size of this file in bytes +---+---+---+---+ 12 | checksum | Covering the meta data, including the file +---+---+---+---+ name, and padding 16 | file name | The zero terminated name of the file, : : padded to 16 byte boundary +---+---+---+---+ xx | file data | : :Notes:+ Values are big endian. (ie NOT intel)+ Checksum : simple sum of the first 512 bytes (or the number of bytes accessible, whichever is smaller). The applied algorithm is the same as in the AFFS filesystem, namely a simple sum of the longwords (assuming bigendian quantities again). For details, please consult the source.*/typedef struct { unsigned int next; unsigned int info; unsigned int size; unsigned int crc;} file_hdr;static unsigned int swapl(unsigned int l){ unsigned int r; r= (unsigned int)( (((l >> 24) & 0xFF) )| (((l >> 16) & 0xFF) << 8)| (((l >> 8) & 0xFF) << 16)| (((l ) & 0xFF) << 24) ); return r;}static void set_flash_boot_status(int st){ boot_status = (boot_status & ~BOOT_STATUS_FLASH_MASK) | st;}/* Raystatic void set_gz_boot_status(int st){ boot_status = (boot_status & ~BOOT_STATUS_GZ_MASK) | st; }*/static int strncmp(const char *s1, const char *s2, int maxlen){ int i; for(i=0; i<maxlen; i++) { if(s1[i]!=s2[i] || s1[i]==0) return s1[i]; } return 0;}// Lookup file in romfs and return file address (or 0 if no such file)static file_hdr *romfs_lookup(unsigned int *romfs, char *name, int maxlen){ char *filename; char *volume; file_hdr *hdr; unsigned int next; volume = (char *)(romfs+4); // +4 32bits words PrintUart(name,maxlen); PrintUart(" (looking up...)\r\n",30); while(*volume) volume++; hdr = (file_hdr *)(((unsigned int)volume+15) & ~0xF); while(1) { filename = ((char *)hdr) + 16; PrintUart(filename,32); PrintUart("\r\n ",4); next=(swapl(hdr->next)&~0xF) >> 2; if(strncmp(name,filename,maxlen)==0) { PrintUart("Found\r\n",20); return hdr; } if(next==0) { PrintUart("Not Found\r\n",20); return 0; } hdr=(file_hdr *)(romfs+next); }}#define ROMFS_MAGIC_1 ('-' + ('r'<<8) + ('o'<<16) + ('m'<<24))#define ROMFS_MAGIC_2 ('1' + ('f'<<8) + ('s'<<16) + ('-'<<24))// Check the romfs starting at 'addr' (with -romfs- marker)static unsigned int romfs_check(unsigned int *addr){ if(((*addr)==ROMFS_MAGIC_1) && ((*(addr+1))==ROMFS_MAGIC_2)) return 1; else return 0;}// Find the romfs in flash starting from 'addr'// Return the first file_hdrstatic unsigned int find_romfs(unsigned int addr){ // For now hardcoded address //if(addr > 0x010000) // return 0x0; while (!romfs_check((unsigned int *)addr) && addr < ROM_END_ADDRESS) addr += 0x1000; return (addr >= ROM_END_ADDRESS) ? 0 : addr;}#undef ROMFS_MAGIC_1#undef ROMFS_MAGIC_2#ifdef SUPPORT_GZ_KERNEL_IN_ROMFSstatic unsigned int load_gz(file_hdr *hdr, unsigned int addr){ unsigned char *filename=(unsigned char *)hdr; unsigned int *fileaddr; unsigned int *loadaddr=(unsigned int *)addr; int count = swapl(hdr->size); filename+=16;// point to beginning of file name do{ filename+=16; } while(*(filename-1)); fileaddr=(unsigned int *)filename; PrintUart("Unzipping image from flash\r\n From: ",40); PrintLong((unsigned long)fileaddr); PrintUart("\r\nTo: ",20); PrintLong((unsigned long)loadaddr); PrintUart("\r\nSize: ",20); PrintLong(count); return kunzip((char *)fileaddr, (char *)loadaddr);}#endif /* SUPPORT_GZ_KERNEL_IN_ROMFS */static unsigned int load_bin(file_hdr *hdr, unsigned int addr){ unsigned char *filename=(unsigned char *)hdr; unsigned int *fileaddr; unsigned int *loadaddr=(unsigned int *)addr; char *verifaddr; unsigned int count = swapl(hdr->size); int i; filename+=16;// point to beginning of file name do{ filename+=16; } while(*(filename-1)); fileaddr=(unsigned int *)filename; PrintUart("Copying image from flash\r\n From: ",40); PrintLong((unsigned int)fileaddr); PrintUart("\r\nTo: ",20); PrintLong((unsigned int)loadaddr); PrintUart("\r\nSize: ",20); PrintLong(count); // fast memcpy - could be even faster using asm and ldm instructions count=1+(count>>2); while(count--) *loadaddr++=*fileaddr++; PrintUart("\r\n Done \r\n",20); // verification#if 1 count = swapl(hdr->size); verifaddr=(char *)0x1008000; for(i=0; i<count; i++) { if(filename[i]!=verifaddr[i]) { PrintUart("KABOOOMMMM!! Corruption @ i=",40); PrintLong(i); PrintUart("\r\nfilename[i] = ",40); PrintLong(filename[i]); PrintUart("\r\nverfiaddr[i] = ",40); PrintLong(verifaddr[i]);/* PrintUart("\r\n Dump filename + ",40); PrintLong(i&~0xF); PrintUart(": \r\n",40); dump(filename+(i&~0xF)); PrintUart("\r\n Dump verifaddr + ",40); PrintLong(i&~0xF);*/ PrintUart(": \r\n",40); // dump(verifaddr+(i&~0xF)); }#endif } return 1;}unsigned int try_boot_flash(unsigned int kload, unsigned int addr) { unsigned int *romfs_addr; file_hdr *hdr; // Look for romfs starting after 8K romfs_addr=(unsigned int *)find_romfs(addr); if(!romfs_addr) { set_flash_boot_status(BOOT_STATUS_NOROMFS); PrintUart("ROMFS Not Found\r\n",30); return 0; //romfs not found } PrintUart("Found romfs @ 0x",30); PrintLong((unsigned long)romfs_addr); PrintUart("\r\n",30); PrintUart("Volume Name: ",30); PrintUart((char *)romfs_addr+16,80); PrintUart("\r\n",30); if(!romfs_check(romfs_addr)) { set_flash_boot_status(BOOT_STATUS_ROMFSCHK); PrintUart("ROMFS Check failed\r\n",30); return 0; //romfs corrupted } // Fixme : in lookup strncmp used with fixed max length#ifdef SUPPORT_GZ_KERNEL_IN_ROMFS if((hdr=romfs_lookup(romfs_addr,"linux.bin.gz",16)) && load_gz(hdr,kload)) return 1;#endif if((hdr=romfs_lookup(romfs_addr,"linux.bin",16)) && load_bin(hdr,kload)) return 1; PrintUart("LOAD FAILED\r\n",20); set_flash_boot_status(BOOT_STATUS_FLASHLOAD); // everything has failed return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -