grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] memdisk plus lnxboot extension


From: Bean
Subject: Re: [PATCH] memdisk plus lnxboot extension
Date: Wed, 23 Jan 2008 00:22:32 +0800

On Jan 22, 2008 9:57 PM, Robert Millan <address@hidden> wrote:
> On Tue, Jan 22, 2008 at 12:25:49PM +0800, Bean wrote:
> > > but, what is the advantage in that?  Is there any use case in which the 
> > > first
> > > option is not good but the second is?
> >
> > Some advantages of using external initrd:
> >
> > 1, Resolve size limit for core.img
> > core.img can't be too large, otherwise it doesn't fit inside
> > conventional memory. external initrd doesn't have this problem.
>
> Ok.
>
> > 2. Easy to modify
> > users may not know how to create core.img, but modifying files in a,
> > say, tar or cpio archive is very easy. They can do simple tasks like
> > replacing splash image without too much knowledge of grub2.
> >
> > 3. Multiple configuration
> > We can use the same core.img, but different initrd to start grub2 with
> > different configuration.
>
> I don't think these two make a big difference, but well.
>
> No objection from me, then.

this is the patch, please try it.

        * boot/i386/pc/lnxboot.S (data_start) : Simplify code.
        (real_code_2) : Set grub_memdisk_image_addr using initrd address.

        * include/grub/i386/pc/boot.h : New constant
        GRUB_BOOT_MACHINE_LNX_LENG_OFFSET.

        * include/grub/i386/pc/kernel.h : New constant
        GRUB_KENRL_MACHINE_MEMDISK_IMAGE_ADDR.
        New variable grub_memdisk_image_addr.

        * kern/i386/pc/init.c (grub_arch_memdisk_addr) : Use
        grub_memdisk_image_addr if it isn't zero.

        * kern/i386/pc/startup.S : New variable grub_memdisk_image_addr.

        * util/i386/pc/grub-mkimage.c (generate_image) : Add is_linux parameter.
        If it's set, use lnxboot.img as header instead of diskboot.img.
        (options): Add "linux"|'x' option
        (main): Parse --linux|-x option, and pass its value to generate_image.


diff --git a/boot/i386/pc/lnxboot.S b/boot/i386/pc/lnxboot.S
index f1a4ded..6503e26 100644
--- a/boot/i386/pc/lnxboot.S
+++ b/boot/i386/pc/lnxboot.S
@@ -36,22 +36,7 @@
         .globl  start, _start

 data_start:
-       pushw   %cs
-       popw    %ds
-       xorl    %eax, %eax
-       xorl    %ebx, %ebx
-       call    data_next
-
-data_next:
-       popw    %bx
-       movw    %cs, %ax
-       shll    $4, %eax
-       leal    0x200 + data_start - data_next(%ebx,%eax), %eax
-       movzbl  setup_sects - data_next(%bx), %ecx
-       shll    $9, %ecx
-       addl    %ecx, %eax
-       movl    %eax, code32_start - data_next(%bx)
-
+       xorl    %ebp, %ebp
        jmp     linux_next

        . = data_start + 0x1F1
@@ -76,7 +61,7 @@ boot_flag:
 start:
 _start:

-       jmp linux_code
+       jmp linux_init

        .ascii  "HdrS"                  // Header signature
        .word   0x0203                  // Header version number
@@ -134,9 +119,10 @@ reg_edx:
 data_leng:
        .long   0

-linux_code:
+linux_init:

        movw    %cs:(reg_edx - start), %dx
+       movl    %cs:(code32_start - start), %ebp

 linux_next:

@@ -164,9 +150,6 @@ real_code:
        movw    %si, %ss
        movw    $(CODE_ADDR), %sp

-       pushl   %esi
-       pushl   %edi
-
        // Move itself to 0:CODE_ADDR

        cld
@@ -183,17 +166,26 @@ real_code:

 real_code_2:

+       xchgl   %ebp, %esi
+       orl     %esi, %esi
+       jnz     1f
+       movw    %ds, %si
+       shll    $4, %esi
+       addl    %ebp, %esi
+1:
+
        pushw   %es
        popw    %ds

