📄 lboot.c
字号:
bip->bi_memsize = strtoul(optarg,0,0); break; case 'o': offset = strtoul(optarg,0,0); break; case 'r': comma = strchr(optarg,','); if (!comma) return(CMD_PARAM_ERROR); *comma = 0; rdb = strtoul(optarg,0,0); rds = strtoul(comma+1,0,0); rde = rdb + rds; break; case 'v': verbose++; break; default: return(CMD_PARAM_ERROR); } } /* If the filename is specified, then we must load the file * from TFS to memory. Note that the relocation addresses * may not be correct because it should be loaded to address zero. * We will depend on the -o option to tell us if we need to * adjust for this. */ if (argc == optind+1) { struct boot_block *bb; char *fbase, *fname; fname = argv[optind]; tfp = tfsstat(fname); if (!tfp) { printf("%s: file not found\n",fname); return(CMD_FAILURE); } if (TFS_USRLVL(tfp) > getUsrLvl()) { printf("Permission denied\n"); return(CMD_FAILURE); } fbase = TFS_BASE(tfp); if (memcmp(fbase,xmagic,4) == 0) { err = tfsloadlelf(tfp,verbose > 1 ? 1 : 0,(long *)&entry); if (err != TFS_OKAY) { printf("%s: %s\n",fname,tfserrmsg(err)); return(CMD_FAILURE); } } else if (memcmp(fbase,zmagic,4) == 0) { bb = (struct boot_block *)fbase; memcpy((char *)bb->dest, fbase + sizeof(struct boot_block), TFS_SIZE(tfp) - sizeof(struct boot_block)); entry = (void(*)())bb->entry_point; } else { printf("File %s, not vmlinux or vmlinuz!!??\n",fname); return(CMD_FAILURE); } entryset = 1; } /* Yanking comments from arch/ppc/kernel/ppc4xx_setup.c of linux, * registers r3 thru r7 are as follows... * * r3 - Optional pointer to a board information structure. * r4 - Optional pointer to the physical starting address of the init RAM * disk. * r5 - Optional pointer to the physical ending address of the init RAM * disk. * r6 - Optional pointer to the physical starting address of any kernel * command-line parameters. * r7 - Optional pointer to the physical ending address of any kernel * command-line parameters. * * Registers r4-r7 can be established locally with this command through * the -b and -r options. The structure pointed to by r3 appears to * be different for different targets, so this will be an external * function. * NOTE: the comments in the linux code say "Optional". Don't beleive * it! They are not optional! At a minimum, the board information * pointer must point to a valid board information structure, and the * other registers must be NULL. */ if (verbose) { printf("entry(0x%lx,0x%lx,0x%lx,0x%lx,0x%lx)\n", (ulong)bip,rdb,rde,(ulong)bpb,(ulong)bpe); } if (entryset) { if (verbose) printf("Branching to entrypoint 0x%lx...\n",(ulong)entry); entry(bip,rdb,rde,bpb,bpe); /* Branch to entrypoint */ } return(CMD_SUCCESS);}/* tfsloadlelf(): * This function is VERY similar to the TFS_EBIN_ELF version of tfsloadebin() * in tfsloader.c. Originally I put a few changes to the standard stuff in * tfsloader.c; but then I decided to leave that stuff work in the standard * way only and put any hacks of the standard here in the lboot.c file. This * will avoid future hacking of the loader functions just to support the * non-standard way in which the ELF file is loaded for linux. */static inttfsloadlelf(TFILE *fp,int verbose,long *entrypoint){ Elf32_Word size, notproctot; ulong delta; int i, err, no_sections_loaded; char *shname_strings; ELFFHDR *ehdr; ELFSHDR *shdr; delta = 0; no_sections_loaded = 1; /* Establish file header pointers... */ ehdr = (ELFFHDR *)(TFS_BASE(fp)); shdr = (ELFSHDR *)((int)ehdr + ehdr->e_shoff); err = 0; /* Store the section name string table base: */ shname_strings = (char *)ehdr + shdr[ehdr->e_shstrndx].sh_offset; notproctot = 0; /* For each section header, relocate or clear if necessary... */ for (i=0;!err && i<ehdr->e_shnum;i++,shdr++) { if ((size = shdr->sh_size) == 0) continue; if ((verbose) && (ehdr->e_shstrndx != SHN_UNDEF)) printf("%-10s: ", shname_strings + shdr->sh_name); if (!(shdr->sh_flags & SHF_ALLOC)) { notproctot += size; if (verbose) printf(" %7ld bytes not processed (tot=%ld)\n", size,notproctot); continue; } /* This linux binary always wants to be loaded at zero. The load * address in the header of the first section is used as a delta * for all sections so that the first section is loaded at zero * and all remaining sections are loaded with the same delta as * the first section. The initial linux code is address independent * and it quickly turns on the MMU and adjusts it's "virtual" * memory space to look like it is running at the actual address * space specified by the elf header. */ if (no_sections_loaded) { delta = (ulong)shdr->sh_addr; no_sections_loaded = 0; } if (shdr->sh_type == SHT_NOBITS) { if (tfsmemset((char *)(shdr->sh_addr - delta),0,size, verbose,0) != 0) err++; } else { if (TFS_ISCPRS(fp)) { int outsize; outsize = decompress((char *)(ehdr)+shdr->sh_offset,size, (char *)shdr->sh_addr - delta); if (outsize == -1) { err++; continue; } if (verbose) printf("dcmp %7d bytes from 0x%08lx to 0x%08lx\n",outsize, (ulong)(ehdr)+shdr->sh_offset,shdr->sh_addr); } else { if (tfsmemcpy((char *)(shdr->sh_addr - delta), (char *)((int)ehdr+shdr->sh_offset), size,verbose,0) != 0) err++; } /* Flush caches for each loadable section... */ flushDcache((char *)shdr->sh_addr - delta,size); invalidateIcache((char *)shdr->sh_addr - delta,size); } } if (err) return(TFSERR_MEMFAIL); if (verbose) { printf("entrypoint: 0x%lx, linux-delta: 0x%lx\n", ehdr->e_entry, delta); } /* Store entry point: */ if (entrypoint) *entrypoint = (long)(ehdr->e_entry) - delta; return(TFS_OKAY);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -