📄 romfs.c
字号:
/***************************************** Copyright (c) 2002-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the boot loader *//* * romfs.c * * Extract linux kernel binary from romfs */#include "config.h"#include "uart.h"#include "util.h"#include "kunzip.h"#include "bootconfig.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 const char *romfs_found_msg = "ROMFS found at 0x%p, Volume name = %s\n";static const char *romfs_none_msg = "ROMFS not found\n";static const char *romfs_chk_msg = "ROMFS Check failed\n";extern unsigned loadaddr_heap_unzip;// Lookup file in romfs and return file address (or 0 if no such file)file_hdr *romfs_lookup(unsigned int *romfs, char *name, file_hdr *hdrprev){ char *filename; char *volume; file_hdr *hdr; unsigned int next; if (hdrprev == NULL) { volume = (char *)(romfs + 4); // +4 32bits words while (*volume) volume++; volume += 1; /* must account for the terminating null character */ hdr = (file_hdr *)(((unsigned int) volume + 15) & ~0xF); } else { next = (swapl(hdrprev->next) & ~0xF) >> 2; if (next == 0) return NULL; hdr = (file_hdr *) (romfs+next); } while (1) { filename = ((char *) hdr) + 16; next = (swapl(hdr->next) & ~0xF) >> 2; // uart_printf("%08x : %s\n", (void *) hdr - (void *) romfs, filename); if (name == NULL) return hdr; else if (strcmp(name, filename) == 0) { uart_printf("File %s found\n", name); return hdr; } else if (next == 0) { uart_printf("File %s not found\n", name); return NULL; } 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)unsigned int romfs_check(unsigned int *addr){ return (((*addr) == ROMFS_MAGIC_1) && ((*(addr + 1)) == ROMFS_MAGIC_2)) ? 1 : 0;}/** * Get the full size of a ROMFS (without padding) * @param addr - beginning address of the ROMFS * @return > 0 on success, 0 on error */unsigned int romfs_size(unsigned int *addr){ if (romfs_check(addr)) return swapl(*(addr + 2)); return 0;}// Find the romfs in flash starting from 'addr'// Return the first file_hdrunsigned int find_romfs(unsigned int addr, unsigned int to){ while (!romfs_check((unsigned int *) addr) && addr <= to) addr += 0x1000; return (addr > to) ? 0 : addr;}#undef ROMFS_MAGIC_1#undef ROMFS_MAGIC_2static 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); int res;#ifdef CONFIG_ENABLE_NETWORK extern int net_dev_down(void); net_dev_down();#endif filename += 16; // point to beginning of file name do { filename += 16; } while (*(filename - 1)); fileaddr = (unsigned int *) filename; uart_printf("Unzipping image from 0x%p to 0x%p, size = %d\n", fileaddr, loadaddr, count); res = kunzip((char *)fileaddr, (char *)loadaddr, loadaddr_heap_unzip); return res;}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; unsigned int count = swapl(hdr->size);#ifdef CONFIG_ENABLE_NETWORK extern int net_dev_down(void); net_dev_down();#endif filename += 16; // point to beginning of file name do { filename += 16; } while (*(filename - 1)); fileaddr = (unsigned int *) filename; uart_printf("Copying image from 0x%p to 0x%p, size = %d\n", fileaddr, loadaddr, count); memcpy(loadaddr, fileaddr, count); // verification if (memcmp(loadaddr, fileaddr, count) != 0) uart_puts("Data mismatch after copying\n"); return count;}unsigned int boot_romfs(unsigned int kload, unsigned int addr, unsigned int to) { unsigned int *romfs_addr; file_hdr *hdr; // Look for romfs starting after 8K romfs_addr = (unsigned int *) find_romfs(addr, to); if (romfs_addr == 0) { uart_puts(romfs_none_msg); return 0; //romfs not found } uart_printf(romfs_found_msg, romfs_addr, (char *) romfs_addr + 16); if (!romfs_check(romfs_addr)) { uart_puts(romfs_chk_msg); return 0; //romfs corrupted } if ((hdr = romfs_lookup(romfs_addr, DEFAULT_KERNELGZ_FILENAME, NULL)) && load_gz(hdr, kload)) return 1; if ((hdr = romfs_lookup(romfs_addr, DEFAULT_KERNEL_FILENAME, NULL)) && load_bin(hdr, kload)) return 1; uart_puts("ROMFS load failed\n"); return 0;}unsigned int load_romfs_file(char *name, unsigned int load_addr, unsigned int addr, unsigned int to, int autoexpand){ unsigned int *romfs_addr; file_hdr *hdr; unsigned int count = 0; char fname[64]; // Look for romfs starting after 8K romfs_addr = (unsigned int *) find_romfs(addr, to); if (romfs_addr == 0) { uart_puts(romfs_none_msg); return 0; //romfs not found } uart_printf(romfs_found_msg, romfs_addr, (char *) romfs_addr + 16); if (!romfs_check(romfs_addr)) { uart_puts(romfs_chk_msg); return 0; //romfs corrupted } if ((hdr = romfs_lookup(romfs_addr, name, NULL)) && (count = load_bin(hdr, load_addr))) return count; if (autoexpand) { strcpy(fname, name); strcat(fname, ".gz"); if ((hdr = romfs_lookup(romfs_addr, fname, NULL)) && (count = load_gz(hdr, load_addr))) return count; } uart_puts("ROMFS load failed\n"); return 0;}int dump_romfs(unsigned int addr, unsigned int to){ static char *s_filetype[] = { "hard link", "dir", "file", "symbolic link", "block dev", "char dev", "socket", "fifo" }; unsigned int *romfs_addr; file_hdr *hdr = NULL; int type, size, next; // Look for romfs starting after 8K romfs_addr = (unsigned int *) find_romfs(addr, to); if (romfs_addr == 0) { uart_puts(romfs_none_msg); return 0; //romfs not found } uart_printf(romfs_found_msg, romfs_addr, (char *) romfs_addr + 16); if (!romfs_check(romfs_addr)) { uart_puts(romfs_chk_msg); return 0; //romfs corrupted } while ((hdr = romfs_lookup(romfs_addr, NULL, hdr)) != NULL) { size = swapl(hdr->size); type = swapl(hdr->next); next = type & ~0x0f; type &= 0x07; uart_printf("%p : Name = %s, Type = %s, Size = %08x, Next = %08x\n", hdr, ((char *) hdr) + 16, s_filetype[type], size, next); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -