📄 mkboot.c
字号:
while(size != 0) { written = write(fd, buf, size); if (written == -1) { perror("Can't write to boot image"); exit(1); } size -= written; }}static intusage(program_name) char *program_name;{ fprintf(stderr, "Usage: %s infile outfile\n", program_name); exit(0);}intmain(argc, argv) int argc; char *argv[];{ char *infile, *outfile; struct stat ifstat; off_t ifsize; char *image; int ifd, ofd, i, symtabix, strtabix; Elf32_Ehdr eh; Elf32_Phdr *ph; Elf32_Shdr *sh; unsigned long vaddr, entry, bss, kernel_entry, kernel_end; unsigned char ahdr[32]; Elf32_Sym sym; int symnum; char *symname; /* * Verify some basic assuptions about type sizes made in this code */ if (sizeof(Elf32_Half) != 2) { fprintf(stderr, "Fix mkboot: sizeof(Elf32_Half) != 2\n"); exit(1); } if (sizeof(Elf32_Word) != 4) { fprintf(stderr, "Fix mkboot: sizeof(Elf32_Word) != 4\n"); exit(1); } if (sizeof(Elf32_Addr) != 4) { fprintf(stderr, "Fix mkboot: sizeof(Elf32_Addr) != 4\n"); exit(1); } if (argc != 3) usage(argv[0]); infile = argv[1]; outfile = argv[2]; if (stat(infile, &ifstat) < 0) { perror("Can't stat kernel image."); exit(1); } if (!S_ISREG(ifstat.st_mode)) { fprintf(stderr, "Input file isn't a regular file.\n"); exit(1); } ifsize = ifstat.st_size; image = malloc((size_t)ifsize); if (image == NULL) { fprintf(stderr, "Can't allocate memory to read file\n"); exit(1); } /* * Read the entire input file in. */ ifd = open(infile, O_RDONLY); if(ifd == 0) { fprintf(stderr, "Can't open input file\n"); exit(1); } do_read(ifd, image, ifsize); close(ifd); /* * Now swap the ELF header in. This is ugly but we the file * we're reading might have different type sizes, byteorder * or alignment than the host. */ memcpy(eh.e_ident, (void *)image, sizeof(eh.e_ident)); if(memcmp(eh.e_ident, ELFMAG, SELFMAG)) { fprintf(stderr, "Input file isn't a ELF file\n"); exit(1); } if(eh.e_ident[EI_CLASS] != ELFCLASS32) { fprintf(stderr, "Input file isn't a 32 bit ELF file\n"); exit(1); } if(eh.e_ident[EI_DATA] != ELFDATA2LSB) { fprintf(stderr, "Input file isn't a little endian ELF file\n"); exit(1); } if(eh.e_ident[EI_VERSION] != EV_CURRENT) { fprintf(stderr, "Input file isn't a version %d ELF file\n", EV_CURRENT); exit(1); } /* * Ok, so far the file looks ok. Now swap the rest of the header in * and do some more paranoia checks. */ eh.e_type = get_Elf32_Half(image + 16); eh.e_machine = get_Elf32_Half(image + 18); eh.e_version = get_Elf32_Word(image + 20); eh.e_entry = get_Elf32_Addr(image + 24); eh.e_phoff = get_Elf32_Off(image + 28); eh.e_shoff = get_Elf32_Off(image + 32); eh.e_flags = get_Elf32_Word(image + 36); eh.e_ehsize = get_Elf32_Half(image + 40); eh.e_phentsize = get_Elf32_Half(image + 42); eh.e_phnum = get_Elf32_Half(image + 44); eh.e_shentsize = get_Elf32_Half(image + 46); eh.e_shnum = get_Elf32_Half(image + 48); eh.e_shstrndx = get_Elf32_Half(image + 50); if(eh.e_type != ET_EXEC) { fprintf(stderr, "Input file isn't a executable.\n"); exit(1); } if(eh.e_machine != EM_MIPS && eh.e_machine != EM_MIPS_RS4_BE) { fprintf(stderr, "Input file isn't a MIPS executable.\n"); exit(1); } /* * Now read the program headers ... */ ph = malloc(sizeof(Elf32_Phdr) * eh.e_phnum); if (ph == NULL) { fprintf(stderr, "No memory for program header table.\n"); exit(1); } for(i = 0;i < eh.e_phnum; i++) get_elfph((void *)(image + eh.e_phoff + i * 32), ph + i); /* * ... and then the section headers. */ sh = malloc(sizeof(Elf32_Shdr) * eh.e_shnum); if (sh == NULL) { fprintf(stderr, "No memory for section header table.\n"); exit(1); } for(i = 0;i < eh.e_shnum; i++) get_elfsh((void *)(image + eh.e_shoff + (i * 40)), sh + i); /* * Find the symboltable and the stringtable in the file. */ for(i = 0;i < eh.e_shnum; i++) { if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name, ".symtab")) { symtabix = i; continue; } if (!strcmp (image + sh [eh.e_shstrndx].sh_offset + sh[i].sh_name, ".strtab")) { strtabix = i; continue; } } if (symtabix == -1) { fprintf(stderr, "The executable doesn't have a symbol table\n"); exit(1); } if (strtabix == -1) { fprintf(stderr, "The executable doesn't have a string table\n"); exit(1); } /* * Dig for the two required symbols in the symbol table. */ symnum = sh[symtabix].sh_size / 16; for(i = 0;i < symnum;i++) { get_elfsym(image + sh[symtabix].sh_offset + (i * 16), &sym); symname = image + sh[strtabix].sh_offset + sym.st_name; if (ELF32_ST_BIND(sym.st_info) != STB_GLOBAL) continue; if (ELF32_ST_TYPE(sym.st_info) != STT_NOTYPE && ELF32_ST_TYPE(sym.st_info) != STT_OBJECT && ELF32_ST_TYPE(sym.st_info) != STT_FUNC) continue; if (strcmp("kernel_entry", symname) == 0) { kernel_entry = sym.st_value; continue; } if (strcmp("_end", symname) == 0) { kernel_end = sym.st_value; continue; } }#ifdef VERBOSE /* * And print what we will be loaded into memory. */ for(i = 0;i < eh.e_phnum; i++) { if (ph[i].p_type != PT_LOAD) { continue; } printf(" Offset: %08lx\n", ph[i].p_offset); printf(" file size: %08lx\n", ph[i].p_filesz); printf(" mem size: %08lx\n", ph[i].p_memsz); printf(" Loading: %08lx - %08lx\n", ph[i].p_vaddr, ph[i].p_vaddr + ph[i].p_filesz); printf(" Zero mapping: %08lx - %08lx\n", ph[i].p_vaddr + ph[i].p_filesz, ph[i].p_vaddr + ph[i].p_memsz); }#endif /* * Time to open the outputfile. */ ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (ofd == -1) { perror("Can't open boot image for output."); exit(1); } /* * First compute the layout of the file. We need to do this * first because we can't seek back to the beginning due to the * broken Seek() call in the Magnum firmware. */ entry = vaddr = 0xffffffff; bss = 0; for(i = 0;i < eh.e_phnum; i++) { if (ph[i].p_type != PT_LOAD) continue; if (vaddr == 0xffffffff) entry = vaddr = ph[i].p_vaddr; vaddr = ph[i].p_vaddr + ph[i].p_filesz; bss = ph[i].p_memsz - ph[i].p_filesz; } /* * In the next step we construct the boot image. The boot file * looks essentially like a dump of the loaded kernel with a * minimal header. Because Milo supports already a.out image * we simply dump the image in an a.out image ... First let's * write the header. */ /* * Create and write the a.out header. */ put_word(ahdr, AOUT_INFO(OMAGIC, M_MIPS1, 0)); put_word(ahdr + 4, vaddr - entry); /* text size */ put_word(ahdr + 8, 0); /* data size */ put_word(ahdr + 12, bss); /* bss size */ put_word(ahdr + 16, 2 * 12); /* size of symbol table */ put_word(ahdr + 20, entry); /* base address */ put_word(ahdr + 24, 0); /* size of text relocations */ put_word(ahdr + 28, 0); /* size of data relocations */ do_write(ofd, ahdr, 32); /* * Write text and data segment combined into the a.out text segment * and a zero length data segment into the file. */ vaddr = 0xffffffff; bss = 0; for(i = 0;i < eh.e_phnum; i++) { if (ph[i].p_type != PT_LOAD) continue; if (vaddr == 0xffffffff) vaddr = ph[i].p_vaddr; writepad(ofd, ph[i].p_vaddr - vaddr); /* Write zero pad */ do_write(ofd, image + ph[i].p_offset, ph[i].p_filesz); vaddr = ph[i].p_vaddr + ph[i].p_filesz; bss = ph[i].p_memsz - ph[i].p_filesz; } /* * Now write the symbol table. It has only two symbols, * kernel_entry and _end which we need for booting. */ put_word(ahdr , 4); /* n_un.n_strx */ put_byte(ahdr + 4, N_TEXT | N_EXT); /* n_type */ put_byte(ahdr + 5, 0); /* n_other */ put_half(ahdr + 6, 0); /* n_desc */ put_word(ahdr + 8, kernel_entry); /* n_value */ do_write(ofd, ahdr, 12); put_word(ahdr , 4 + 13); /* n_un.n_strx */ put_byte(ahdr + 4, N_ABS | N_EXT); /* n_type */ put_byte(ahdr + 5, 0); /* n_other */ put_half(ahdr + 6, 0); /* n_desc */ put_word(ahdr + 8, kernel_end); /* n_value */ do_write(ofd, ahdr, 12); /* * Now write stringtable size and the strings. */ put_word(ahdr, 4 + 20); do_write(ofd, ahdr, 4); do_write(ofd, "kernel_entry\0_end\0\0", 20); /* * That's is all ... */ close(ofd);#ifdef VERBOSE printf("Entry: %08lx\n", entry); printf("Dumped image %08lx - %08lx\n", 0x80000000, vaddr); printf("Extra bss at end: %08lx\n", bss);#endif return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -