📄 lboot.c
字号:
/* lboot: * Code needed to conveniently boot a linux image. * Having gone through the process of figuring out how to boot linux through * the monitor, following is some documentation on what I've learned... * First of all, this was done with HardHat linux running on the WALNUT * PowerPC 405 platform from IBM, so the information is limited to my * experience on that platform. * * The linux image can be built in two different ways, neither of which is * just a standard ELF file format... * * 1. VMLINUZ: * A non-standard image is created that contains a small executable that * essentially decompresses the real image into memory at location zero. * I refer to this small executable as a "linux boot wrapper". The linux * source that makes this wrapper is found in arch/ppc/boot/tree, and the * function start() does most of the work in main.c. It turns off the * ethernet interface and decompresses another embedded image to location * zero then jumps to that location. The wrapper code that is built for * the WALNUT platform running the OSOPEN monitor assumes that at flash * address 0xfffe0b50 (BOARD_INFO_VECTOR) there is a pointer to a function * that can be executed and will return a pointer to a board-information * structure. * For our environment, this is changed so that the monitor simply passes * in a pointer to the board information structure when it calls the * entrypoint of the boot wrapper. Note here that if we are to run the * "off-the-shelf" vmlinuz image on WALNUT with MicroMonitor, then we must * install a pointer at 0xfffe0b50 manually!! * This "vmlinuz" file is stored in TFS as a non-executable. The command * "lboot" is used to read a 32-byte boot header that is prepended to the * file. This header is the following structure (found in * openbios/include/bootLib.h) and is used to properly load the vmlinuz file * to RAM and jump into it... * * struct boot_block { * ulong magic; BOOT_MAGIC = 0x0052504F * ulong dest; Load destination for remaining data * ulong num_512blocks; * ulong debug_flag; * ulong entry_point; Jump here after load * ulong reserved[3]; * }; * * Once we've turned over control to the vmlinuz module, it turns off * the ethernet interface, decompresses an internal image to RAM, then * calls yet another entrypoint with five arguments described below * in the VMLINUX text... * * 2. VMLINUX: * An elf file that is mapped at KERNELBASE (0xC0000000 for WALNUT) but * loaded at zero. The first portion of code is position independent, * (_start in arch/ppc/kernel/head_4xx.S) but fairly quickly, the MMU is * enabled and the code is "virtually" positioned at 0xC0000000 through * the MMU. When the entrypoint (also zero) is jumped to, it assumes * that 5 arguments are passed in through registers (r3-r7). * * r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) * r4 - Starting address of the init RAM disk * r5 - Ending address of the init RAM disk * r6 - Start of kernel command line string (e.g. "boot=/dev/nfs") * r7 - End of kernel command line string * * The structure pointed to by r3 looks like it can be different from * one Linux port to the next; however, the use of the other four * values appears to be constant across LINUX ports. * * Figuring all this out took a lot of browsing through osopen code from * IBM (the IBM boot monitor); particularly the file net_boot.c. It contains * the code that is invoked to retrieve the VMLINUZ file as described above. * Notice that the very first packet retrieved contains a structure that * is used to tell the loader where in memory to put the image. * The code browsed in hardhat was arch/ppc/kernel/setup.c & head_4xx.S. * * THE GOAL OF THE LBOOT COMMAND IS TO SUPPORT BOOTING EITHER TYPE OF * FILE (VMLINUZ OR VMLINUX) FROM tfs OR DIRECTLY FROM THE LOADED LOCATION * IF IT WAS PREVIOUSLY TFTP'D INTO THE TARGET MEMORY. * * WALNUT BOARD NOTE: * There is not much flash on the WALNUT board, so we could not store * a LINUX image file in TFS and load it. To get around this, we * converted the vmlinux image to a binary image using elf -B * (elf -B vmlinux.bin vmlinux). Then that .bin file was tftp'd to * the target at location zero (simulating a TFS ld), and we used * "lboot -ve 0 -c root=/dev/nfs" to start things up. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#include "tfs.h"#include "tfsprivate.h"#include "stddefs.h"#include "flash.h"#include "genlib.h"#include "ether.h"#include "cli.h"#include "elf.h"static int tfsloadlelf(TFILE *fp,int verbose,long *entrypoint);/* This is the structure used for PPC405 LINUX port; it is probably * not the same for other ports... The first argument passed to the * entrypoint should contain apointer to this structure. */struct board_info { unsigned char bi_s_version[4]; /* Version of this structure */ unsigned char bi_r_version[30]; /* Version of the IBM ROM */ unsigned int bi_memsize; /* DRAM installed, in bytes */ unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ unsigned int bi_intfreq; /* Processor speed, in Hz */ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */};/* struct boot_block: * See comments above for description. */struct boot_block { ulong magic; ulong dest; ulong num_512blocks; ulong debug_flag; ulong entry_point; ulong reserved[3];};/* One important thing to note is that it appears that at startup, LINUX * configures a maximum memory size of 16Mg, so the board_info structure * must be located in space lower than 0x1000000. This also applies to * the command line that is pointed to by r6. Depending on how the * monitor is built, this range of memory may not be in it's bss space * so it is important to make sure that this is located properly. */#define FIXED_BINFO 0xf00000;#define FIXED_CLI 0xf00200;uchar xmagic[] = { 0x7f, 0x45, 0x4c, 0x46 };uchar zmagic[] = { 0x00, 0x52, 0x50, 0x4f };char *LbootHelp[] = { "Boot a linux image.", "-[c:e:r:s:v] {linux_image_file}", "Options:", " -c {cmd_line} boot parameters command line string", " -e {entry_addr} skip load step, use specified entrypoint", " -m {memsize} override default bi_memsize value in board info", " -o {entrypt_offst} value subtracted from ELF-derived entrypoint", " -r {rdb,rds} ram-disk-base, ram-disk-size", " -v enable verbosity", 0};intLbootCmd(int argc,char *argv[]){ TFILE *tfp; char *comma; ulong offset; void (*entry)(); ulong rdb, rde; /* ramdisk base & end */ char *bpb, *bpe; /* boot param string base & end */ int bps, rds; /* ramdisk & boot string size */ struct board_info *bip; /* board info pointer */ int opt, verbose, err, entryset; /* Build the board information structure: */ bip = (struct board_info *)FIXED_BINFO; memset((char *)bip,0,sizeof(struct board_info)); bip->bi_memsize = RAM_VECTOR_TABLE-1;bip->bi_memsize = 0x2000000; bip->bi_intfreq = 200000000; /* 200 mhz */ bip->bi_busfreq = 100000000; /* 100 mhz */ bip->bi_pci_busfreq = 33333333; /* 33.333 mhz */ memcpy(bip->bi_enetaddr,BinEnetAddr,6); entry = 0; entryset = 0; bpb = bpe = (char *)0; verbose = rdb = rde = rds = bps = 0; while((opt=getopt(argc,argv,"c:e:m:o:r:v")) != -1) { switch(opt) { case 'c': bps = strlen(optarg) + 1; bpb = (char *)FIXED_CLI; if (bpb) bpe = bpb + bps; strcpy(bpb,optarg); break; case 'e': entryset = 1; entry = (void(*)())strtoul(optarg,0,0); break; case 'm':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -