grub-devel
[Top][All Lists]
Advanced

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

[PATCH] generic ELF version of grub-mkimage


From: Patrick Georgi
Subject: [PATCH] generic ELF version of grub-mkimage
Date: Thu, 30 Aug 2007 12:03:47 +0200
User-agent: Thunderbird 2.0b2 (X11/20070411)

Hi,

the attached patch makes powerpc-ieee1275's grub-mkimage work with little endian ELF images, too. I did this, as I need basically the same functionality for i386-linuxbios, just with little endian ELFs. I first copied and changed the file for my needs, but it might be more generally useful (other architectures), and having to maintain two very similar files seems like a waste of time to me - hence the merged version. I also moved the file to util/elf, to denote that it's a generic ELF mangler now and adapted the powerpc makefile.

Description of changes:

1.
Detect endianess of the kernel (and check it's actually an ELF file)

2.
Configure a set of function pointers appropriately. This also required me to wrap the grub_cpu_to_be* (and reverse) functions as those are macros.

3.
Replace all grub_cpu_to_be* and grub_be_to_cpu* calls with calls to the function pointers.

4.
Undefine the old macros in this file as a debugging aid (there should be any need for them)

Comments are very appreciated.

Regards,
Patrick Georgi
#
#
# rename "util/powerpc/ieee1275/grub-mkimage.c"
#     to "util/elf/grub-mkimage.c"
# 
# add_dir "util/elf"
# 
# patch "conf/powerpc-ieee1275.rmk"
#  from [dd6aa1b34a30806ec5739e36ac0c8dd9c3f90cd4]
#    to [e41cc58b76b3d62bef76cee905e953629024f753]
# 
# patch "util/elf/grub-mkimage.c"
#  from [0d5043da1774f2f00e4eb10823f82623735d8976]
#    to [f36bb74ba54243e417c618d4294d23f8761afd57]
#
============================================================
--- conf/powerpc-ieee1275.rmk   dd6aa1b34a30806ec5739e36ac0c8dd9c3f90cd4
+++ conf/powerpc-ieee1275.rmk   e41cc58b76b3d62bef76cee905e953629024f753
@@ -32,7 +32,7 @@ endif
 endif
  
 # For grub-mkimage.
-grub_mkimage_SOURCES = util/powerpc/ieee1275/grub-mkimage.c util/misc.c \
+grub_mkimage_SOURCES = util/elf/grub-mkimage.c util/misc.c \
         util/resolve.c 
 
 # For grub-mkdevicemap.
============================================================
--- util/powerpc/ieee1275/grub-mkimage.c        
0d5043da1774f2f00e4eb10823f82623735d8976
+++ util/elf/grub-mkimage.c     f36bb74ba54243e417c618d4294d23f8761afd57
@@ -62,6 +62,35 @@ struct grub_ieee1275_note
   struct grub_ieee1275_note_desc descriptor;
 };
 
