[EMAIL PROTECTED] (Eric W. Biederman) writes:

> Anyway I'll see if I can get a good patch out in the next couple of
> days.
Make that hours.

Here is my preliminar patch.
The code present in it is good, but it still doesn't integrate into
Etherboot quite right.  In particular it refuses to build if you give
it options it doesn't support when running under linuxBIOS.  It
probably just needs a different make target or the like.

The code is archived at:
ftp://download.linuxnetworx.com/pub/src/etherboot

The patch is against etherboot-5.1.0

Eric

diff -uNr --exclude=Roms etherboot-5.1.0/src/Config etherboot-5.1.0.eb1/src/Config
--- etherboot-5.1.0/src/Config  Sun May  6 23:55:54 2001
+++ etherboot-5.1.0.eb1/src/Config      Thu Jun 21 00:54:57 2001
@@ -170,6 +170,11 @@
 #                      Define this for PCI BIOSes that do not implement
 #                      BIOS32 or not correctly. Normally not needed.
 #                      Only works for BIOSes of a certain era.
+#      -DCONFIG_TSC_CURRTICKS
+#                       Uses the processor time stamp counter instead of reading
+#                       the BIOS time counter.  This allows etherboot to work
+#                       even without a BIOS.  This only works on late model
+#                       486s and above.
 #
 #      Obscure options you probably don't need to touch:
 #
@@ -219,11 +224,14 @@
 
 # Enable tagged image, generic ELF, Multiboot ELF
 # or FreeBSD ELF/a.out boot image support
-CFLAGS32+=     -DTAGGED_IMAGE -DELF_IMAGE
+#CFLAGS32+=    -DTAGGED_IMAGE -DELF_IMAGE
 # CFLAGS32+=   -DAOUT_IMAGE -DIMAGE_MULTIBOOT -DIMAGE_FREEBSD
 
 # Change download protocol to NFS, default is TFTP
 # CFLAGS32+=   -DDOWNLOAD_PROTO_NFS
+
+# Options to make a version of etherboot that will work under linuxBIOS.
+CFLAGS32+= -DCONFIG_TSC_CURRTICKS  -DCONSOLE_SERIAL -DCOMCONSOLE=0x3f8 
+-DCONSPEED=115200 -DCONFIG_PCI_DIRECT -DELF_IMAGE -DIMAGE_MULTIBOOT
 
 # These flags affect the loader that is prepended to the Etherboot image
 LCONFIG+=      -DMOVEROM
diff -uNr --exclude=Roms etherboot-5.1.0/src/Makefile etherboot-5.1.0.eb1/src/Makefile
--- etherboot-5.1.0/src/Makefile        Sat May 26 17:45:39 2001
+++ etherboot-5.1.0.eb1/src/Makefile    Thu Jun 21 01:53:22 2001
@@ -84,11 +84,12 @@
 
 GCC=           gcc
 CPP=           gcc -E
+STRIP=         strip
 OBJCOPY=       objcopy
 VERSION_MAJOR= 5
 VERSION_MINOR= 1
 VERSION_PATCH= 0
-VERSION=       $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
+VERSION=       $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH).eb1
 CFLAGS32+=     -DVERSION_MAJOR=$(VERSION_MAJOR) \
                -DVERSION_MINOR=$(VERSION_MINOR) \
                -DVERSION=\"$(VERSION)\" -DRELOC=$(RELOCADDR) $(OLDGAS)
@@ -152,6 +153,7 @@
 LILOPREFIX=    bin/liloprefix.bin
 
 START32=       bin32/start32.o
+UBE_START32 = bin32/ube_start32.o bin32/ube.o
 
 BOBJS32=       bin32/main.o bin32/osloader.o bin32/nfs.o bin32/misc.o
 BOBJS32+=      bin32/ansiesc.o bin32/bootmenu.o bin32/md5.o bin32/floppy.o
@@ -160,6 +162,7 @@
 LIBS32=                $(BLIB32) $(LIBC32)
 UTILS+=                bin/makerom bin/lzhuf
 STDDEPS32=     $(START32) $(BLIB32) $(UTILS)
+UBE_DEPS32=    $(UBE_START32) $(BLIB2)
 MAKEDEPS=      Makefile Config Roms
 
 CHECKSIZE=     { read d1; read d1 d2 d3 size d4; [ $$size -gt $(ROMLIMIT) ] &&\
@@ -366,6 +369,7 @@
        $(RM) bin32/*.com
        $(RM) bin32/*.dsk bin32/*.lzdsk
        $(RM) bin32/*.lilo bin32/*.lzlilo
+       $(RM) bin32/*.elf bin32/*.ebi
 
 tarball:
        (echo -n $(VERSION) ''; date -u +'%Y-%m-%d') > ../VERSION
diff -uNr --exclude=Roms etherboot-5.1.0/src/etherboot.h 
etherboot-5.1.0.eb1/src/etherboot.h
--- etherboot-5.1.0/src/etherboot.h     Sat May 26 17:47:14 2001
+++ etherboot-5.1.0.eb1/src/etherboot.h Thu Jun 21 00:45:53 2001
@@ -531,6 +531,10 @@
 extern void xend P((void));
 #endif
 extern unsigned long currticks P((void));
+#if !defined(CONFIG_TSC_CURRTICKS)
+extern unsigned long __currticks P((void));
+#define currticks __currticks
+#endif /* RTC_CURRTICKS */
 extern int setjmp P((jmpbuf env));
 extern void longjmp P((jmpbuf env, int val));
 extern void exit P((int status));
diff -uNr --exclude=Roms etherboot-5.1.0/src/genrules.pl 
etherboot-5.1.0.eb1/src/genrules.pl
--- etherboot-5.1.0/src/genrules.pl     Mon Apr 23 07:51:53 2001
+++ etherboot-5.1.0.eb1/src/genrules.pl Thu Jun 21 00:00:08 2001
@@ -89,7 +89,7 @@
        }
 }
 foreach $key (sort keys %roms_pci) {
-       print "BINS32\t+= bin32/$key.rom bin32/$key.lzrom\n";
+       print "BINS32\t+= bin32/$key.rom bin32/$key.lzrom bin32/$key.ebi\n";
 }
 foreach $key (sort keys %roms_isa) {
        print "BINS32\t+= bin32/$key.rom bin32/$key.lzrom\n";
@@ -141,6 +141,9 @@
        cat \$(PRZLOADER) \$< > \$@
        bin/makerom \$(MAKEROM_\$*) -p $ids -i\$(IDENT32) \$@
 
+bin32/$rom.ebi: bin32/$drv.elf
+       cp bin32/$drv.elf \$@
+       \$(STRIP) -R .comment -R .note \$@
 EOF
 }
 foreach $rom (sort keys %roms_isa) {
@@ -160,6 +163,10 @@
        print <<EOF;
 bin32/$key.tmp:        bin32/$key.o bin32/config-$key.o bin32/pci.o \$(STDDEPS32)
        \$(LD32) \$(LDFLAGS32) -o \$@ \$(START32) bin32/config-$key.o bin32/$key.o 
bin32/pci.o \$(LIBS32)
+       @\$(SIZE32) \$@ | \$(CHECKSIZE)
+
+bin32/$key.elf: bin32/$key.o bin32/config-$key.o bin32/pci.o \$(UBE_DEPS32)
+       \$(LD32) \$(LDFLAGS32) -o \$@ \$(UBE_START32) bin32/config-$key.o bin32/$key.o 
+bin32/pci.o \$(LIBS32)
        @\$(SIZE32) \$@ | \$(CHECKSIZE)
 
 bin32/$key.img:        bin32/$key.o bin32/$key.tmp bin32/config-$key.o bin32/pci.o 
\$(STDDEPS32)
diff -uNr --exclude=Roms etherboot-5.1.0/src/start32.S 
etherboot-5.1.0.eb1/src/start32.S
--- etherboot-5.1.0/src/start32.S       Thu Mar  8 04:51:42 2001
+++ etherboot-5.1.0.eb1/src/start32.S   Thu Jun 21 00:05:09 2001
@@ -118,8 +118,8 @@
 today) and byte 0040:0070 (midnight crossover flag) instead of calling
 timeofday BIOS interrupt.
 **************************************************************************/
-       .globl  currticks
-currticks:
+       .globl  __currticks
+__currticks:
        pushl   %ebp
        pushl   %ebx
        pushl   %esi
diff -uNr --exclude=Roms etherboot-5.1.0/src/timer.c etherboot-5.1.0.eb1/src/timer.c
--- etherboot-5.1.0/src/timer.c Sun Dec 10 00:40:48 2000
+++ etherboot-5.1.0.eb1/src/timer.c     Thu Jun 21 00:43:58 2001
@@ -18,3 +18,110 @@
        outb(ticks & 0xFF, TIMER2_PORT);
        outb(ticks >> 8, TIMER2_PORT);
 }
+
+#if defined(CONFIG_TSC_CURRTICKS)
+#define rdtsc(low,high) \
+     __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
+
+#define rdtscll(val) \
+     __asm__ __volatile__ ("rdtsc" : "=A" (val))
+
+
+#define HZ TICKS_PER_SEC
+#define CLOCK_TICK_RATE        1193180U /* Underlying HZ */
+/* LATCH is used in the interval timer and ftape setup. */
+#define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
+
+
+/* ------ Calibrate the TSC ------- 
+ * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
+ * Too much 64-bit arithmetic here to do this cleanly in C, and for
+ * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
+ * output busy loop as low as possible. We avoid reading the CTC registers
+ * directly because of the awkward 8-bit access mechanism of the 82C54
+ * device.
+ */
+
+#define CALIBRATE_LATCH        (5 * LATCH)
+
+static unsigned long long calibrate_tsc(void)
+{
+       /* Set the Gate high, disable speaker */
+       outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+       /*
+        * Now let's take care of CTC channel 2
+        *
+        * Set the Gate high, program CTC channel 2 for mode 0,
+        * (interrupt on terminal count mode), binary count,
+        * load 5 * LATCH count, (LSB and MSB) to begin countdown.
+        */
+       outb(0xb0, 0x43);                       /* binary, mode 0, LSB/MSB, Ch 2 */
+       outb(CALIBRATE_LATCH & 0xff, 0x42);     /* LSB of count */
+       outb(CALIBRATE_LATCH >> 8, 0x42);       /* MSB of count */
+
+       {
+               unsigned long startlow, starthigh;
+               unsigned long endlow, endhigh;
+               unsigned long count;
+
+               rdtsc(startlow,starthigh);
+               count = 0;
+               do {
+                       count++;
+               } while ((inb(0x61) & 0x20) == 0);
+               rdtsc(endlow,endhigh);
+
+               /* Error: ECTCNEVERSET */
+               if (count <= 1)
+                       goto bad_ctc;
+
+               /* 64-bit subtract - gcc just messes up with long longs */
+               __asm__("subl %2,%0\n\t"
+                       "sbbl %3,%1"
+                       :"=a" (endlow), "=d" (endhigh)
+                       :"g" (startlow), "g" (starthigh),
+                        "0" (endlow), "1" (endhigh));
+
+               /* Error: ECPUTOOFAST */
+               if (endhigh)
+                       goto bad_ctc;
+
+               endlow /= 5;
+               return endlow;
+       }
+
+       /*
+        * The CTC wasn't reliable: we got a hit on the very first read,
+        * or the CPU was so fast/slow that the quotient wouldn't fit in
+        * 32 bits..
+        */
+bad_ctc:
+       printf("bad_ctc\n");
+       return 0;
+}
+
+
+unsigned long currticks(void)
+{
+       static unsigned long clocks_per_tick;
+       unsigned long clocks_high, clocks_low;
+       unsigned long currticks;
+       if (!clocks_per_tick) {
+               clocks_per_tick = calibrate_tsc();
+               printf("clocks_per_tick = %d\n", clocks_per_tick);
+       }
+
+       /* Read the Time Stamp Counter */
+       rdtsc(clocks_low, clocks_high);
+
+       /* currticks = clocks / clocks_per_tick; */
+       __asm__("divl %1"
+               :"=a" (currticks)
+               :"r" (clocks_per_tick), "0" (clocks_low), "d" (clocks_high));
+
+
+       return currticks;
+}
+
+#endif /* RTC_CURRTICKS */
diff -uNr --exclude=Roms etherboot-5.1.0/src/ube.c etherboot-5.1.0.eb1/src/ube.c
--- etherboot-5.1.0/src/ube.c   Wed Dec 31 17:00:00 1969
+++ etherboot-5.1.0.eb1/src/ube.c       Thu Jun 21 01:49:44 2001
@@ -0,0 +1,159 @@
+#include "etherboot.h"
+#include "uniform_boot.h"
+
+static struct bootinfo {
+       unsigned base_mem_k;
+       unsigned high_mem_k;
+} bootinfo;
+
+
+
+static unsigned long uniform_boot_compute_header_checksum(
+       struct uniform_boot_header *header)
+{
+       unsigned short *ptr;
+       unsigned long sum;
+       unsigned long len;
+       /* compute an ip style checksum on the header */
+       sum = 0;
+       len = header->header_bytes >> 1;
+       ptr = (void *)header;
+       while (len--) {
+               sum += *(ptr++);
+               if (sum > 0xFFFF)
+                       sum -= 0xFFFF;
+       }
+       return (~sum) & 0xFFFF;
+}
+
+static void set_base_mem_k(struct bootinfo *info, unsigned mem_k)
+{
+       if ((mem_k <= 640) && (info->base_mem_k <= mem_k)) {
+               info->base_mem_k = mem_k;
+       }
+}
+static void set_high_mem_k(struct bootinfo *info, unsigned mem_k)
+{
+       /* Shave off a megabyte before playing */
+       if (mem_k < 1024) {
+               return;
+       }
+       mem_k -= 1024;
+       if (info->high_mem_k <= mem_k) {
+               info->high_mem_k = mem_k;
+       }
+}
+static void read_uniform_boot_memory(
+       struct bootinfo *info, struct ube_memory *mem)
+{
+       int i;
+       int entries;
+       entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
+       for(i = 0; (i < entries); i++) {
+               switch(mem->map[i].type) {
+               case UBE_MEM_RAM:
+               {
+                       unsigned long long high;
+                       unsigned long mem_k;
+                       high = mem->map[i].start + mem->map[i].size;
+#if defined(DEBUG_UBE)
+                       printf("ube: ram start: %X%X size: %X%X high: %X%X\n",
+                               (unsigned long)(mem->map[i].start >>32), 
+                               (unsigned long)(mem->map[i].start & 0xFFFFFFFF), 
+                               (unsigned long)(mem->map[i].size >> 32),
+                               (unsigned long)(mem->map[i].size  & 0xFFFFFFFF),
+                               (unsigned long)(high >> 32), 
+                               (unsigned long)(high & 0xFFFFFFFF));
+#endif /* DEBUG_UBE */
+                       high >>= 10;
+                       mem_k = high;
+                       if (high & 0xFFFFFFFF00000000ULL) {
+                               mem_k = 0xFFFFFFFF;
+                       }
+                       set_base_mem_k(info, mem_k);
+                       set_high_mem_k(info, mem_k);
+                       break;
+               }
+               case UBE_MEM_ACPI:
+                       break;
+               case UBE_MEM_NVS:
+                       break;
+               case UBE_MEM_RESERVED:
+               default:
+                       break;
+               }
+       }
+}
+
+
+static void read_uniform_boot_data(struct bootinfo *info,
+       struct uniform_boot_header *header)
+{
+       /* Uniform boot environment */
+       unsigned long env_bytes;
+       char *env;
+       unsigned long checksum;
+       checksum = uniform_boot_compute_header_checksum(header);
+       if (checksum != 0) {
+               printf("Bad uniform boot header checksum!\n");
+       }
+       if (header->arg_bytes) {
+               /* Ignore the command line I am passed */
+       }
+       env = (void *)(header->env);
+       env_bytes = header->env_bytes;
+       while(env_bytes) {
+               struct ube_record *record;
+               unsigned long mem_k;
+               record = (void *)env;
+               if (record->tag == UBE_TAG_MEMORY) {
+                       read_uniform_boot_memory(info, (void *)record);
+               }
+               env += record->size;
+               env_bytes -= record->size;
+       }
+}
+
+static void initialize_bootinfo(void)
+{
+       extern unsigned long initeax;
+       extern unsigned long initebx;
+       static int initialized = 0;
+       unsigned long type;
+       void *ptr;
+       if (initialized) {
+               return;
+       }
+       initialized = 1;
+#if defined(DEBUG_UBE)
+       printf("\nReading bootinfo initeax = %X initebx = %X\n",
+               initeax, initebx);
+#endif /* DEBUG_UBE */
+       type = initeax;
+       ptr = (void *)initebx;
+       bootinfo.base_mem_k = 0;
+       bootinfo.high_mem_k = 0;
+       if (type == 0x0A11B007) {
+               read_uniform_boot_data(&bootinfo, ptr);
+       }
+       if (bootinfo.base_mem_k == 0) {
+               printf("No base memory found assuming 640K\n");
+               bootinfo.base_mem_k = 640;
+       }
+#if defined(DEBUG_UBE)
+       printf("base_mem_k = %d high_mem_k = %d\n", 
+               bootinfo.base_mem_k, bootinfo.high_mem_k);
+#endif /* DEBUG_UBE */
+}
+unsigned short basememsize(void)
+{
+       initialize_bootinfo();
+       return bootinfo.base_mem_k;
+}
+
+unsigned int memsize(void)
+{
+       initialize_bootinfo();
+       return bootinfo.high_mem_k;
+}
+
diff -uNr --exclude=Roms etherboot-5.1.0/src/ube_start32.S 
etherboot-5.1.0.eb1/src/ube_start32.S
--- etherboot-5.1.0/src/ube_start32.S   Wed Dec 31 17:00:00 1969
+++ etherboot-5.1.0.eb1/src/ube_start32.S       Thu Jun 21 01:18:17 2001
@@ -0,0 +1,165 @@
+/* #defines because ljmp wants a number, probably gas bug */
+/*     .equ    KERN_CODE_SEG,_pmcs-_gdt        */
+#define        KERN_CODE_SEG   0x08
+       .equ    KERN_DATA_SEG,_pmds-_gdt
+/*     .equ    REAL_CODE_SEG,_rmcs-_gdt        */
+#define        REAL_CODE_SEG   0x18
+       .equ    REAL_DATA_SEG,_rmds-_gdt
+       .equ    CR0_PE,1
+
+#ifdef GAS291
+#define DATA32 data32;
+#define ADDR32 addr32;
+#define        LJMPI(x)        ljmp    x
+#else
+#define DATA32 data32
+#define ADDR32 addr32
+/* newer GAS295 require #define        LJMPI(x)        ljmp    *x */
+#define        LJMPI(x)        ljmp    x
+#endif
+
+/*
+ * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
+ * then you only have to take care of %ebx, %esi, %edi and %ebp.  These
+ * registers must not be altered under any circumstance.  All other registers
+ * may be clobbered without any negative side effects.  If you don't follow
+ * this rule then you'll run into strange effects that only occur on some
+ * gcc versions (because the register allocator may use different registers).
+ *
+ * All the data32 prefixes for the ljmp instructions are necessary, because
+ * the assembler emits code with a relocation address of 0.  This means that
+ * all destinations are initially negative, which the assembler doesn't grok,
+ * because for some reason negative numbers don't fit into 16 bits. The addr32
+ * prefixes are there for the same reasons, because otherwise the memory
+ * references are only 16 bit wide.  Theoretically they are all superfluous.
+ * One last note about prefixes: the data32 prefixes on all call _real_to_prot
+ * instructions could be removed if the _real_to_prot function is changed to
+ * deal correctly with 16 bit return addresses.  I tried it, but failed.
+ */
+
+       
+
+/**************************************************************************
+START - Where all the fun begins....
+**************************************************************************/
+/* this must be the first thing in the file because we enter from the top */
+       .global _start
+       .code32
+#ifdef IMAGE_MULTIBOOT
+/**************************************************************************
+XEND - Restart Etherboot from the beginning (from protected mode)
+**************************************************************************/
+       .globl xend
+xend:
+#endif
+_start:
+       cli
+
+       cs;lgdt gdtarg  
+       ljmp    $KERN_CODE_SEG, $1f
+1:
+       /* reload other segment registers */
+       movl    $KERN_DATA_SEG, %ebp
+       movl    %ebp,%ds
+       movl    %ebp,%es
+       movl    %ebp,%ss
+       movl    %ebp,%fs
+       movl    %ebp,%gs
+
+       movl    %esp, initesp
+       movl    %eax, initeax
+       movl    %ebx, initebx
+
+       movl    $_estack, %esp
+
+       call    main
+       /* fall through */
+
+       .globl  exit
+exit:
+       movl    initesp, %esp
+       ret
+
+
+/**************************************************************************
+SETJMP - Save stack context for non-local goto
+**************************************************************************/
+       .globl  setjmp
+setjmp:
+       movl    4(%esp),%ecx
+       movl    0(%esp),%edx
+       movl    %edx,0(%ecx)
+       movl    %ebx,4(%ecx)
+       movl    %esp,8(%ecx)
+       movl    %ebp,12(%ecx)
+       movl    %esi,16(%ecx)
+       movl    %edi,20(%ecx)
+       movl    %eax,24(%ecx)
+       movl    $0,%eax
+       ret
+
+/**************************************************************************
+LONGJMP - Non-local jump to a saved stack context
+**************************************************************************/
+       .globl  longjmp
+longjmp:
+       movl    4(%esp),%edx
+       movl    8(%esp),%eax
+       movl    0(%edx),%ecx
+       movl    4(%edx),%ebx
+       movl    8(%edx),%esp
+       movl    12(%edx),%ebp
+       movl    16(%edx),%esi
+       movl    20(%edx),%edi
+       cmpl    $0,%eax
+       jne     1f
+       movl    $1,%eax
+1:     movl    %ecx,0(%esp)
+       ret
+
+/**************************************************************************
+GLOBAL DESCRIPTOR TABLE
+**************************************************************************/
+       .align  4
+_gdt:
+gdtarg:
+       .word   0x27                    /* limit */
+       .long   _gdt                    /* addr */
+       .word   0
+
+_pmcs:
+       /* 32 bit protected mode code segment */
+       .word   0xffff,0
+       .byte   0,0x9f,0xcf,0
+
+_pmds:
+       /* 32 bit protected mode data segment */
+       .word   0xffff,0
+       .byte   0,0x93,0xcf,0
+
+_rmcs:
+       /* 16 bit real mode code segment */
+       .word   0xffff,(RELOC&0xffff)
+       .byte   (RELOC>>16),0x9b,0x00,(RELOC>>24)
+
+_rmds:
+       /* 16 bit real mode data segment */
+       .word   0xffff,(RELOC&0xffff)
+       .byte   (RELOC>>16),0x93,0x00,(RELOC>>24)
+
+initesp: .long 0
+       .globl initeax
+initeax: .long 0
+       .globl initebx
+initebx: .long 0
+
+
+       .align  4
+
+       .section ".bss"
+       .p2align 3
+       /* allocate a 4K stack in the bss segment */
+_stack:
+       .space 4096
+_estack:
+       
diff -uNr --exclude=Roms etherboot-5.1.0/src/uniform_boot.h 
etherboot-5.1.0.eb1/src/uniform_boot.h
--- etherboot-5.1.0/src/uniform_boot.h  Wed Dec 31 17:00:00 1969
+++ etherboot-5.1.0.eb1/src/uniform_boot.h      Thu Jun 21 00:08:06 2001
@@ -0,0 +1,67 @@
+#ifndef __UNIFORM_BOOT_H
+#define __UNIFORM_BOOT_H
+
+/* The uniform boot environment information is restricted to 
+ * hardware information.  In particular for a simple enough machine
+ * all of the environment information should be able to reside in
+ * a rom and not need to be moved.  This information is the
+ * information a trivial boot room can pass to linux to let it
+ * run the hardware.  
+ *
+ * Also all of the information should be Position Independent Data.  
+ * That is it should be safe to relocated any of the information
+ * without it's meaning/correctnes changing. The exception is the
+ * uniform_boot_header with it's two pointers arg & env.
+ * 
+ * The addresses in the arg & env pointers must be physical
+ * addresses. A physical address is an address you put in the page
+ * table. 
+ *
+ * The Command line is for user policy.  Things like the default
+ * root device.
+ * 
+ */
+
+struct uniform_boot_header
+{
+       unsigned long header_bytes;
+       unsigned long header_checksum;
+       unsigned long arg;
+       unsigned long arg_bytes;
+       unsigned long env;
+       unsigned long env_bytes;
+};
+
+/* Every entry in the boot enviroment list will correspond to a boot
+ * info record.  Encoding both type and size.  The type is obviously
+ * so you can tell what it is.  The size allows you to skip that
+ * boot enviroment record if you don't know what it easy.  This allows
+ * forward compatibility with records not yet defined.
+ */
+struct ube_record {
+       unsigned long tag;              /* tag ID */
+       unsigned long size;             /* size of record (in bytes) */
+       unsigned long data[0];          /* data */
+};
+
+
+#define UBE_TAG_MEMORY 0x0001
+
+struct ube_memory_range {
+       unsigned long long start;
+       unsigned long long size;
+       unsigned long type;
+#define UBE_MEM_RAM      1
+#define UBE_MEM_RESERVED 2
+#define UBE_MEM_ACPI     3
+#define UBE_MEM_NVS      4
+       
+};
+
+struct ube_memory {
+       unsigned long tag;
+       unsigned long size;
+       struct ube_memory_range map[0];
+};
+
+#endif /* _UNIFORM_BOOT_H */

Reply via email to