-       movl    (ramdisk_image - start), %esi
-       or      %esi, %esi
+       movl    (data_leng - start), %ecx
+       or      %ecx, %ecx
        jnz     1f
-       movl    (code32_start - start), %esi
+       movl    (ramdisk_image - start), %esi
+       movl    (ramdisk_size - start), %ecx
+       addl    $0x200, %esi
+       subl    $0x200, %ecx
 1:

-       movl    $0x200, %ecx
-       addl    %ecx, %esi
        movl    $DATA_ADDR, %edi

        call    move_memory
@@ -204,13 +196,17 @@ real_code_2:
        movsbl  (reg_edx + 2 - start), %eax
        movl    %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)

-       movl    %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
-       addl    $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
+       movl    (data_leng - start), %eax
+       or      %eax, %eax
+       jz      1f
+       movl    (ramdisk_size - start), %eax
+       or      %eax, %eax
+       jz      1f

-       call    move_memory
-
-       popl    %edi
-       popl    %esi
+       movl    %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE)
+       movl    (ramdisk_image - start), %eax
+       movl    %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_ADDR)
+1:

        ljmp    $(DATA_ADDR >> 4), $0

@@ -261,8 +257,8 @@ move_memory:

 2:

-       leal    (%esi, %eax), %esi
-       leal    (%edi, %eax), %edi
+       addl    %eax, %esi
+       addl    %eax, %edi
        subl    %eax, %ecx
        jnz     1b

diff --git a/include/grub/i386/pc/boot.h b/include/grub/i386/pc/boot.h
index fcc961b..4cc9a04 100644
--- a/include/grub/i386/pc/boot.h
+++ b/include/grub/i386/pc/boot.h
@@ -75,4 +75,7 @@
 /* The size of a block list used in the kernel startup code.  */
 #define GRUB_BOOT_MACHINE_LIST_SIZE    12

+/* The offset of variable data_leng in lnxboot.S.  */
+#define GRUB_BOOT_MACHINE_LNX_LENG_OFFSET      0x264
+
 #endif /* ! BOOT_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
index ca16df7..f5d8438 100644
--- a/include/grub/i386/pc/kernel.h
+++ b/include/grub/i386/pc/kernel.h
@@ -37,8 +37,11 @@
 /* The offset of GRUB_MEMDISK_IMAGE_SIZE.  */
 #define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE 0x1c

+/* The offset of GRUB_MEMDISK_IMAGE_ADDR.  */
+#define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_ADDR 0x20
+
 /* The offset of GRUB_PREFIX.  */
-#define GRUB_KERNEL_MACHINE_PREFIX             0x20
+#define GRUB_KERNEL_MACHINE_PREFIX             0x24

 /* End of the data section. */
 #define GRUB_KERNEL_MACHINE_DATA_END           0x50
@@ -66,6 +69,9 @@ extern grub_int32_t grub_install_bsd_part;
 /* The size of memory disk image, if present.  */
 extern grub_int32_t grub_memdisk_image_size;

+/* The address of memory disk image, if present.  */
+extern grub_int32_t grub_memdisk_image_addr;
+
 /* The prefix which points to the directory where GRUB modules and its
    configuration file are located.  */
 extern char grub_prefix[];
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
index 0cf81d7..af6deda 100644
--- a/kern/i386/pc/init.c
+++ b/kern/i386/pc/init.c
@@ -253,9 +253,10 @@ grub_arch_modules_addr (void)
 grub_addr_t
 grub_arch_memdisk_addr (void)
 {
-  return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
+  return (grub_memdisk_image_addr) ? grub_memdisk_image_addr :
+    (GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
     + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE)
-    + grub_total_module_size;
+    + grub_total_module_size);
 }

 /* Return the size of the memdisk image.  */
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
index e4101a6..5dd2e67 100644
--- a/kern/i386/pc/startup.S
+++ b/kern/i386/pc/startup.S
@@ -97,6 +97,8 @@ VARIABLE(grub_install_bsd_part)
        .long   0xFFFFFFFF
 VARIABLE(grub_memdisk_image_size)
        .long   0
+VARIABLE(grub_memdisk_image_addr)
+       .long   0
 VARIABLE(grub_prefix)
        /* to be filled by grub-mkimage */

diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c
index 48d6dfc..eee6b34 100644
--- a/util/i386/pc/grub-mkimage.c
+++ b/util/i386/pc/grub-mkimage.c
@@ -77,7 +77,7 @@ compress_kernel (char *kernel_img, size_t kernel_size,
 }

 static void
-generate_image (const char *dir, char *prefix, FILE *out, char
*mods[], char *memdisk_path)
+generate_image (const char *dir, char *prefix, FILE *out, char
*mods[], char *memdisk_path, int is_linux)
 {
   grub_addr_t module_addr = 0;
   char *kernel_img, *boot_img, *core_img;
@@ -151,17 +151,25 @@ generate_image (const char *dir, char *prefix,
FILE *out, char *mods[], char *me
   if (num > 0xffff)
     grub_util_error ("the core image is too big");

-  boot_path = grub_util_get_path (dir, "diskboot.img");
+  boot_path = grub_util_get_path (dir, (is_linux) ? "lnxboot.img" :
"diskboot.img");
   boot_size = grub_util_get_image_size (boot_path);
-  if (boot_size != GRUB_DISK_SECTOR_SIZE)
+  if ((! is_linux) && (boot_size != GRUB_DISK_SECTOR_SIZE))
     grub_util_error ("diskboot.img is not one sector size");

   boot_img = grub_util_read_image (boot_path);

-  /* i386 is a little endian architecture.  */
-  *((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
+  if (is_linux)
+    {
+      *((grub_uint32_t *) (boot_img + GRUB_BOOT_MACHINE_LNX_LENG_OFFSET))
+      = grub_cpu_to_le32 (core_size);
+    }
+  else
+    {
+      /* i386 is a little endian architecture.  */
+      *((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE
                       - GRUB_BOOT_MACHINE_LIST_SIZE + 8))
-    = grub_cpu_to_le16 (num);
+      = grub_cpu_to_le16 (num);
+    }

   grub_util_write_image (boot_img, boot_size, out);
   free (boot_img);
@@ -208,6 +216,7 @@ static struct option options[] =
     {"prefix", required_argument, 0, 'p'},
     {"memdisk", required_argument, 0, 'm'},
     {"output", required_argument, 0, 'o'},
+    {"linux", no_argument, 0, 'x'},
     {"help", no_argument, 0, 'h'},
     {"version", no_argument, 0, 'V'},
     {"verbose", no_argument, 0, 'v'},
@@ -229,6 +238,7 @@ Make a bootable image of GRUB.\n\
   -p, --prefix=DIR        set grub_prefix directory [default=%s]\n\
   -m, --memdisk=FILE      embed FILE as a memdisk image\n\
   -o, --output=FILE       output a generated image to FILE [default=stdout]\n\
+  -x, --linux             add linux kernel header to output file\n\
   -h, --help              display this message and exit\n\
   -V, --version           print version information and exit\n\
   -v, --verbose           print verbose messages\n\
@@ -247,12 +257,13 @@ main (int argc, char *argv[])
   char *prefix = NULL;
   char *memdisk = NULL;
   FILE *fp = stdout;
+  int is_linux = 0;

   progname = "grub-mkimage";

   while (1)
     {
-      int c = getopt_long (argc, argv, "d:p:m:o:hVv", options, 0);
+      int c = getopt_long (argc, argv, "d:p:m:o:xhVv", options, 0);

       if (c == -1)
        break;
@@ -280,6 +291,10 @@ main (int argc, char *argv[])
            memdisk = xstrdup (optarg);
            break;

+         case 'x':
+           is_linux = 1;
+           break;
+
          case 'h':
            usage (0);
            break;
@@ -312,7 +327,7 @@ main (int argc, char *argv[])
        grub_util_error ("cannot open %s", output);
     }

-  generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY,
fp, argv + optind, memdisk);
+  generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY,
fp, argv + optind, memdisk, is_linux);

   fclose (fp);




-- 
Bean




reply via email to

[Prev in Thread] Current Thread [Next in Thread]