From: Rusty Russell <rusty@rustcorp.com.au>
To: "H. Peter Anvin" <hpa@zytor.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>,
Jeff Garzik <jeff@garzik.org>,
patches@x86-64.org, linux-kernel@vger.kernel.org,
virtualization <virtualization@lists.linux-foundation.org>,
Vivek Goyal <vgoyal@in.ibm.com>,
Gerd Hoffmann <kraxel@redhat.com>,
"Eric W. Biederman" <ebiederm@xmission.com>
Subject: Re: [patches] [PATCH] [21/22] x86_64: Extend bzImage protocol for relocatable bzImage
Date: Thu, 03 May 2007 12:01:24 +1000 [thread overview]
Message-ID: <1178157684.23670.11.camel@localhost.localdomain> (raw)
In-Reply-To: <4638FE1B.9050901@zytor.com>
On Wed, 2007-05-02 at 14:09 -0700, H. Peter Anvin wrote:
> Jeremy Fitzhardinge wrote:
> >
> > Hm, that's unfortunate. How about an ELF file wrapped in some other
> > container, so that we can easily extract a properly formed ELF file?
> >
>
> Effectively the same thing as changing the magic number. Note that the
> format for bzImage is pretty rigid, and it would be *highly* undesirable
> to muck that up.
To add some code to the debate, here's how lguest loads a bzImage (from
my draft documentation). Almost anything would be an improvement:
/* A bzImage, unlike an ELF file, is not meant to be loaded. You're
* supposed to jump into it and it will unpack itself. We can't do that
* because the Guest can't run the unpacking code, and adding features to
* lguest kills puppies, so we don't want to.
*
* The bzImage is formed by putting the decompressing code in front of the
* compressed kernel code. So we can simple scan through it looking for the
* first "gzip" header, and start decompressing from there. */
static unsigned long load_bzimage(int fd, unsigned long *page_offset)
{
unsigned char c;
int state = 0;
/* GZIP header is 0x1F 0x8B <method> <flags>... <compressed-by>. */
while (read(fd, &c, 1) == 1) {
switch (state) {
case 0:
if (c == 0x1F)
state++;
break;
case 1:
if (c == 0x8B)
state++;
else
state = 0;
break;
case 2 ... 8:
state++;
break;
case 9:
/* Seek back to the start of the gzip header. */
lseek(fd, -10, SEEK_CUR);
/* One final check: "compressed under UNIX". */
if (c != 0x03)
state = -1;
else
return unpack_bzimage(fd, page_offset);
}
}
errx(1, "Could not find kernel in bzImage");
}
/* Unfortunately the entire ELF image isn't compressed: the segments
* which need loading are extracted and compressed raw. This denies us the
* information we need to make a fully-general loader. */
static unsigned long unpack_bzimage(int fd, unsigned long *page_offset)
{
gzFile f;
int ret, len = 0;
/* A bzImage always gets loaded at physical address 1M. This is
* actually configurable as CONFIG_PHYSICAL_START, but as the comment
* there says, "Don't change this unless you know what you are doing".
* Indeed. */
void *img = (void *)0x100000;
/* gzdopen takes our file descriptor (carefully placed at the start of
* the GZIP header we found) and returns a gzFile. */
f = gzdopen(fd, "rb");
/* Unfortunately, if we made a mistake and it wasn't really a gzip
* header, it will still read the file, but directly without
* decompressing it. For us, that's a misfeature. */
if (gzdirect(f))
errx(1, "did not find correct gzip header");
/* We read it into memory in 64k chunks until we hit the end. */
while ((ret = gzread(f, img + len, 65536)) > 0)
len += ret;
if (ret < 0)
err(1, "reading image from bzImage");
verbose("Unpacked size %i addr %p\n", len, img);
/* Without the ELF header, we can't tell virtual-physical gap. This is
* CONFIG_PAGE_OFFSET, and people do actually change it. Fortunately,
* I have a clever way of figuring it out from the code itself. */
*page_offset = intuit_page_offset(img, len);
/* Entry is physical address: convert to virtual */
return (unsigned long)img + *page_offset;
}
/* Prepare to be SHOCKED and AMAZED. And possibly a trifle nauseated.
*
* We know that CONFIG_PAGE_OFFSET sets what virtual address the kernel expects
* to be. We don't know what that option was, but we can figure it out
* approximately by looking at the addresses in the code. I chose the common
* case of reading a memory location into the %eax register:
*
* movl <some-address>, %eax
*
* This gets encoded as five bytes: "0xA1 <4-byte-address>". For example,
* "0xA1 0x18 0x60 0x47 0xC0" reads the address 0xC0476018 into %eax.
*
* In this example can guess that the kernel was compiled with
* CONFIG_PAGE_OFFSET set to 0xC0000000 (it's always a round number). If the
* kernel were larger than 16MB, we might see 0xC1 addresses show up, but our
* kernel isn't that bloated yet.
*
* Unfortunately, x86 has variable-length instructions, so finding this
* particular instruction properly involves writing a disassembler. Instead,
* we rely on statistics. We look for "0xA1" and tally the different bytes
* which occur 4 bytes later (the "0xC0" in our example above). When one of
* those bytes appears three times, we can be reasonably confident that it
* forms the start of CONFIG_PAGE_OFFSET.
*
* This is amazingly reliable. */
static unsigned long intuit_page_offset(unsigned char *img, unsigned long len)
{
unsigned int i, possibilities[256] = { 0 };
for (i = 0; i + 4 < len; i++) {
/* mov 0xXXXXXXXX,%eax */
if (img[i] == 0xA1 && ++possibilities[img[i+4]] > 3)
return (unsigned long)img[i+4] << 24;
}
errx(1, "could not determine page offset");
}
next prev parent reply other threads:[~2007-05-03 2:01 UTC|newest]
Thread overview: 113+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-28 17:58 [PATCH] [0/22] x86 candidate patches for review II: 64bit relocatable kernel Andi Kleen
2007-04-28 17:58 ` [PATCH] [1/22] x86_64: dma_ops as const Andi Kleen
2007-04-28 17:58 ` [PATCH] [2/22] x86_64: Assembly safe page.h and pgtable.h Andi Kleen
2007-04-28 17:58 ` [PATCH] [3/22] x86_64: Kill temp boot pmds Andi Kleen
2007-04-28 17:58 ` [PATCH] [4/22] x86_64: Clean up the early boot page table Andi Kleen
2007-04-28 17:58 ` [PATCH] [5/22] x86_64: Fix early printk to use standard ISA mapping Andi Kleen
2007-04-28 17:58 ` [PATCH] [6/22] x86_64: modify copy_bootdata to use virtual addresses Andi Kleen
2007-04-28 17:58 ` [PATCH] [7/22] x86_64: cleanup segments Andi Kleen
2007-04-28 17:58 ` [PATCH] [8/22] x86_64: Add EFER to the register set saved by save_processor_state Andi Kleen
2007-04-28 17:58 ` [PATCH] [9/22] x86_64: 64bit PIC SMP trampoline Andi Kleen
2007-04-28 17:58 ` [PATCH] [10/22] x86_64: Get rid of dead code in suspend resume Andi Kleen
2007-04-28 17:58 ` [PATCH] [11/22] x86_64: wakeup.S rename registers to reflect right names Andi Kleen
2007-04-28 17:58 ` [PATCH] [12/22] x86_64: wakeup.S misc cleanups Andi Kleen
2007-04-28 17:59 ` [PATCH] [13/22] x86_64: 64bit ACPI wakeup trampoline Andi Kleen
2007-04-28 17:59 ` [PATCH] [14/22] x86_64: Modify discover_ebda to use virtual addresses Andi Kleen
2007-04-28 17:59 ` [PATCH] [15/22] x86_64: Remove the identity mapping as early as possible Andi Kleen
2007-04-28 17:59 ` [PATCH] [16/22] x86: Move swsusp __pa() dependent code to arch portion Andi Kleen
2007-04-28 17:59 ` [PATCH] [17/22] x86_64: do not use virt_to_page on kernel data address Andi Kleen
2007-04-28 17:59 ` [PATCH] [18/22] x86: __pa and __pa_symbol address space separation Andi Kleen
2007-04-28 17:59 ` [PATCH] [19/22] x86_64: Relocatable Kernel Support Andi Kleen
2007-04-28 17:59 ` [PATCH] [20/22] x86_64: build-time checking Andi Kleen
2007-04-28 17:59 ` [PATCH] [21/22] x86_64: Extend bzImage protocol for relocatable bzImage Andi Kleen
2007-04-28 18:07 ` Jeff Garzik
2007-04-28 18:24 ` Andi Kleen
2007-04-28 20:18 ` [patches] " Eric W. Biederman
2007-04-28 20:38 ` H. Peter Anvin
2007-04-28 20:46 ` Eric W. Biederman
2007-04-29 4:50 ` Vivek Goyal
2007-04-28 20:39 ` Jeff Garzik
2007-04-29 7:24 ` Jeremy Fitzhardinge
2007-04-29 15:11 ` Eric W. Biederman
2007-04-30 3:03 ` Rusty Russell
2007-04-30 4:38 ` H. Peter Anvin
2007-04-30 5:03 ` Rusty Russell
2007-04-30 5:25 ` Eric W. Biederman
2007-04-30 16:03 ` H. Peter Anvin
2007-04-30 16:47 ` Eric W. Biederman
2007-04-30 15:34 ` Eric W. Biederman
2007-05-01 3:38 ` Rusty Russell
2007-05-01 3:45 ` H. Peter Anvin
2007-05-01 3:59 ` Rusty Russell
2007-05-01 4:00 ` H. Peter Anvin
2007-05-01 4:50 ` Rusty Russell
2007-05-01 5:28 ` H. Peter Anvin
2007-05-01 6:05 ` Eric W. Biederman
2007-05-01 3:57 ` Eric W. Biederman
2007-05-01 5:37 ` Jeremy Fitzhardinge
2007-05-01 6:11 ` Eric W. Biederman
2007-05-01 7:34 ` Rusty Russell
2007-05-01 8:03 ` Jeremy Fitzhardinge
2007-04-30 18:50 ` Jeremy Fitzhardinge
2007-04-30 22:10 ` Eric W. Biederman
2007-04-30 22:42 ` Jeremy Fitzhardinge
2007-04-30 22:51 ` Jeremy Fitzhardinge
2007-04-30 23:10 ` Eric W. Biederman
2007-04-30 23:16 ` H. Peter Anvin
2007-04-30 23:35 ` Eric W. Biederman
2007-05-01 3:39 ` Andi Kleen
2007-05-01 2:48 ` H. Peter Anvin
2007-05-02 9:31 ` Gerd Hoffmann
2007-05-02 15:16 ` Jeremy Fitzhardinge
2007-05-02 20:51 ` H. Peter Anvin
2007-05-02 21:01 ` Jeremy Fitzhardinge
2007-05-02 21:09 ` H. Peter Anvin
2007-05-02 21:39 ` Jeremy Fitzhardinge
2007-05-02 21:59 ` H. Peter Anvin
2007-05-02 23:03 ` Jeremy Fitzhardinge
2007-05-03 4:50 ` Vivek Goyal
2007-05-03 6:42 ` Eric W. Biederman
2007-05-03 7:05 ` Jeremy Fitzhardinge
2007-05-03 13:23 ` Eric W. Biederman
2007-05-03 16:23 ` Jeremy Fitzhardinge
2007-05-08 16:41 ` yhlu
2007-05-08 17:18 ` Eric W. Biederman
2007-05-08 17:33 ` yhlu
2007-05-08 18:51 ` yhlu
2007-05-08 19:01 ` yhlu
2007-05-08 19:11 ` Eric W. Biederman
2007-05-08 22:00 ` yhlu
2007-05-08 22:07 ` Jeremy Fitzhardinge
2007-05-08 22:35 ` H. Peter Anvin
2007-05-08 22:41 ` yhlu
2007-05-08 23:13 ` H. Peter Anvin
2007-05-09 1:44 ` Eric W. Biederman
2007-05-09 2:23 ` H. Peter Anvin
2007-05-09 3:30 ` Eric W. Biederman
2007-05-09 4:52 ` yhlu
2007-05-09 5:04 ` H. Peter Anvin
2007-05-09 5:08 ` H. Peter Anvin
2007-05-09 5:48 ` yhlu
2007-05-09 5:54 ` H. Peter Anvin
2007-05-09 5:55 ` H. Peter Anvin
2007-05-09 10:52 ` Eric W. Biederman
2007-05-09 16:31 ` yhlu
2007-05-09 19:21 ` H. Peter Anvin
2007-05-10 0:52 ` Eric W. Biederman
2007-05-09 7:58 ` Gerd Hoffmann
2007-05-09 11:21 ` Eric W. Biederman
2007-05-10 0:55 ` yhlu
2007-05-09 2:44 ` yhlu
2007-05-09 3:33 ` Vivek Goyal
2007-05-09 4:42 ` yhlu
2007-05-09 4:58 ` Eric W. Biederman
2007-05-08 17:24 ` Vivek Goyal
2007-05-08 17:34 ` yhlu
2007-05-03 2:01 ` Rusty Russell [this message]
2007-05-02 21:17 ` Eric W. Biederman
2007-05-02 21:24 ` H. Peter Anvin
2007-05-02 21:36 ` Eric W. Biederman
2007-04-29 17:51 ` H. Peter Anvin
2007-04-29 18:10 ` Eric W. Biederman
2007-04-30 4:41 ` Rusty Russell
2007-04-28 17:59 ` [PATCH] [22/22] x86_64: Move cpu verification code to common file Andi Kleen
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=1178157684.23670.11.camel@localhost.localdomain \
--to=rusty@rustcorp.com.au \
--cc=ebiederm@xmission.com \
--cc=hpa@zytor.com \
--cc=jeff@garzik.org \
--cc=jeremy@goop.org \
--cc=kraxel@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@x86-64.org \
--cc=vgoyal@in.ibm.com \
--cc=virtualization@lists.linux-foundation.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome