All of lore.kernel.org
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: Linus Torvalds <torvalds@transmeta.com>, Dave Jones <davej@suse.de>
Cc: <linux-kernel@vger.kernel.org>
Subject: [PATCH 2.5.12] x86 Boot enhancements, bzElf support 11/11
Date: 02 May 2002 09:15:57 -0600	[thread overview]
Message-ID: <m1sn5awpg2.fsf_-_@frodo.biederman.org> (raw)
In-Reply-To: <m11ycuzk4q.fsf@frodo.biederman.org> <m1wuumy5eo.fsf@frodo.biederman.org> <m1sn5ay5ac.fsf_-_@frodo.biederman.org> <m1offyy55x.fsf_-_@frodo.biederman.org> <m1it66y4xz.fsf_-_@frodo.biederman.org> <m1elguy4pj.fsf_-_@frodo.biederman.org> <m1adriy4im.fsf_-_@frodo.biederman.org> <m16626y4et.fsf_-_@frodo.biederman.org> <m11ycuy48d.fsf_-_@frodo.biederman.org> <m1wuumwpkk.fsf_-_@frodo.biederman.org>

Please apply,

This patch allows a bzELF image to be built instead of a bzImage.
A bzELF is just a bzImage represented in the ELF file format.  The transform
from bzELF to bzImage is 1-1.

Eric

diff -uNr linux-2.5.12.boot.linuxbios/arch/i386/Makefile linux-2.5.12.boot.elf/arch/i386/Makefile
--- linux-2.5.12.boot.linuxbios/arch/i386/Makefile	Wed May  1 09:38:47 2002
+++ linux-2.5.12.boot.elf/arch/i386/Makefile	Wed May  1 09:41:44 2002
@@ -119,6 +119,9 @@
 bzImage: vmlinux
 	@$(MAKEBOOT) bzImage
 
+bzElf: vmlinux
+	@$(MAKEBOOT) bzElf
+
 compressed: zImage
 
 zlilo: vmlinux
diff -uNr linux-2.5.12.boot.linuxbios/arch/i386/boot/Makefile linux-2.5.12.boot.elf/arch/i386/boot/Makefile
--- linux-2.5.12.boot.linuxbios/arch/i386/boot/Makefile	Wed May  1 09:40:42 2002
+++ linux-2.5.12.boot.elf/arch/i386/boot/Makefile	Wed May  1 09:41:44 2002
@@ -18,6 +18,9 @@
 bzImage: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux brealmode compressed/bvmlinux 
 	tools/build -b $(TOPDIR)/vmlinux brealmode compressed/bvmlinux bzImage
 
+bzElf: $(CONFIGURE) tools/build $(TOPDIR)/vmlinux brealmode compressed/bvmlinux 
+	tools/build -e -b $(TOPDIR)/vmlinux brealmode compressed/bvmlinux bzElf
+
 compressed/vmlinux: $(TOPDIR)/vmlinux
 	@$(MAKE) -C compressed vmlinux
 
@@ -75,5 +78,5 @@
 clean:
 	rm -f tools/build
 	rm -f realmode zImage
-	rm -f brealmode bzImage
+	rm -f brealmode bzImage bzElf
 	@$(MAKE) -C compressed clean
diff -uNr linux-2.5.12.boot.linuxbios/arch/i386/boot/tools/build.c linux-2.5.12.boot.elf/arch/i386/boot/tools/build.c
--- linux-2.5.12.boot.linuxbios/arch/i386/boot/tools/build.c	Wed May  1 09:40:42 2002
+++ linux-2.5.12.boot.elf/arch/i386/boot/tools/build.c	Wed May  1 09:41:44 2002
@@ -80,11 +80,12 @@
 #define ISEGS  3
 
 /* Segments of the output file */
-#define OREAL 0
-#define OKERN 1
-#define OBSS1 2
-#define OBSS2 3
-#define OSEGS 4
+#define OEHDR 0
+#define OREAL 1
+#define OKERN 2
+#define OBSS1 3
+#define OBSS2 4
+#define OSEGS 5
 
 struct file_seg
 {
@@ -96,6 +97,37 @@
 	unsigned char *data;
 };
 
+/* Kernel version */
+#define LINUX_KERNEL_VERSION \
+	UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION
+
+typedef uint16_t Elf_Half;
+typedef uint32_t Elf_Word;
+typedef uint64_t Elf_Xword;
+
+typedef struct 
+{
+	Elf_Word n_namesz;		/* Length of the note's name.  */
+	Elf_Word n_descsz;		/* Length of the note's descriptor.  */
+	Elf_Word n_type;		/* Type of the note.  */
+} Elf_Nhdr;
+
+typedef struct 
+{
+	Elf_Word n_paddr;
+	Elf_Word n_size;
+} Elf_Pdesc;
+
+/*  Elf image notes for booting... The name for all of these is ELFBoot */
+
+#define EIN_NOTE_NAME	"ELFBoot"
+#define EIN_PROGRAM_NAME	0x00000001
+/* The program in this ELF file */
+#define EIN_PROGRAM_VERSION	0x00000002
+/* The version of the program in this ELF file */
+#define EIN_PROGRAM_CHECKSUM	0x00000003
+/* ip style checksum of the memory image. */
+
 struct boot_params {
 	uint8_t  reserved1[0x1f1];		/* 0x000 */
 	uint8_t  setup_sects;			/* 0x1f1 */
@@ -335,6 +367,76 @@
 	return result;
 }
 
