From 7150f00f5be87fa8e37f7d00fbbef35645081138 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Mon, 1 Dec 1997 22:06:48 +0000 Subject: Inclusion of PC386 BSP submitted by Pedro Miguel Da Cruz Neto Romano and Jose Rufino of NavIST (http://pandora.ist.utl.pt/). --- c/src/lib/libbsp/i386/pc386/tools/Makefile.in | 63 +++++ c/src/lib/libbsp/i386/pc386/tools/Spec.doc | 354 ++++++++++++++++++++++++++ c/src/lib/libbsp/i386/pc386/tools/bin2boot.c | 239 +++++++++++++++++ 3 files changed, 656 insertions(+) create mode 100644 c/src/lib/libbsp/i386/pc386/tools/Makefile.in create mode 100644 c/src/lib/libbsp/i386/pc386/tools/Spec.doc create mode 100644 c/src/lib/libbsp/i386/pc386/tools/bin2boot.c (limited to 'c/src/lib/libbsp/i386/pc386/tools') diff --git a/c/src/lib/libbsp/i386/pc386/tools/Makefile.in b/c/src/lib/libbsp/i386/pc386/tools/Makefile.in new file mode 100644 index 0000000000..d3ea3f7ce3 --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/tools/Makefile.in @@ -0,0 +1,63 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH=@srcdir@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +manext = 1 +mandir = @mandir@/man$(manext) + + +VPATH=@srcdir@ + + +# we use host compiler in this directory +USE_HOST_COMPILER=yes + +# C source names, if any, go here -- minus the .c +C_PIECES=bin2boot +C_FILES=$(C_PIECES:%=%.c) +C_O_FILES=$(C_PIECES:%=$(ARCH)/%.o) + +H_FILES= + +SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) +OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES) + +PGMS=$(ARCH)/bin2boot + +include $(RTEMS_CUSTOM) +include $(RTEMS_ROOT)/make/leaf.cfg + +# +# (OPTIONAL) Add local stuff here using += +# + +DEFINES += +CPPFLAGS += +CFLAGS += + +LD_PATHS += +LD_LIBS += +LDFLAGS += + +# +# Add your list of files to delete here. The config files +# already know how to delete some stuff, so you may want +# to just run 'make clean' first to see what gets missed. +# 'make clobber' already includes 'make clean' +# + +CLEAN_ADDITIONS += $(HOST_ARCH) +CLOBBER_ADDITIONS += + +all: $(ARCH) $(SRCS) $(PGMS) + $(INSTALL_VARIANT) -m 555 $(PGMS) ${PROJECT_RELEASE}/build-tools + cd ${PROJECT_RELEASE}/build-tools/diskboot.exe ; \ + uudecode < $(srcdir)/diskboot.uue diff --git a/c/src/lib/libbsp/i386/pc386/tools/Spec.doc b/c/src/lib/libbsp/i386/pc386/tools/Spec.doc new file mode 100644 index 0000000000..c4ca3c4234 --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/tools/Spec.doc @@ -0,0 +1,354 @@ + + 2-28-1995 GK + +In order to provide more functionality to the boot rom code I changed +Jamie's draft a little bit. All my changes have a bar sign (|) in the +79th column. + +Gero Kuhlmann + +=============================================================================== + + +0. Numbering + +This is Draft Net Boot Image Proposal 0.2, February 28, 1995 | + + +1. Preamble - the why + +Whilst researching what other boot proms do (at least those implementing +TCP/IP protocols) it is clear that each 'does their own thing' in +terms of what they expect in a boot image. + +If we could all agree on working toward an open standard, O/S suppliers +and boot rom suppliers can build their products to this norm, and be confident +that they will work with each other. + +This is a description of how I will implement the boot rom for +Linux. I believe it to be flexible enough for any OS that will be loaded +when a PC boots from a network in the TCP/IP environment. + +It would be good if this could be turned into some form of standard. + +This is very much a first draft. I am inviting comment. + +The ideas presented here should be independant of any implementation. +In the end, where there is a conflict between the final of this draft, and an +implementation, this description should prevail. + +The terms I use are defined at the end. + + +2. The target + +The target is to have a PC retrieve a boot image from a network in the TCP/IP +environment. + +The boot may take place from a network adaptor rom, from a boot floppy, or +from a program in MSDOS. + + +3. Net Boot Process Description. + +The net boot process can be started either as a result of the PC +boot process, or through normal DOS execution of a program. The net boot +program can reside on a rom, e.g. on an adaptor card, or in ram, either +as a result of reading off disk or transferred from ram. + +The boot process may execute in any mode (e.g. 8086, 80386) it desires. +When it jumps to the start location in the boot image, it must be in +8086 mode and be capable of going into any mode supported by the +underlying processor. + +The image cannot be loaded into address spaces below 10000h, or between +A0000h through FFFFFh, or between 98000h through 9FFFFh. Once the image +starts executing, all the memory is available to it, so it can relocate +parts of itself to these areas. + +The boot process must be capable of loading the image into all other +memory locations. Specifically, where the machine supports this, this means +memory over 100000h. + +The net boot process must execute the bootp protocol, followed by +the tftp protocol, as defined in the relevant rfc's. + +The file name used in the tftp protocol must be that given by the bootp +record. + +If less than 512 bytes are loaded, the net boot process attempts to display +on the screen any ascii data at the start of the image. The net boot +process then exits in the normal manner. For a boot prom, this will +allow normal disk booting. For DOS programs, this will mean a normal return +to DOS. + +When the first 512 bytes have been loaded, the boot process checks +for an initial magic number, which is defined later. If this number +is present, the net process continues loading under the control +of the image format. The image, which is described later, tells the +net boot process where to put this record and all subsequent data. + +If no initial magic number is present the net boot process checks for a second +magic number at offset 510. If the magic number 510 = 55h, 511 = AAh, +then the net process continues. If this second magic number is not +present, then the net boot process terminates the tftp protocol, displays +an error message and exits in the normal manner. + +If no initial magic number is present and the second one is, the net boot +process relocates the 512 bytes to location 7c00h. The net boot process +continues to load any further image data to 10000h up. This data can overwrite +the first 512 boot bytes. If the image reaches 98000h, then any further data is +continued to be loaded above 100000h. When all the data has been loaded, the +net boot process jumps to location 0:7c00. + +When the net boot process calls the image, it places 2 far pointers onto | +the stack, in standard intel order (e.g. segment:offset representation). | +The first far pointer which immediately follows the return address on | +the stack, points to the loaded boot image header. The second far pointer | +which is placed above the first one, shows to the memory area where the | +net boot process saved the bootp reply. | + + +4. Image Format with Initial Magic Number. + +The first 512 bytes of the image file contain the image header, +and image loading information records. This contains all the +information needed by the net boot process as to where data +is to be loaded. + +The magic number (in time-honoured tradition (well why not?)) is: + + 0 = 36h + 1 = 13h + 2 = 03h + 3 = 1Bh + +Apart from the two magic numbers, all words and double words are in PC +native endian. + +Including the initial magic number the header record is: + + +---------------------+ + | | + | Initial Magic No. | 4 bytes + +---------------------+ + | | + | Flags and length | double word + +---------------------+ + | | + | Location Address | double word in ds:bx format + +---------------------+ + | | + | Execute Address | double word in cs:ip format + +---------------------+ + +The Location address is where to place the 512 bytes. The net boot +process does this before loading the rest of the image. The location +address cannot be one of the reserved locations mentioned above, but +must be an address lower than 100000h. + +The rest of the image must not overwrite these initial 512 bytes, placed +at the required location. The writing of data by the net boot process +into these 512 bytes is deprecated. These 512 bytes must be available for +the image to interogate once it is loaded and running. + +The execute address is the location in cs:ip of the initial instruction +once the full image has been loaded. This must be lower than 100000h, +since the initial instructions will be executed in 8086 mode. When the +jump (actaully a far call) is made to the boot image, the stack contains a +far return address, with a far pointer parameter above that, pointing +to the location of this header. + +The flags and length field is broken up in the following way: + +Bits 0 to 3 (lowest 4 bits) define the length of the non vendor header in +double words. Currently the value is 4. + +Bits 4 to 7 define the length required by the vendor extra information +in double words. A value of zero indicates no extra vendor information. + +Bits 8 to 31 are reserved for future use and must be set to zero. + +After this header, and any vendor header, come the image loading information +records. These specify where data is to be loaded, how long it is, and +communicates to the loaded image what sort of data it is. + +The format of each image loading information record is : + + + +---------------------+ + | Flags, tags and | double word + | lengths | + +---------------------+ + | | + | Load Address | double word + +---------------------+ + | | + | Image Length | double word + +---------------------+ + | | + | Memory Length | double word + +---------------------+ + +Each image loading information record follows the previous, or the header. + +The memory length, image length and load address fields are unsigned 32 +numbers. They do not have the segment:offset format used by the 8086. + +The flags, tags and lengths field is broken up as follows: + +Bits 0 to 3 (lowest 4 bits) are the length of the non vendor part of this +header in double words. Currently this value is 4. + +Bits 4 to 7 indicate the length of any vendor information, in double words. + +Bits 8 to 15 are for vendor's tags. The vendor tag is a private number that +the loaded image can use to determine what sort of image is at this particular +location. + +Bits 16 to 23 are for future expansion and should be set to zero. + +Bits 24 to 31 are for flags, which are defined later. + +Vendors may place further information after this information record, and +before the next. Each information record may have a different vendor +length. + +There are two restrictions on vendor information. + +One is that the header and all information records that the net boot process +is to use fall within the first 512 bytes. + +The second restriction is that the net boot process must ignore all +vendor additions. The net boot process may not overwrite vendor supplied +information, or other undefined data in the initial 512 bytes. + +The flags are used to modify the load address field, and to indicate +that this is the last information record that the net boot process should +use. + +Bit 24 works in conjunction with bit 25 to specify the meaning of the +load address. + + B24 B25 + + 0 0 load address is an absolute 32 number + + 1 0 add the load address to the location one past the last byte + of the memory area required by the last image loaded. + If the first image, then add to 512 plus the location + where the 512 bytes were placed + + 0 1 subtract the load address from the one past the + last writeable location in memory. Thus 1 would + be the last location one could write in memory. + + 1 1 load address is subtracted from the start of + the last image loaded. If the first image, then + subtract from the start of where the 512 bytes were + placed + +(For convenience bit 24 is byte 0 of the flag field) + +Bit 26 is the end marker for the net boot process. It is set when +this is the last information record the net boot process should +look at. More records may be present, but the net boot process will not +look at them. (Vendors can continue information records out past the 512 +boundary for private use in this manner). + +The image length tells the net boot process how many bytes are to be loaded. +Zero is a valid value. This can be used to mark memory areas such as +shared memory for interprocessor communication, flash eproms, data in eproms. + +The image length can also be different from the memory length. This allows +decompression programs to fluff up the kernel image. It also allows a file +system to be larger then the loaded file system image. + +Bits 27 through 31 are not defined as yet and must be set to zero until +they are. + + +6. Boot prom entry points. + +I have not defined boot entry points, and means of obtaining them. +It could be useful to down load part of an image, and have that image +load more of itself by using handy parts of the net boot program. + +This can be considered 'for further study'. + + +7. Example of a boot image. + +Here is an example of how the boot image would look for Linux: + + 0x1B031336, /* magic number */ + 0x4, /* length of header is 16 bytes, no vendor info */ + 0x90000000, /* location in ds:bx format */ + 0x90000200, /* execute address in cs:ip format */ + + /* 2048 setup.S bytes */ + 0x4, /* flags, not end, absolute address, 16 bytes this + record, no vendor info */ + 0x90200, /* load address - note format */ + 0x800, /* 4 8 512 byte blocks for linux */ + 0x800, + + /* kernel image */ + 0x4, /* flags, not end, absolute address, 16 bytes this + record, no vendor info */ + 0x10000, /* load address - note format */ + 0x80000, /* 512K (this could be shorter */ + 0x80000, + + /* ramdisk for root file system */ + 0x04000004, /* flags = last, absolute address, 16 bytes this + record, no vendor info *// + 0x100000, /* load address - in extended memory */ + 0x80000, /* 512K for instance */ + 0x80000, + + /* Then follows linux specific information */ + + +8. Terms + +When I say 'the net boot process', I mean the act of loading the image into +memory, setting up any tables, up until the jump to the required location +in the image. + +The net booting program executes the net boot process. The net boot program +may be a rom, but not neccassarily. It is a set of instructions and data +residing on the booting machine. + +The image, or boot image, consists of the data loaded by the net boot process. + +When I say 'the PC boot process', I mean the general PC rom bios boot process, +the setting up of hardware, the scanning for adaptor roms, the execution +of adaptor roms, the loading in of the initial boot track. The PC boot +process will include the net boot process, if one is present. + +When I say client, I mean the PC booting up. + +When I say 'image host', I mean the host where the boot image is comming from. +This may not have the same architecture as the client. + +The bootp protocol is defined in RFC951 and RFC1084. The tftp protocol +is defined in RFC783. These are available on many sites. +See Comer 1991 for details on how to obtain them. + +A bootp server is the machine that answers the bootp request. It is not +neccassarily the image host. + +'Can' and 'may' means doesn't have to, but is allowed to and might. +'Must' means just that. 'Cannot' means must not. + + +9 References + +Comer, D.E. 1991, Internetworking with TCP/IP Vol I: Principles, Protocols, +and Architecture Second Edition, Prentice Hall, Englewood Cliffs, N.J., 1991 + +Stevens, W.R 1990, Unix Network Programming, Prentice Hall, +Englewood Cliffs, N.J., 1990 + + diff --git a/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c b/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c new file mode 100644 index 0000000000..f8eaa0faea --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c @@ -0,0 +1,239 @@ +/*-------------------------------------------------------------------------+ +| bin2boot.c v1.1 - PC386 BSP - 1997/08/18 ++--------------------------------------------------------------------------+ +| This file contains the i386 binary to boot image filter. ++--------------------------------------------------------------------------+ +| (C) Copyright 1997 - +| - NavIST Group - Real-Time Distributed Systems and Industrial Automation +| +| http://pandora.ist.utl.pt +| +| Instituto Superior Tecnico * Lisboa * PORTUGAL ++--------------------------------------------------------------------------+ +| Disclaimer: +| +| This file is provided "AS IS" without warranty of any kind, either +| expressed or implied. ++--------------------------------------------------------------------------*/ + + +#include +#include +#include +#include +#include "bytetype.h" +#include "bootimg.h" + +/*-------------------------------------------------------------------------+ +| Constants ++--------------------------------------------------------------------------*/ +#define SEG_MASK 0xffff0000 + /* Mask for segment part of seg:off address. */ +#define OFF_MASK 0x0000ffff + /* Mask for offset part of seg:off address. */ +#define DEFAULT_START_ADDR 0x10200 /* Default start address for binary. */ +#define BOOTIMG_HDR_SIZE 0x0200 /* Size of output file header. */ +#define BUFFER_BLOCK_SIZE 0x1000 /* Size of transfer buffer size. */ +#define LAST_BLOCK_SIZE 0x0200 + /* The output file must have a size multiple of this value. */ + + +/*-------------------------------------------------------------------------+ +| Macros ++--------------------------------------------------------------------------*/ +#define getSeg(x) (Word)((x) >> 16) + /* Return seg part (Word) of a seg:off address (DWord). */ + +#define getOff(x) (Word)((x) & OFF_MASK) + /* Return off part (Word) of a seg:off address (DWord). */ + +#define getSegOff(x) ((((x) & SEG_MASK) << 12) + ((x) & OFF_MASK)) + /* Converts a flat address to a seg:off address. */ + +/*-------------------------------------------------------------------------+ +| Global Variables ++--------------------------------------------------------------------------*/ +const char UsageMsg[] = "\ +Usage: bin2boot [ []] [-s ] [-v]\n\ +\n\ + : input file name\n\ + : output file name\n\ + -s : start address of binary image\n\ + -m : actual size (for compressed images)\n\ + -v : verbose output\n"; /* Usage message. */ + + +/*-------------------------------------------------------------------------+ +| External Prototypes (for use with getopt) ++--------------------------------------------------------------------------*/ +extern char *optarg; + +int getopt(int, char *const[], const char *); + + +/*-------------------------------------------------------------------------+ +| Auxiliary Functions ++--------------------------------------------------------------------------*/ +static DWord +getNumArg(char *arg) +{ + char *dummy; + + if (arg[0] == '0') + if ((arg[1] == 'x') || (arg[1] == 'X')) /* Hexadecimal */ + return (DWord)strtol(arg, &dummy, 16); + else /* Octal */ + return (DWord)strtol(arg, &dummy, 8); + else /* Decimal */ + return (DWord)strtol(arg, &dummy, 10); +} /* getNumArg */ + + +/*-------------------------------------------------------------------------+ +| Main ++--------------------------------------------------------------------------*/ +void main(int argc, char *argv[]) +{ + FileHeader bootimgFileHdr; /* Output file header. */ + LoadingInfo imageInfo; /* Section header. */ + Byte auxBuf[BUFFER_BLOCK_SIZE]; /* */ + DWord nRead; /* Number of bytes read. */ + Word padSize; /* Size of padding at end of file. */ + + char *progName = argv[0]; /* Program name for errors. */ + FILE *fpIn = stdin; + FILE *fpOut = stdout; + DWord binStart = DEFAULT_START_ADDR; /* Start address of image. */ + DWord memLen = 0; /* Real length for compressed images. */ + + char currArg; + int argCount; + int flag; /* general purpose flag */ + int verbose = 0; /* flag for verbose output */ + + while ((currArg = getopt(argc, argv, "hm:s:v")) >= 0) /* parse command line */ + switch (currArg) + { + case 'h' : + fprintf(stderr, UsageMsg); + exit(0); + break; + case 'm' : + memLen = getNumArg(optarg); + break; + case 's' : + binStart = getNumArg(optarg); + break; + case 'v' : + verbose = 1; + break; + default : + fprintf(stderr, UsageMsg); + exit(1); + break; + } /* switch */ + + flag = 0; + + for (argCount = 1; argCount < argc; argCount++) + if (argv[argCount][0] == '-') + { + if (argv[argCount][1] == 's') + argCount++; + } + else if (flag) /* we already have the input file => output file */ + { + if ((fpOut = fopen(argv[argCount], "w")) == NULL) + { + fprintf(stderr, "%s: can't open %s\n", progName, argv[argCount]); + exit(1); + } + } + else /* input file */ + { + if ((fpIn = fopen(argv[argCount], "r")) == NULL) + { + fprintf(stderr, "%s: can't open %s\n", progName, argv[argCount]); + exit(1); + } + flag = 1; + } + + /*** begin: Conversion to Bootimg */ + + /*** File Header */ + + if (verbose) + fprintf(stderr, "\nBoot Image File Header:\n\n"); + + bootimgFileHdr.magicNum = BOOT_IMAGE_MAGIC; /* 4 bytes - magic number */ + bootimgFileHdr.flagsLen = NON_VENDOR_LEN; /* 4 bytes - flags and length */ + bootimgFileHdr.locAddr = getSegOff(binStart - BOOTIMG_HDR_SIZE); + /* 4 bytes - location address in ds:bx format */ + bootimgFileHdr.execAddr = getSegOff(binStart); + /* 4 bytes - execute address in cs:ip format */ + + if (verbose) + { + fprintf(stderr, ">> location address in ds:bx format: %04x:%04x\n", + getSeg(bootimgFileHdr.locAddr), getOff(bootimgFileHdr.locAddr)); + fprintf(stderr, ">> execute address in cs:ip format: %04x:%04x\n", + getSeg(bootimgFileHdr.execAddr), getOff(bootimgFileHdr.execAddr)); + } + + /*** Write File Header to output file */ + + fwrite((void *)(& bootimgFileHdr), sizeof(FileHeader), 1, fpOut); + + /*** Sections */ + + if (verbose) + fprintf(stderr, "\nCode Section:\n\n"); + + imageInfo.flagsTagsLens = 0x04000004; + /* flags, vendor's tags, vendor and non-vendor lengths */ + imageInfo.loadAddr = binStart; /* load address */ + + rewind(fpIn); + fseek(fpIn, 0, SEEK_END); + nRead = ftell(fpIn); + rewind(fpIn); + padSize = LAST_BLOCK_SIZE - (nRead % LAST_BLOCK_SIZE); + imageInfo.imageLength = nRead + padSize; /* image length */ + imageInfo.memoryLength = (memLen != 0) ? memLen : imageInfo.imageLength; + /* memory length */ + + fwrite((void *)(&imageInfo), sizeof(LoadingInfo), 1, fpOut); + + if (verbose) + { + fprintf(stderr, ">> load address: 0x%08lx\n", imageInfo.loadAddr); + fprintf(stderr, ">> image length: 0x%08lx\n", imageInfo.imageLength); + fprintf(stderr, ">> memory length: 0x%08lx\n\n", imageInfo.memoryLength); + } + + nRead = BOOTIMG_HDR_SIZE - sizeof(FileHeader) - sizeof(LoadingInfo); + memset((void *)auxBuf, 0x00, nRead); + fwrite((void *)auxBuf, 1, nRead, fpOut); + + nRead = fread((void *)auxBuf, 1, BUFFER_BLOCK_SIZE, fpIn); + + while (!feof(fpIn)) + { + fwrite((void *)auxBuf, BUFFER_BLOCK_SIZE, 1, fpOut); + nRead = fread((void *)auxBuf, 1, BUFFER_BLOCK_SIZE, fpIn); + } + + fwrite((void *)auxBuf, 1, nRead, fpOut); + + memset((void *)auxBuf, 0x00, padSize); + fwrite((void *)auxBuf, 1, padSize, fpOut); + + fclose(fpOut); + fclose(fpIn); + + /*** end: Conversion to Bootimg */ + + exit(0); + +} /* main */ -- cgit v1.2.3