+#define wrapmacro(name, len) \
+  static grub_uint ## len ## _t \
+  name ## len (grub_uint ## len ## _t x) \
+  { return grub_ ## name ## len (x); }
+
+wrapmacro(le_to_cpu, 32)
+wrapmacro(cpu_to_le, 32)
+wrapmacro(le_to_cpu, 16)
+wrapmacro(cpu_to_le, 16)
+wrapmacro(be_to_cpu, 32)
+wrapmacro(cpu_to_be, 32)
+wrapmacro(be_to_cpu, 16)
+wrapmacro(cpu_to_be, 16)
+
+/* those macros should not be used after this. use cpu_to_file32 etc instead */
+#undef grub_cpu_to_le16
+#undef grub_cpu_to_le32
+#undef grub_cpu_to_be16
+#undef grub_cpu_to_be32
+#undef grub_le_to_cpu16
+#undef grub_le_to_cpu32
+#undef grub_be_to_cpu16
+#undef grub_be_to_cpu32
+
+grub_uint32_t (*file_to_cpu32)(grub_uint32_t) = 0;
+grub_uint16_t (*file_to_cpu16)(grub_uint16_t) = 0;
+grub_uint32_t (*cpu_to_file32)(grub_uint32_t) = 0;
+grub_uint16_t (*cpu_to_file16)(grub_uint16_t) = 0;
+
 void
 load_note (Elf32_Phdr *phdr, FILE *out)
 {
@@ -70,28 +99,28 @@ load_note (Elf32_Phdr *phdr, FILE *out)
 
   grub_util_info ("adding CHRP NOTE segment");
 
-  note.header.namesz = grub_cpu_to_be32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
-  note.header.descsz = grub_cpu_to_be32 (note_size);
-  note.header.type = grub_cpu_to_be32 (GRUB_IEEE1275_NOTE_TYPE);
+  note.header.namesz = cpu_to_file32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
+  note.header.descsz = cpu_to_file32 (note_size);
+  note.header.type = cpu_to_file32 (GRUB_IEEE1275_NOTE_TYPE);
   strcpy (note.header.name, GRUB_IEEE1275_NOTE_NAME);
-  note.descriptor.real_mode = grub_cpu_to_be32 (0xffffffff);
-  note.descriptor.real_base = grub_cpu_to_be32 (0x00c00000);
-  note.descriptor.real_size = grub_cpu_to_be32 (0xffffffff);
-  note.descriptor.virt_base = grub_cpu_to_be32 (0xffffffff);
-  note.descriptor.virt_size = grub_cpu_to_be32 (0xffffffff);
-  note.descriptor.load_base = grub_cpu_to_be32 (0x00004000);
+  note.descriptor.real_mode = cpu_to_file32 (0xffffffff);
+  note.descriptor.real_base = cpu_to_file32 (0x00c00000);
+  note.descriptor.real_size = cpu_to_file32 (0xffffffff);
+  note.descriptor.virt_base = cpu_to_file32 (0xffffffff);
+  note.descriptor.virt_size = cpu_to_file32 (0xffffffff);
+  note.descriptor.load_base = cpu_to_file32 (0x00004000);
 
   /* Write the note data to the new segment.  */
   grub_util_write_image_at (&note, note_size,
-                           grub_be_to_cpu32 (phdr->p_offset), out);
+                           file_to_cpu32 (phdr->p_offset), out);
 
   /* Fill in the rest of the segment header.  */
-  phdr->p_type = grub_cpu_to_be32 (PT_NOTE);
-  phdr->p_flags = grub_cpu_to_be32 (PF_R);
-  phdr->p_align = grub_cpu_to_be32 (sizeof (long));
+  phdr->p_type = cpu_to_file32 (PT_NOTE);
+  phdr->p_flags = cpu_to_file32 (PF_R);
+  phdr->p_align = cpu_to_file32 (sizeof (long));
   phdr->p_vaddr = 0;
   phdr->p_paddr = 0;
-  phdr->p_filesz = grub_cpu_to_be32 (note_size);
+  phdr->p_filesz = cpu_to_file32 (note_size);
   phdr->p_memsz = 0;
 }
 
