Hi,

with the attached patch, grub is able to load tagged images (at least 
those created with mknbi-dos). Tagged linux images aren't supported 
yet. Also some error handling is missing. grub is a real replacement 
for etherboot menus for me now.

Posted here for discussion purposes. Any opinions?

Any chance to get this into grub CVS after some cleanups?

Cheers,
Pete
--- ../grub-0.93/netboot/main.c	2002-06-12 10:58:18.000000000 +0200
+++ netboot/main.c	2003-07-28 14:08:40.000000000 +0200
@@ -49,14 +49,14 @@
 int ip_abort = 0;
 /* Set if an ethernet card is probed and IP addresses are set.  */
 int network_ready = 0;
 
 struct rom_info rom;
+struct bootpd_t bootp_data;
 
 static int vendorext_isvalid;
 static unsigned long netmask;
-static struct bootpd_t bootp_data;
 static unsigned long xid;
 static unsigned char *end_of_rfc1533 = NULL;
 
 #ifndef	NO_DHCP_SUPPORT
 #endif /* NO_DHCP_SUPPORT */
--- ../grub-0.93/stage2/asm.S	2002-12-03 00:18:56.000000000 +0100
+++ stage2/asm.S	2003-07-29 00:56:41.000000000 +0200
@@ -1721,10 +1721,87 @@
 ENTRY(patch_code_end)
 
 	.code32
 
 
+#ifdef SUPPORT_NETBOOT
+/*
+ * taggedimg_boot()
+ *
+ * Does some funky things and then jumps to the entry point
+ */
+VARIABLE(taggedimg_setup)
+	.long	0
+
+VARIABLE(taggedimg_setup_length)
+	.long	0
+
+VARIABLE(taggedimg_entry)
+	.long	0
+
+VARIABLE(taggedimg_bootp)
+	.long	0
+
+ENTRY(taggedimg_boot)
+	/* don't worry about saving anything, we're committed at this point */
+	cld	/* forward copying */
+
+	/* copy setup segment, if necessary */
+	movl	EXT_C(taggedimg_setup_length), %ecx
+	cmpl	$0, %ecx
+	je	1f
+	addl	$3, %ecx
+	shrl	$2, %ecx
+	movl	$0x100000, %esi
+	movl	$0x10000, %edi
+	rep
+	movsl
+
+1:
+	/* XXX new stack pointer in safe area for calling functions */
+	movl	$0x4000, %esp
+	/*call	EXT_C(stop_floppy)*/
+
+	/* final setup for tagged image boot */
+
+	movl	EXT_C(taggedimg_setup), %edx
+	/* convert *BOOTP_DATA_ADDR to seg:off */
+	movl	EXT_C(taggedimg_bootp), %ecx
+	shll	$12, %ecx
+	shrw	$12, %cx
+
+	/* prepare ljmp */
+	movl	EXT_C(taggedimg_entry), %ebx
+	movl	%ebx, taggedimg_jmp
+
+	call	EXT_C(prot_to_real)
+	.code16
+
+	/* final setup for tagged image boot */
+	cli
+	movw	%bx, %ss
+	movw	$9000, %sp
+	
+	movw	%bx, %ds
+	movw	%bx, %es
+	movw	%bx, %fs
+	movw	%bx, %gs
+
+	pushl	%ecx	/* taggedimg_bootp */
+	pushl	%edx	/* taggedimg_setup */
+	pushl	%edx	/* in case of ret */
+
+	/* jump to start */
+	/* ljmp */
+	.byte	0xea
+taggedimg_jmp:	
+	.long	0
+	.code32
+
+#endif /* SUPPORT_NETBOOT */
+
+
 /*
  * linux_boot()
  *
  * Does some funky things (including on the stack!), then jumps to the
  * entry point of the Linux setup code.
--- ../grub-0.93/stage2/boot.c	2002-11-30 18:29:16.000000000 +0100
+++ stage2/boot.c	2003-07-29 01:00:49.000000000 +0200
@@ -23,10 +23,94 @@
 
 #include "freebsd.h"
 #include "imgact_aout.h"
 #include "i386-elf.h"
 
+#ifdef SUPPORT_NETBOOT
+# define GRUB 1
+# include <etherboot.h>
+
+struct imgheader 
+{
+        unsigned long magic;
+        unsigned long length;                   /* and flags */
+        union
+        {
+                struct { unsigned short bx, ds; } segoff;
+                unsigned long location;
+        } u;
+        unsigned long execaddr;
+};
+
+#define TAGGED_MAGIC 0x1b031336
+
+struct segheader
+{
+        unsigned char length;
+        unsigned char vendortag;
+        unsigned char reserved; 
+        unsigned char flags;
+        unsigned long loadaddr;
+        unsigned long imglength;
+        unsigned long memlength;
+};
+
+/* Keep all context about loaded image in one place */
+static struct tagged_context
+{
+        struct imgheader        img;                    /* copy of header */
+        unsigned long           linlocation;            /* addr of header */
+        unsigned long           last0, last1;           /* of prev segment */
+        unsigned long           segaddr, seglen;        /* of current segment */
+        unsigned char           segflags;
+} tctx;
+
+#define TAGGED_PROGRAM_RETURNS  (tctx.img.length & 0x00000100)  /* bit 8 */
+#define LINEAR_EXEC_ADDR        (tctx.img.length & 0x80000000)  /* bit 31 */
+
+static struct ebinfo            loaderinfo = {
+        5,0, /* VERSION_MAJOR, VERSION_MINOR, */
+        0
+};
+
+#endif /* SUPPORT_NETBOOT */
+
+#if 0
+/* for debugging */
+static void hexdump(unsigned char *buf, unsigned len)
+{
+  int i, j = 0;
+  char s[17];
+  unsigned addr = (unsigned) buf;
+
+  s[16] = 0;
+  while(len--) {
+    i = buf[j];
+    i = i & 0xff;
+    s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.';
+    if(!(j & 15)) {
+      printf("%x  ", j + addr);
+    }
+    if(!(j & 7) && (j & 15)) printf(" ");
+    /* stupid grub_printf */
+    printf("%x", (i >> 4) & 0x0f);
+    printf("%x ", i & 0x0f);
+    if(!(++j & 15)) {
+      printf(" %s\n", s);
+    }
+  }
+
+  if(j & 15) {
+    s[j & 15] = 0;
+    if(!(j & 8)) printf(" ");
+    i = 1 + 3 * (16 - (j & 15));
+    while(i--) printf(" ");
+    printf("%s\n", s);
+  }
+}
+#endif
+
 static int cur_addr;
 entry_func entry_addr;
 static struct mod_list mll[99];
 static int linux_mem_size;
 
@@ -89,10 +173,91 @@
 	  str2 = "Multiboot";
 	  break;
 	}
     }
 
+#ifdef SUPPORT_NETBOOT
+
+  /* check for tagged image */
+  if ((type == KERNEL_TYPE_NONE) && (*((unsigned long *)buffer) == TAGGED_MAGIC))
+    {
+      type = KERNEL_TYPE_TAGGEDIMAGE;
+      str2 = "Tagged Image";
+      taggedimg_setup = NULL;
+      taggedimg_setup_length = 0;
+      taggedimg_entry = NULL;
+      taggedimg_bootp = NULL;
+      printf("Tagged image detected\n");
+      /* Zero all context info */
+      grub_memset(&tctx, 0, sizeof(tctx));
+      /* Copy first 4 longwords */
+      grub_memmove(&tctx.img, buffer, sizeof(tctx.img));
+      /* Memory location where we are supposed to save it */
+      tctx.segaddr = tctx.linlocation = ((tctx.img.u.segoff.ds) << 4) + tctx.img.u.segoff.bx;
+
+      /* Grab a copy */
+      if (tctx.segaddr < 0x90000) {
+	  /* We won't overwrite grub, move stuff to a temporary location */
+	  tctx.segaddr += 0xf0000;
+	  taggedimg_setup_length = 512;
+      }
+      grub_memmove((void *)tctx.segaddr, buffer, 512);
+      tctx.segaddr += ((tctx.img.length & 0x0F) << 2) + ((tctx.img.length & 0xF0) >> 2);
+      //printf("segaddr: %x, seglen: %d, segflags: %x\n", tctx.segaddr, tctx.seglen, tctx.segflags);
+
+      grub_seek(512);
+
+      while (1) 
+	{
+	  if (tctx.seglen == 0) {
+	    struct segheader sh;
+	    if (tctx.segflags & 0x04) {
+	      taggedimg_entry = (char *)(tctx.img.execaddr);
+	      taggedimg_setup = (char *)(tctx.img.u.location);
+	      taggedimg_bootp = (char *)BOOTP_DATA_ADDR;
+	      //printf("entry: %x, setup: %x, bootp: %x\n", taggedimg_entry, taggedimg_setup, taggedimg_bootp);
+	      printf("done");
+	      break;
+	    }
+	    sh = *((struct segheader *)tctx.segaddr);
+	    tctx.seglen = sh.imglength;
+	    if ((tctx.segflags = sh.flags & 0x03) == 0)
+		    cur_addr = sh.loadaddr;
+	    else if (tctx.segflags == 0x01)
+		    cur_addr = tctx.last1 + sh.loadaddr;
+	    else if (tctx.segflags == 0x02) {
+		    //cur_addr = (Address)(meminfo.memsize * 1024L
+		      //		  + 0x100000L)
+		      //      - sh.loadaddr;
+	    }
+	    else
+		    cur_addr = tctx.last0 - sh.loadaddr;
+	    tctx.last1 = (tctx.last0 = cur_addr) + sh.memlength;
+	    tctx.segflags = sh.flags;
+	    tctx.segaddr += ((sh.length & 0x0F) << 2)
+		    + ((sh.length & 0xF0) >> 2);
+	  }
+	  //printf("segaddr: %x, seglen: %d, segflags: %x\n", tctx.segaddr, tctx.seglen, tctx.segflags);
+
+	  if (tctx.seglen) {
+	      /* another segment */
+	      if (cur_addr < 0x90000) {
+		  cur_addr += 0xf0000;
+		  taggedimg_setup_length = (cur_addr - 0x100000) + tctx.seglen;
+	      }
+	      //printf("cur_addr: %x, len: %d (%d)\n", cur_addr, tctx.seglen, taggedimg_setup_length);
+	      grub_read((char *) RAW_ADDR(cur_addr), tctx.seglen);
+	      tctx.seglen = 0;
+	  } 
+	  else break;
+	}
+      grub_close ();
+      return type;
+    }
+
+#endif /* SUPPORT_NETBOOT */
+
   /* Use BUFFER as a linux kernel header, if the image is Linux zImage
      or bzImage.  */
   lh = (struct linux_kernel_header *) buffer;
   
   /* ELF loading supported if multiboot, FreeBSD and NetBSD.  */
--- ../grub-0.93/stage2/builtins.c	2002-12-04 05:41:57.000000000 +0100
+++ stage2/builtins.c	2003-07-29 01:10:12.000000000 +0200
@@ -295,10 +295,17 @@
     case KERNEL_TYPE_MULTIBOOT:
       /* Multiboot */
       multi_boot ((int) entry_addr, (int) &mbi);
       break;
 
+#ifdef SUPPORT_NETBOOT
+    case KERNEL_TYPE_TAGGEDIMAGE:
+      /* Tagged Image */
+      taggedimg_boot ();
+      break;
+#endif
+
     default:
       errnum = ERR_BOOT_COMMAND;
       return 1;
     }
 
--- ../grub-0.93/stage2/shared.h	2002-12-03 00:15:12.000000000 +0100
+++ stage2/shared.h	2003-07-29 01:05:22.000000000 +0200
@@ -547,10 +547,16 @@
 extern char version_string[];
 extern char config_file[];
 extern unsigned long linux_text_len;
 extern char *linux_data_tmp_addr;
 extern char *linux_data_real_addr;
+#ifdef SUPPORT_NETBOOT
+extern char *taggedimg_setup;
+extern unsigned long taggedimg_setup_length;
+extern char *taggedimg_entry;
+extern char *taggedimg_bootp;
+#endif /* SUPPORT_NETBOOT */
 
 #ifdef GRUB_UTIL
 /* If not using config file, this variable is set to zero,
    otherwise non-zero.  */
 extern int use_config_file;
@@ -711,10 +717,15 @@
      __attribute__ ((noreturn));
 void chain_stage2 (unsigned long segment, unsigned long offset,
 		   int second_sector)
      __attribute__ ((noreturn));
 
+#ifdef SUPPORT_NETBOOT
+/* do some funky stuff, then boot a tagged image */
+void taggedimg_boot (void) __attribute__ ((noreturn));
+#endif
+
 /* do some funky stuff, then boot linux */
 void linux_boot (void) __attribute__ ((noreturn));
 
 /* do some funky stuff, then boot bzImage linux */
 void big_linux_boot (void) __attribute__ ((noreturn));
@@ -829,11 +840,14 @@
   KERNEL_TYPE_MULTIBOOT,	/* Multiboot.  */
   KERNEL_TYPE_LINUX,		/* Linux.  */
   KERNEL_TYPE_BIG_LINUX,	/* Big Linux.  */
   KERNEL_TYPE_FREEBSD,		/* FreeBSD.  */
   KERNEL_TYPE_NETBSD,		/* NetBSD.  */
-  KERNEL_TYPE_CHAINLOADER	/* Chainloader.  */
+  KERNEL_TYPE_CHAINLOADER,	/* Chainloader.  */
+#ifdef SUPPORT_NETBOOT
+  KERNEL_TYPE_TAGGEDIMAGE,	/* Netboot Tagged Image */
+#endif /* SUPPORT_NETBOOT */
 }
 kernel_t;
 
 extern kernel_t kernel_type;
 extern int show_menu;
_______________________________________________
Bug-grub mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/bug-grub

Reply via email to