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