@@ -120,9 +149,9 @@ load_modules (grub_addr_t modbase, Elf32
 
   module_img = xmalloc (total_module_size);
   modinfo = (struct grub_module_info *) module_img;
-  modinfo->magic = grub_cpu_to_be32 (GRUB_MODULE_MAGIC);
-  modinfo->offset = grub_cpu_to_be32 (sizeof (struct grub_module_info));
-  modinfo->size = grub_cpu_to_be32 (total_module_size);
+  modinfo->magic = cpu_to_file32 (GRUB_MODULE_MAGIC);
+  modinfo->offset = cpu_to_file32 (sizeof (struct grub_module_info));
+  modinfo->size = cpu_to_file32 (total_module_size);
 
   /* Load all the modules, with headers, into module_img.  */
   for (p = path_list; p; p = p->next)
@@ -135,8 +164,8 @@ load_modules (grub_addr_t modbase, Elf32
       mod_size = grub_util_get_image_size (p->name);
 
       header = (struct grub_module_header *) (module_img + offset);
-      header->offset = grub_cpu_to_be32 (sizeof (*header));
-      header->size = grub_cpu_to_be32 (mod_size + sizeof (*header));
+      header->offset = cpu_to_file32 (sizeof (*header));
+      header->size = cpu_to_file32 (mod_size + sizeof (*header));
 
       grub_util_load_image (p->name, module_img + offset + sizeof (*header));
 
@@ -145,16 +174,16 @@ load_modules (grub_addr_t modbase, Elf32
 
   /* Write the module data to the new segment.  */
   grub_util_write_image_at (module_img, total_module_size,
-                           grub_cpu_to_be32 (phdr->p_offset), out);
+                           cpu_to_file32 (phdr->p_offset), out);
 
   /* Fill in the rest of the segment header.  */
-  phdr->p_type = grub_cpu_to_be32 (PT_LOAD);
-  phdr->p_flags = grub_cpu_to_be32 (PF_R | PF_W | PF_X);
-  phdr->p_align = grub_cpu_to_be32 (sizeof (long));
-  phdr->p_vaddr = grub_cpu_to_be32 (modbase);
-  phdr->p_paddr = grub_cpu_to_be32 (modbase);
-  phdr->p_filesz = grub_cpu_to_be32 (total_module_size);
-  phdr->p_memsz = grub_cpu_to_be32 (total_module_size);
+  phdr->p_type = cpu_to_file32 (PT_LOAD);
+  phdr->p_flags = cpu_to_file32 (PF_R | PF_W | PF_X);
+  phdr->p_align = cpu_to_file32 (0x1000);
+  phdr->p_vaddr = cpu_to_file32 (modbase);
+  phdr->p_paddr = cpu_to_file32 (modbase);
+  phdr->p_filesz = cpu_to_file32 (total_module_size);
+  phdr->p_memsz = cpu_to_file32 (total_module_size);
 }
 
 void
@@ -176,11 +205,31 @@ add_segments (char *dir, FILE *out, int 
     grub_util_error ("cannot open %s", kernel_path);
 
   grub_util_read_at (&ehdr, sizeof (ehdr), 0, in);
-  
-  phdrs = xmalloc (grub_be_to_cpu16 (ehdr.e_phentsize)
-                  * (grub_be_to_cpu16 (ehdr.e_phnum) + 2));
+  if ((ehdr.e_ident[EI_MAG0]!=ELFMAG0) ||
+      (ehdr.e_ident[EI_MAG1]!=ELFMAG1) ||
+      (ehdr.e_ident[EI_MAG2]!=ELFMAG2) ||
+      (ehdr.e_ident[EI_MAG3]!=ELFMAG3)) {
+    grub_util_error("%s is not an ELF image", kernel_path);
+  }
+
+  if (ehdr.e_ident[EI_DATA]==ELFDATA2LSB) {
+    file_to_cpu16 = le_to_cpu16;
+    file_to_cpu32 = le_to_cpu32;
+    cpu_to_file16 = cpu_to_le16;
+    cpu_to_file32 = cpu_to_le32;
+  } else if (ehdr.e_ident[EI_DATA]==ELFDATA2MSB) {
+    file_to_cpu16 = be_to_cpu16;
+    file_to_cpu32 = be_to_cpu32;
+    cpu_to_file16 = cpu_to_be16;
+    cpu_to_file32 = cpu_to_be32;
+  } else {
+    grub_util_error("Unknown file encoding");
+  }
+
+  phdrs = xmalloc (file_to_cpu16 (ehdr.e_phentsize)
+                  * (file_to_cpu16 (ehdr.e_phnum) + 2));
   /* Copy all existing segments.  */
-  for (i = 0; i < grub_be_to_cpu16 (ehdr.e_phnum); i++)
+  for (i = 0; i < file_to_cpu16 (ehdr.e_phnum); i++)
     {
       char *segment_img;
       grub_size_t segment_end;
@@ -189,26 +238,26 @@ add_segments (char *dir, FILE *out, int 
 
       /* Read segment header.  */
       grub_util_read_at (phdr, sizeof (Elf32_Phdr),
-                        (grub_be_to_cpu32 (ehdr.e_phoff)
-                         + (i * grub_be_to_cpu16 (ehdr.e_phentsize))),
+                        (file_to_cpu32 (ehdr.e_phoff)
+                         + (i * file_to_cpu16 (ehdr.e_phentsize))),
                         in);
       grub_util_info ("copying segment %d, type %d", i,
-                     grub_be_to_cpu32 (phdr->p_type));
+                     file_to_cpu32 (phdr->p_type));
 
       /* Locate _end.  */
-      segment_end = grub_be_to_cpu32 (phdr->p_paddr)
-                   + grub_be_to_cpu32 (phdr->p_memsz);
+      segment_end = file_to_cpu32 (phdr->p_paddr)
+                   + file_to_cpu32 (phdr->p_memsz);
       grub_util_info ("segment %u end 0x%lx", i, segment_end);
       if (segment_end > grub_end)
        grub_end = segment_end;
 
       /* Read segment data and write it to new file.  */
-      segment_img = xmalloc (grub_be_to_cpu32 (phdr->p_filesz));
+      segment_img = xmalloc (file_to_cpu32 (phdr->p_filesz));
   
-      grub_util_read_at (segment_img, grub_be_to_cpu32 (phdr->p_filesz),
-                        grub_be_to_cpu32 (phdr->p_offset), in);
-      grub_util_write_image_at (segment_img, grub_be_to_cpu32 (phdr->p_filesz),
-                               grub_be_to_cpu32 (phdr->p_offset), out);
+      grub_util_read_at (segment_img, file_to_cpu32 (phdr->p_filesz),
+                        file_to_cpu32 (phdr->p_offset), in);
+      grub_util_write_image_at (segment_img, file_to_cpu32 (phdr->p_filesz),
+                               file_to_cpu32 (phdr->p_offset), out);
 
       free (segment_img);
     }
@@ -218,14 +267,14 @@ add_segments (char *dir, FILE *out, int 
       grub_addr_t modbase;
 
       /* Place modules just after grub segment.  */
-      modbase = ALIGN_UP(grub_end, GRUB_IEEE1275_MOD_ALIGN);
+      modbase = ALIGN_UP(grub_end, GRUB_MOD_ALIGN);
 
       /* Construct new segment header for modules.  */
-      phdr = phdrs + grub_be_to_cpu16 (ehdr.e_phnum);
-      ehdr.e_phnum = grub_cpu_to_be16 (grub_be_to_cpu16 (ehdr.e_phnum) + 1);
+      phdr = phdrs + file_to_cpu16 (ehdr.e_phnum);
+      ehdr.e_phnum = cpu_to_file16 (file_to_cpu16 (ehdr.e_phnum) + 1);
 
       /* Fill in p_offset so the callees know where to write.  */
-      phdr->p_offset = grub_cpu_to_be32 (ALIGN_UP (grub_util_get_fp_size (out),
+      phdr->p_offset = cpu_to_file32 (ALIGN_UP (grub_util_get_fp_size (out),
                                                   sizeof (long)));
 
       load_modules (modbase, phdr, dir, mods, out);
@@ -234,11 +283,11 @@ add_segments (char *dir, FILE *out, int 
   if (chrp)
     {
       /* Construct new segment header for the CHRP note.  */
-      phdr = phdrs + grub_be_to_cpu16 (ehdr.e_phnum);
-      ehdr.e_phnum = grub_cpu_to_be16 (grub_be_to_cpu16 (ehdr.e_phnum) + 1);
+      phdr = phdrs + file_to_cpu16 (ehdr.e_phnum);
+      ehdr.e_phnum = cpu_to_file16 (file_to_cpu16 (ehdr.e_phnum) + 1);
 
       /* Fill in p_offset so the callees know where to write.  */
-      phdr->p_offset = grub_cpu_to_be32 (ALIGN_UP (grub_util_get_fp_size (out),
+      phdr->p_offset = cpu_to_file32 (ALIGN_UP (grub_util_get_fp_size (out),
                                                   sizeof (long)));
 
       load_note (phdr, out);
@@ -251,12 +300,12 @@ add_segments (char *dir, FILE *out, int 
 
   /* Append entire segment table to the file.  */
   phdroff = ALIGN_UP (grub_util_get_fp_size (out), sizeof (long));
-  grub_util_write_image_at (phdrs, grub_be_to_cpu16 (ehdr.e_phentsize)
-                           * grub_be_to_cpu16 (ehdr.e_phnum), phdroff,
+  grub_util_write_image_at (phdrs, file_to_cpu16 (ehdr.e_phentsize)
+                           * file_to_cpu16 (ehdr.e_phnum), phdroff,
                            out);
 
   /* Write ELF header.  */
-  ehdr.e_phoff = grub_cpu_to_be32 (phdroff);
+  ehdr.e_phoff = cpu_to_file32 (phdroff);
   grub_util_write_image_at (&ehdr, sizeof (ehdr), 0, out);
 
   free (phdrs);

reply via email to

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