+static unsigned long compute_ip_checksum(void *addr, unsigned long length)
+{
+	uint16_t *ptr;
+	unsigned long sum;
+	unsigned long len;
+	unsigned long laddr;
+	/* compute an ip style checksum */
+	laddr = (unsigned long )addr;
+	sum = 0;
+	if (laddr & 1) {
+		uint16_t buffer;
+		unsigned char *ptr;
+		/* copy the first byte into a 2 byte buffer.
+		 * This way automatically handles the endian question
+		 * of which byte (low or high) the last byte goes in.
+		 */
+		buffer = 0;
+		ptr = addr;
+		memcpy(&buffer, ptr, 1);
+		sum += buffer;
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+		length -= 1;
+		addr = ptr +1;
+	}
+	len = length >> 1;
+	ptr = addr;
+	while (len--) {
+		sum += *(ptr++);
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+	}
+	addr = ptr;
+	if (length & 1) {
+		uint16_t buffer;
+		unsigned char *ptr;
+		/* copy the last byte into a 2 byte buffer.
+		 * This way automatically handles the endian question
+		 * of which byte (low or high) the last byte goes in.
+		 */
+		buffer = 0;
+		ptr = addr;
+		memcpy(&buffer, ptr, 1);
+		sum += buffer;
+		if (sum > 0xFFFF)
+			sum -= 0xFFFF;
+	}
+	return (~sum) & 0xFFFF;
+	
+}
+
+static unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new)
+{
+	unsigned long checksum;
+	sum = ~sum & 0xFFFF;
+	new = ~new & 0xFFFF;
+	if (offset & 1) {
+		/* byte swap the sum if it came from an odd offset 
+		 * since the computation is endian independant this
+		 * works.
+		 */
+		new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
+	}
+	checksum = sum + new;
+	if (checksum > 0xFFFF) {
+		checksum -= 0xFFFF;
+	}
+	return (~checksum) & 0xFFFF;
+}
+
 static void check_ehdr(Elf32_Ehdr *ehdr, char *name)
 {
 	/* Do some basic to ensure it is an ELF image */
@@ -489,6 +591,7 @@
 
 struct image_info {
 	int is_big_kernel;
+	int is_elf;
 	size_t entry32;
 	size_t setup_sectors;
 	size_t sys_size;
@@ -518,11 +621,114 @@
 	zhdr->output_overhang = cpu_to_le32(info->unzip_overhang);
 	zhdr->kernel_memsz    = cpu_to_le32(iseg[IKERN].mem_size);
 	zhdr->kernel_filesz   = cpu_to_le32(iseg[IKERN].data_size);
+	if (info->is_elf) {
+		/* For ELF images we don't expect the header to be relocated */
+		param->loadflags |= cpu_to_le32(LOADFLAG_STAY_PUT);
+		param->type_of_loader = LOADER_UNKNOWN;
+	}
+}
+
+struct elf_header {
+	Elf32_Ehdr ehdr;
+	Elf32_Phdr phdr[OSEGS - (OEHDR + 1)];
+	Elf_Nhdr   program_name_hdr;
+	uint8_t    program_name_name[8];
+	uint8_t    program_name_desc[8];
+	Elf_Nhdr   program_version_hdr;
+	uint8_t    program_version_name[8];
+	uint8_t    program_version_desc[(sizeof(LINUX_KERNEL_VERSION) + 3) & ~3];
+	Elf_Nhdr   program_checksum_hdr;
+	uint8_t    program_checksum_name[8];
+	uint16_t   program_checksum;
+	uint16_t   program_checksum_pad;
+} __attribute__((packed));
+
+static void build_elf_header(struct file_seg *seg, struct image_info *info)
+{
+	struct elf_header *hdr;
+	size_t checksum, bytes;
+	size_t offset, size;
+	int i;
+	hdr = checked_malloc(sizeof(*hdr));
+	memset(hdr, 0, sizeof(*hdr));
+	memcpy(hdr->ehdr.e_ident, ELFMAG, 4);
+	hdr->ehdr.e_ident[EI_CLASS]   = ELFCLASS32;
+	hdr->ehdr.e_ident[EI_DATA]    = ELFDATA2LSB;
+	hdr->ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+	hdr->ehdr.e_type      = cpu_to_le16(ET_EXEC);
+	hdr->ehdr.e_machine   = cpu_to_le16(EM_386);
+	hdr->ehdr.e_version   = cpu_to_le32(EV_CURRENT);
+	hdr->ehdr.e_entry     = cpu_to_le32(info->entry32);
+	hdr->ehdr.e_phoff     = cpu_to_le32(offsetof(struct elf_header, phdr));
+	hdr->ehdr.e_shoff     = cpu_to_le32(0);
+	hdr->ehdr.e_flags     = cpu_to_le16(0);
+	hdr->ehdr.e_ehsize    = cpu_to_le16(sizeof(hdr->ehdr));
+	hdr->ehdr.e_phentsize = cpu_to_le16(sizeof(hdr->phdr[0]));
+	hdr->ehdr.e_phnum     = cpu_to_le16(sizeof(hdr->phdr)/sizeof(hdr->phdr[0]));
+	hdr->ehdr.e_shentsize = cpu_to_le16(0);
+	hdr->ehdr.e_shnum     = cpu_to_le16(0);
+	hdr->ehdr.e_shstrndx  = cpu_to_le16(0);
+
+	offset = offsetof(struct elf_header, program_name_hdr);
+	size = sizeof(*hdr) - offset;
+	hdr->phdr[0].p_type   = cpu_to_le32(PT_NOTE);
+	hdr->phdr[0].p_offset = cpu_to_le32(offset);
+	hdr->phdr[0].p_vaddr  = cpu_to_le32(0);
+	hdr->phdr[0].p_paddr  = cpu_to_le32(0);
+	hdr->phdr[0].p_filesz = cpu_to_le32(size);
+	hdr->phdr[0].p_memsz  = cpu_to_le32(size);
+	hdr->phdr[0].p_flags  = cpu_to_le32(0);
+	hdr->phdr[0].p_align  = cpu_to_le32(0);
+	
+	for(i = OEHDR +1; i < OSEGS; i++) {
+		hdr->phdr[i].p_type = cpu_to_le32(PT_NULL);
+		if (seg[i].mem_size == 0) 
+			continue;
+		hdr->phdr[i].p_type   = cpu_to_le32(PT_LOAD);
+		hdr->phdr[i].p_offset = cpu_to_le32(seg[i].file_offset);
+		hdr->phdr[i].p_vaddr  = cpu_to_le32(seg[i].mem_addr);
+		hdr->phdr[i].p_paddr  = cpu_to_le32(seg[i].mem_addr);
+		hdr->phdr[i].p_filesz = cpu_to_le32(seg[i].data_size);
+		hdr->phdr[i].p_memsz  = cpu_to_le32(seg[i].mem_size);
+		hdr->phdr[i].p_flags  = cpu_to_le32(0);
+		hdr->phdr[i].p_align  = cpu_to_le32(0);
+	}
+	
+	hdr->program_name_hdr.n_namesz = cpu_to_le32(strlen(EIN_NOTE_NAME) +1);
+	hdr->program_name_hdr.n_descsz = cpu_to_le32(strlen("Linux") +1);
+	hdr->program_name_hdr.n_type   = cpu_to_le32(EIN_PROGRAM_NAME);
+	strcpy(hdr->program_name_name, EIN_NOTE_NAME);
+	strcpy(hdr->program_name_desc, "Linux");
+	
+	hdr->program_version_hdr.n_namesz = cpu_to_le32(strlen(EIN_NOTE_NAME) +1);
+	hdr->program_version_hdr.n_descsz = cpu_to_le32(strlen(LINUX_KERNEL_VERSION)+1);
+	hdr->program_version_hdr.n_type   = cpu_to_le32(EIN_PROGRAM_VERSION);
+	strcpy(hdr->program_version_name, EIN_NOTE_NAME);
+	strcpy(hdr->program_version_desc, LINUX_KERNEL_VERSION);
+
+	hdr->program_checksum_hdr.n_namesz = cpu_to_le32(strlen(EIN_NOTE_NAME) +1);
+	hdr->program_checksum_hdr.n_descsz = cpu_to_le32(2);
+	hdr->program_checksum_hdr.n_type   = cpu_to_le32(EIN_PROGRAM_CHECKSUM);
+	strcpy(hdr->program_checksum_name, EIN_NOTE_NAME);
+	hdr->program_checksum = cpu_to_le16(0); /* This is written later */
+
+	/* Compute the image checksum, this covers everything except the
+	 * ELF notes.
+	 */
+	bytes = sizeof(hdr->ehdr) + sizeof(hdr->phdr);
+	checksum = compute_ip_checksum(hdr, bytes);
+	for(i = 1; i < 4; i++) {
+		checksum = add_ip_checksums(bytes, checksum, 
+			compute_ip_checksum(seg[i].data, seg[i].data_size));
+		bytes += seg[i].mem_size;
+	}
+	hdr->program_checksum = cpu_to_le16(checksum);
+	seg[OEHDR].data = (unsigned char *)hdr;
 }
 
 static void usage(void)
 {
-	die("Usage: build [-b] vmlinux realmode compressed/vmlinux image");
+	die("Usage: build [-e] [-b] vmlinux realmode compressed/vmlinux image");
 }
 
 int main(int argc, char ** argv)
@@ -544,6 +750,12 @@
 	memset(oseg, 0, sizeof(oseg));
 	memset(&info, 0, sizeof(info));
 	info.is_big_kernel = 0;
+	info.is_elf = 0;
+	if (argc > 2 && (strcmp(argv[1], "-e") == 0)) {
+		info.is_elf = 1;
+		argc--;
+		argv++;
+	}
 	if (argc > 2 && (strcmp(argv[1], "-b") == 0)) {
 		info.is_big_kernel = 1;
 		argc--;
@@ -626,7 +838,7 @@
 	} else {
 		/* bzImage */
 		size_t unzip_bufsz;
-		
+
 		/* Compute the bzImage decompressor memory size */
 		unzip_bufsz = iseg[IKERN].data_size + info.unzip_overhang;
 		if (unzip_bufsz > oseg[OKERN].mem_size) {
@@ -653,7 +865,15 @@
 	info.setup_sectors = (oseg[OREAL].data_size - 512 + 511)/512;
 	if (info.setup_sectors < SETUP_SECTS)
 		info.setup_sectors = SETUP_SECTS;
+	if (info.is_elf) {
+		oseg[OEHDR].data_size = sizeof(struct elf_header);
+	}
 
+	/* Note: for ELF images I don't have to make OREAL
+	 * info.setup_sectors long, but it makes the conversion back
+	 * to a bzImage just a trivial header removal.
+	 */
+	oseg[OREAL].file_offset = oseg[OEHDR].file_offset + oseg[OEHDR].data_size;
 	oseg[OKERN].file_offset = oseg[OREAL].file_offset + (info.setup_sectors +1)*512;
 
 	/* Check and print the values to write back. */
@@ -692,6 +912,10 @@
 
 	/* Write the values back */
 	update_image(iseg, oseg, &info);
+	if (info.is_elf) {
+		build_elf_header(oseg, &info);
+		printf("elf_header_size=%d\n", oseg[OEHDR].data_size);
+	}
 
 	/* Write destination file */
 	image_fd = checked_open(image, O_RDWR | O_CREAT | O_TRUNC, 0666);

  reply	other threads:[~2002-05-02 15:25 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-05-02 14:42 [PATCH 2.5.12] x86 Boot enhancements, boot params 1/11 Eric W. Biederman
2002-04-27  2:56 ` Pavel Machek
2002-05-06 10:13   ` Eric W. Biederman
2002-05-06 15:19     ` Pavel Machek
2002-05-06 17:55       ` Eric W. Biederman
2002-05-06 20:20         ` Pavel Machek
2002-05-02 14:45 ` [PATCH 2.5.12] x86 Boot enhancements, linker fixes 2/11 Eric W. Biederman
2002-05-02 14:48   ` [PATCH 2.5.12] x86 Boot enhancements, bzImage/zImage code differentiation 3/11 Eric W. Biederman
2002-05-02 14:51     ` [PATCH 2.5.12] x86 Boot enhancements, constants 4/11 Eric W. Biederman
2002-05-02 14:55       ` [PATCH 2.5.12] x86 Boot enhancements, heap 5/11 Eric W. Biederman
2002-05-02 15:00         ` [PATCH 2.5.12] x86 Boot enhancements, 32bit entries 6/11 Eric W. Biederman
2002-04-27  4:53           ` Pavel Machek
2002-05-02 15:05           ` [PATCH 2.5.12] x86 Boot enhancements, footprint reduction 7/11 Eric W. Biederman
2002-05-02 15:07             ` [PATCH 2.5.12] x86 Boot enhancements, build beancounting 8/11 Eric W. Biederman
2002-05-02 15:11               ` [PATCH 2.5.12] x86 Boot enhancements, boot protocol 2.04 9/11 Eric W. Biederman
2002-05-02 15:13                 ` [PATCH 2.5.12] x86 Boot enhancements, LinuxBIOS support 10/11 Eric W. Biederman
2002-05-02 15:15                   ` Eric W. Biederman [this message]
2002-05-02 20:45                     ` [PATCH 2.5.12] x86 Boot enhancements, bzElf support 11/11 H. Peter Anvin
2002-05-02 20:39                 ` [PATCH 2.5.12] x86 Boot enhancements, boot protocol 2.04 9/11 H. Peter Anvin
2002-05-02 20:45                 ` H. Peter Anvin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m1sn5awpg2.fsf_-_@frodo.biederman.org \
    --to=ebiederm@xmission.com \
    --cc=davej@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.