⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lboot.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 + -