mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
Merge branch 'x86/setup' into x86/devel
This commit is contained in:
commit
3c1ca43faf
20 changed files with 210 additions and 148 deletions
|
@ -1,17 +1,14 @@
|
||||||
THE LINUX/I386 BOOT PROTOCOL
|
THE LINUX/x86 BOOT PROTOCOL
|
||||||
----------------------------
|
---------------------------
|
||||||
|
|
||||||
H. Peter Anvin <hpa@zytor.com>
|
On the x86 platform, the Linux kernel uses a rather complicated boot
|
||||||
Last update 2007-05-23
|
|
||||||
|
|
||||||
On the i386 platform, the Linux kernel uses a rather complicated boot
|
|
||||||
convention. This has evolved partially due to historical aspects, as
|
convention. This has evolved partially due to historical aspects, as
|
||||||
well as the desire in the early days to have the kernel itself be a
|
well as the desire in the early days to have the kernel itself be a
|
||||||
bootable image, the complicated PC memory model and due to changed
|
bootable image, the complicated PC memory model and due to changed
|
||||||
expectations in the PC industry caused by the effective demise of
|
expectations in the PC industry caused by the effective demise of
|
||||||
real-mode DOS as a mainstream operating system.
|
real-mode DOS as a mainstream operating system.
|
||||||
|
|
||||||
Currently, the following versions of the Linux/i386 boot protocol exist.
|
Currently, the following versions of the Linux/x86 boot protocol exist.
|
||||||
|
|
||||||
Old kernels: zImage/Image support only. Some very early kernels
|
Old kernels: zImage/Image support only. Some very early kernels
|
||||||
may not even support a command line.
|
may not even support a command line.
|
||||||
|
@ -372,10 +369,17 @@ Protocol: 2.00+
|
||||||
- If 0, the protected-mode code is loaded at 0x10000.
|
- If 0, the protected-mode code is loaded at 0x10000.
|
||||||
- If 1, the protected-mode code is loaded at 0x100000.
|
- If 1, the protected-mode code is loaded at 0x100000.
|
||||||
|
|
||||||
|
Bit 5 (write): QUIET_FLAG
|
||||||
|
- If 0, print early messages.
|
||||||
|
- If 1, suppress early messages.
|
||||||
|
This requests to the kernel (decompressor and early
|
||||||
|
kernel) to not write early messages that require
|
||||||
|
accessing the display hardware directly.
|
||||||
|
|
||||||
Bit 6 (write): KEEP_SEGMENTS
|
Bit 6 (write): KEEP_SEGMENTS
|
||||||
Protocol: 2.07+
|
Protocol: 2.07+
|
||||||
- if 0, reload the segment registers in the 32bit entry point.
|
- If 0, reload the segment registers in the 32bit entry point.
|
||||||
- if 1, do not reload the segment registers in the 32bit entry point.
|
- If 1, do not reload the segment registers in the 32bit entry point.
|
||||||
Assume that %cs %ds %ss %es are all set to flat segments with
|
Assume that %cs %ds %ss %es are all set to flat segments with
|
||||||
a base of 0 (or the equivalent for their environment).
|
a base of 0 (or the equivalent for their environment).
|
||||||
|
|
||||||
|
@ -504,7 +508,7 @@ Protocol: 2.06+
|
||||||
maximum size was 255.
|
maximum size was 255.
|
||||||
|
|
||||||
Field name: hardware_subarch
|
Field name: hardware_subarch
|
||||||
Type: write
|
Type: write (optional, defaults to x86/PC)
|
||||||
Offset/size: 0x23c/4
|
Offset/size: 0x23c/4
|
||||||
Protocol: 2.07+
|
Protocol: 2.07+
|
||||||
|
|
||||||
|
@ -520,11 +524,13 @@ Protocol: 2.07+
|
||||||
0x00000002 Xen
|
0x00000002 Xen
|
||||||
|
|
||||||
Field name: hardware_subarch_data
|
Field name: hardware_subarch_data
|
||||||
Type: write
|
Type: write (subarch-dependent)
|
||||||
Offset/size: 0x240/8
|
Offset/size: 0x240/8
|
||||||
Protocol: 2.07+
|
Protocol: 2.07+
|
||||||
|
|
||||||
A pointer to data that is specific to hardware subarch
|
A pointer to data that is specific to hardware subarch
|
||||||
|
This field is currently unused for the default x86/PC environment,
|
||||||
|
do not modify.
|
||||||
|
|
||||||
Field name: payload_offset
|
Field name: payload_offset
|
||||||
Type: read
|
Type: read
|
||||||
|
@ -545,6 +551,34 @@ Protocol: 2.08+
|
||||||
|
|
||||||
The length of the payload.
|
The length of the payload.
|
||||||
|
|
||||||
|
Field name: setup_data
|
||||||
|
Type: write (special)
|
||||||
|
Offset/size: 0x250/8
|
||||||
|
Protocol: 2.09+
|
||||||
|
|
||||||
|
The 64-bit physical pointer to NULL terminated single linked list of
|
||||||
|
struct setup_data. This is used to define a more extensible boot
|
||||||
|
parameters passing mechanism. The definition of struct setup_data is
|
||||||
|
as follow:
|
||||||
|
|
||||||
|
struct setup_data {
|
||||||
|
u64 next;
|
||||||
|
u32 type;
|
||||||
|
u32 len;
|
||||||
|
u8 data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
Where, the next is a 64-bit physical pointer to the next node of
|
||||||
|
linked list, the next field of the last node is 0; the type is used
|
||||||
|
to identify the contents of data; the len is the length of data
|
||||||
|
field; the data holds the real payload.
|
||||||
|
|
||||||
|
This list may be modified at a number of points during the bootup
|
||||||
|
process. Therefore, when modifying this list one should always make
|
||||||
|
sure to consider the case where the linked list already contains
|
||||||
|
entries.
|
||||||
|
|
||||||
|
|
||||||
**** THE IMAGE CHECKSUM
|
**** THE IMAGE CHECKSUM
|
||||||
|
|
||||||
From boot protocol version 2.08 onwards the CRC-32 is calculated over
|
From boot protocol version 2.08 onwards the CRC-32 is calculated over
|
||||||
|
@ -553,6 +587,7 @@ initial remainder of 0xffffffff. The checksum is appended to the
|
||||||
file; therefore the CRC of the file up to the limit specified in the
|
file; therefore the CRC of the file up to the limit specified in the
|
||||||
syssize field of the header is always 0.
|
syssize field of the header is always 0.
|
||||||
|
|
||||||
|
|
||||||
**** THE KERNEL COMMAND LINE
|
**** THE KERNEL COMMAND LINE
|
||||||
|
|
||||||
The kernel command line has become an important way for the boot
|
The kernel command line has become an important way for the boot
|
||||||
|
@ -584,28 +619,6 @@ command line is entered using the following protocol:
|
||||||
covered by setup_move_size, so you may need to adjust this
|
covered by setup_move_size, so you may need to adjust this
|
||||||
field.
|
field.
|
||||||
|
|
||||||
Field name: setup_data
|
|
||||||
Type: write (obligatory)
|
|
||||||
Offset/size: 0x250/8
|
|
||||||
Protocol: 2.09+
|
|
||||||
|
|
||||||
The 64-bit physical pointer to NULL terminated single linked list of
|
|
||||||
struct setup_data. This is used to define a more extensible boot
|
|
||||||
parameters passing mechanism. The definition of struct setup_data is
|
|
||||||
as follow:
|
|
||||||
|
|
||||||
struct setup_data {
|
|
||||||
u64 next;
|
|
||||||
u32 type;
|
|
||||||
u32 len;
|
|
||||||
u8 data[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
Where, the next is a 64-bit physical pointer to the next node of
|
|
||||||
linked list, the next field of the last node is 0; the type is used
|
|
||||||
to identify the contents of data; the len is the length of data
|
|
||||||
field; the data holds the real payload.
|
|
||||||
|
|
||||||
|
|
||||||
**** MEMORY LAYOUT OF THE REAL-MODE CODE
|
**** MEMORY LAYOUT OF THE REAL-MODE CODE
|
||||||
|
|
|
@ -20,6 +20,14 @@ config NONPROMISC_DEVMEM
|
||||||
|
|
||||||
If in doubt, say Y.
|
If in doubt, say Y.
|
||||||
|
|
||||||
|
config X86_VERBOSE_BOOTUP
|
||||||
|
bool "Enable verbose x86 bootup info messages"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enables the informational output from the decompression stage
|
||||||
|
(e.g. bzImage) of the boot. If you disable this you will still
|
||||||
|
see errors. Disable this if you want silent bootup.
|
||||||
|
|
||||||
config EARLY_PRINTK
|
config EARLY_PRINTK
|
||||||
bool "Early printk" if EMBEDDED
|
bool "Early printk" if EMBEDDED
|
||||||
default y
|
default y
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* -*- linux-c -*- ------------------------------------------------------- *
|
/* -*- linux-c -*- ------------------------------------------------------- *
|
||||||
*
|
*
|
||||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||||
* Copyright 2007 rPath, Inc. - All Rights Reserved
|
* Copyright 2007-2008 rPath, Inc. - All Rights Reserved
|
||||||
*
|
*
|
||||||
* This file is part of the Linux kernel, and is made available under
|
* This file is part of the Linux kernel, and is made available under
|
||||||
* the terms of the GNU General Public License version 2.
|
* the terms of the GNU General Public License version 2.
|
||||||
|
@ -95,6 +95,9 @@ static void enable_a20_kbc(void)
|
||||||
|
|
||||||
outb(0xdf, 0x60); /* A20 on */
|
outb(0xdf, 0x60); /* A20 on */
|
||||||
empty_8042();
|
empty_8042();
|
||||||
|
|
||||||
|
outb(0xff, 0x64); /* Null command, but UHCI wants it */
|
||||||
|
empty_8042();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enable_a20_fast(void)
|
static void enable_a20_fast(void)
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/boot.h>
|
#include <asm/boot.h>
|
||||||
|
#include <asm/bootparam.h>
|
||||||
|
|
||||||
/* WARNING!!
|
/* WARNING!!
|
||||||
* This code is compiled with -fPIC and it is relocated dynamically
|
* This code is compiled with -fPIC and it is relocated dynamically
|
||||||
|
@ -187,13 +188,8 @@ static void gzip_release(void **);
|
||||||
/*
|
/*
|
||||||
* This is set up by the setup-routine at boot-time
|
* This is set up by the setup-routine at boot-time
|
||||||
*/
|
*/
|
||||||
static unsigned char *real_mode; /* Pointer to real-mode data */
|
static struct boot_params *real_mode; /* Pointer to real-mode data */
|
||||||
|
static int quiet;
|
||||||
#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
|
|
||||||
#ifndef STANDARD_MEMORY_BIOS_CALL
|
|
||||||
#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
|
|
||||||
#endif
|
|
||||||
#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
|
|
||||||
|
|
||||||
extern unsigned char input_data[];
|
extern unsigned char input_data[];
|
||||||
extern int input_len;
|
extern int input_len;
|
||||||
|
@ -206,7 +202,8 @@ static void free(void *where);
|
||||||
static void *memset(void *s, int c, unsigned n);
|
static void *memset(void *s, int c, unsigned n);
|
||||||
static void *memcpy(void *dest, const void *src, unsigned n);
|
static void *memcpy(void *dest, const void *src, unsigned n);
|
||||||
|
|
||||||
static void putstr(const char *);
|
static void __putstr(int, const char *);
|
||||||
|
#define putstr(__x) __putstr(0, __x)
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
#define memptr long
|
#define memptr long
|
||||||
|
@ -270,18 +267,24 @@ static void scroll(void)
|
||||||
vidmem[i] = ' ';
|
vidmem[i] = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
static void putstr(const char *s)
|
static void __putstr(int error, const char *s)
|
||||||
{
|
{
|
||||||
int x, y, pos;
|
int x, y, pos;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifndef CONFIG_X86_VERBOSE_BOOTUP
|
||||||
if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
|
if (!error)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
x = RM_SCREEN_INFO.orig_x;
|
#ifdef CONFIG_X86_32
|
||||||
y = RM_SCREEN_INFO.orig_y;
|
if (real_mode->screen_info.orig_video_mode == 0 &&
|
||||||
|
lines == 0 && cols == 0)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
x = real_mode->screen_info.orig_x;
|
||||||
|
y = real_mode->screen_info.orig_y;
|
||||||
|
|
||||||
while ((c = *s++) != '\0') {
|
while ((c = *s++) != '\0') {
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
|
@ -302,8 +305,8 @@ static void putstr(const char *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RM_SCREEN_INFO.orig_x = x;
|
real_mode->screen_info.orig_x = x;
|
||||||
RM_SCREEN_INFO.orig_y = y;
|
real_mode->screen_info.orig_y = y;
|
||||||
|
|
||||||
pos = (x + cols * y) * 2; /* Update cursor position */
|
pos = (x + cols * y) * 2; /* Update cursor position */
|
||||||
outb(14, vidport);
|
outb(14, vidport);
|
||||||
|
@ -366,9 +369,9 @@ static void flush_window(void)
|
||||||
|
|
||||||
static void error(char *x)
|
static void error(char *x)
|
||||||
{
|
{
|
||||||
putstr("\n\n");
|
__putstr(1, "\n\n");
|
||||||
putstr(x);
|
__putstr(1, x);
|
||||||
putstr("\n\n -- System halted");
|
__putstr(1, "\n\n -- System halted");
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
|
@ -395,7 +398,8 @@ static void parse_elf(void *output)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
putstr("Parsing ELF... ");
|
if (!quiet)
|
||||||
|
putstr("Parsing ELF... ");
|
||||||
|
|
||||||
phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
|
phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum);
|
||||||
if (!phdrs)
|
if (!phdrs)
|
||||||
|
@ -430,7 +434,10 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
|
||||||
{
|
{
|
||||||
real_mode = rmode;
|
real_mode = rmode;
|
||||||
|
|
||||||
if (RM_SCREEN_INFO.orig_video_mode == 7) {
|
if (real_mode->hdr.loadflags & QUIET_FLAG)
|
||||||
|
quiet = 1;
|
||||||
|
|
||||||
|
if (real_mode->screen_info.orig_video_mode == 7) {
|
||||||
vidmem = (char *) 0xb0000;
|
vidmem = (char *) 0xb0000;
|
||||||
vidport = 0x3b4;
|
vidport = 0x3b4;
|
||||||
} else {
|
} else {
|
||||||
|
@ -438,8 +445,8 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
|
||||||
vidport = 0x3d4;
|
vidport = 0x3d4;
|
||||||
}
|
}
|
||||||
|
|
||||||
lines = RM_SCREEN_INFO.orig_video_lines;
|
lines = real_mode->screen_info.orig_video_lines;
|
||||||
cols = RM_SCREEN_INFO.orig_video_cols;
|
cols = real_mode->screen_info.orig_video_cols;
|
||||||
|
|
||||||
window = output; /* Output buffer (Normally at 1M) */
|
window = output; /* Output buffer (Normally at 1M) */
|
||||||
free_mem_ptr = heap; /* Heap */
|
free_mem_ptr = heap; /* Heap */
|
||||||
|
@ -465,9 +472,11 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
makecrc();
|
makecrc();
|
||||||
putstr("\nDecompressing Linux... ");
|
if (!quiet)
|
||||||
|
putstr("\nDecompressing Linux... ");
|
||||||
gunzip();
|
gunzip();
|
||||||
parse_elf(output);
|
parse_elf(output);
|
||||||
putstr("done.\nBooting the kernel.\n");
|
if (!quiet)
|
||||||
|
putstr("done.\nBooting the kernel.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,20 @@
|
||||||
#define USE_BSD
|
#define USE_BSD
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
#define MAX_SHDRS 100
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
static Elf32_Ehdr ehdr;
|
static Elf32_Ehdr ehdr;
|
||||||
static Elf32_Shdr shdr[MAX_SHDRS];
|
|
||||||
static Elf32_Sym *symtab[MAX_SHDRS];
|
|
||||||
static Elf32_Rel *reltab[MAX_SHDRS];
|
|
||||||
static char *strtab[MAX_SHDRS];
|
|
||||||
static unsigned long reloc_count, reloc_idx;
|
static unsigned long reloc_count, reloc_idx;
|
||||||
static unsigned long *relocs;
|
static unsigned long *relocs;
|
||||||
|
|
||||||
|
struct section {
|
||||||
|
Elf32_Shdr shdr;
|
||||||
|
struct section *link;
|
||||||
|
Elf32_Sym *symtab;
|
||||||
|
Elf32_Rel *reltab;
|
||||||
|
char *strtab;
|
||||||
|
};
|
||||||
|
static struct section *secs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Following symbols have been audited. There values are constant and do
|
* Following symbols have been audited. There values are constant and do
|
||||||
* not change if bzImage is loaded at a different physical address than
|
* not change if bzImage is loaded at a different physical address than
|
||||||
|
@ -35,7 +39,7 @@ static int is_safe_abs_reloc(const char* sym_name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
|
for (i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
|
||||||
if (!strcmp(sym_name, safe_abs_relocs[i]))
|
if (!strcmp(sym_name, safe_abs_relocs[i]))
|
||||||
/* Match found */
|
/* Match found */
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -137,10 +141,10 @@ static const char *sec_name(unsigned shndx)
|
||||||
{
|
{
|
||||||
const char *sec_strtab;
|
const char *sec_strtab;
|
||||||
const char *name;
|
const char *name;
|
||||||
sec_strtab = strtab[ehdr.e_shstrndx];
|
sec_strtab = secs[ehdr.e_shstrndx].strtab;
|
||||||
name = "<noname>";
|
name = "<noname>";
|
||||||
if (shndx < ehdr.e_shnum) {
|
if (shndx < ehdr.e_shnum) {
|
||||||
name = sec_strtab + shdr[shndx].sh_name;
|
name = sec_strtab + secs[shndx].shdr.sh_name;
|
||||||
}
|
}
|
||||||
else if (shndx == SHN_ABS) {
|
else if (shndx == SHN_ABS) {
|
||||||
name = "ABSOLUTE";
|
name = "ABSOLUTE";
|
||||||
|
@ -159,7 +163,7 @@ static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
|
||||||
name = sym_strtab + sym->st_name;
|
name = sym_strtab + sym->st_name;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
name = sec_name(shdr[sym->st_shndx].sh_name);
|
name = sec_name(secs[sym->st_shndx].shdr.sh_name);
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -244,29 +248,34 @@ static void read_ehdr(FILE *fp)
|
||||||
static void read_shdrs(FILE *fp)
|
static void read_shdrs(FILE *fp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (ehdr.e_shnum > MAX_SHDRS) {
|
Elf32_Shdr shdr;
|
||||||
die("%d section headers supported: %d\n",
|
|
||||||
ehdr.e_shnum, MAX_SHDRS);
|
secs = calloc(ehdr.e_shnum, sizeof(struct section));
|
||||||
|
if (!secs) {
|
||||||
|
die("Unable to allocate %d section headers\n",
|
||||||
|
ehdr.e_shnum);
|
||||||
}
|
}
|
||||||
if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
|
if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
|
||||||
die("Seek to %d failed: %s\n",
|
die("Seek to %d failed: %s\n",
|
||||||
ehdr.e_shoff, strerror(errno));
|
ehdr.e_shoff, strerror(errno));
|
||||||
}
|
}
|
||||||
if (fread(&shdr, sizeof(shdr[0]), ehdr.e_shnum, fp) != ehdr.e_shnum) {
|
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||||
die("Cannot read ELF section headers: %s\n",
|
struct section *sec = &secs[i];
|
||||||
strerror(errno));
|
if (fread(&shdr, sizeof shdr, 1, fp) != 1)
|
||||||
}
|
die("Cannot read ELF section headers %d/%d: %s\n",
|
||||||
for(i = 0; i < ehdr.e_shnum; i++) {
|
i, ehdr.e_shnum, strerror(errno));
|
||||||
shdr[i].sh_name = elf32_to_cpu(shdr[i].sh_name);
|
sec->shdr.sh_name = elf32_to_cpu(shdr.sh_name);
|
||||||
shdr[i].sh_type = elf32_to_cpu(shdr[i].sh_type);
|
sec->shdr.sh_type = elf32_to_cpu(shdr.sh_type);
|
||||||
shdr[i].sh_flags = elf32_to_cpu(shdr[i].sh_flags);
|
sec->shdr.sh_flags = elf32_to_cpu(shdr.sh_flags);
|
||||||
shdr[i].sh_addr = elf32_to_cpu(shdr[i].sh_addr);
|
sec->shdr.sh_addr = elf32_to_cpu(shdr.sh_addr);
|
||||||
shdr[i].sh_offset = elf32_to_cpu(shdr[i].sh_offset);
|
sec->shdr.sh_offset = elf32_to_cpu(shdr.sh_offset);
|
||||||
shdr[i].sh_size = elf32_to_cpu(shdr[i].sh_size);
|
sec->shdr.sh_size = elf32_to_cpu(shdr.sh_size);
|
||||||
shdr[i].sh_link = elf32_to_cpu(shdr[i].sh_link);
|
sec->shdr.sh_link = elf32_to_cpu(shdr.sh_link);
|
||||||
shdr[i].sh_info = elf32_to_cpu(shdr[i].sh_info);
|
sec->shdr.sh_info = elf32_to_cpu(shdr.sh_info);
|
||||||
shdr[i].sh_addralign = elf32_to_cpu(shdr[i].sh_addralign);
|
sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
|
||||||
shdr[i].sh_entsize = elf32_to_cpu(shdr[i].sh_entsize);
|
sec->shdr.sh_entsize = elf32_to_cpu(shdr.sh_entsize);
|
||||||
|
if (sec->shdr.sh_link < ehdr.e_shnum)
|
||||||
|
sec->link = &secs[sec->shdr.sh_link];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -274,20 +283,22 @@ static void read_shdrs(FILE *fp)
|
||||||
static void read_strtabs(FILE *fp)
|
static void read_strtabs(FILE *fp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < ehdr.e_shnum; i++) {
|
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||||
if (shdr[i].sh_type != SHT_STRTAB) {
|
struct section *sec = &secs[i];
|
||||||
|
if (sec->shdr.sh_type != SHT_STRTAB) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
strtab[i] = malloc(shdr[i].sh_size);
|
sec->strtab = malloc(sec->shdr.sh_size);
|
||||||
if (!strtab[i]) {
|
if (!sec->strtab) {
|
||||||
die("malloc of %d bytes for strtab failed\n",
|
die("malloc of %d bytes for strtab failed\n",
|
||||||
shdr[i].sh_size);
|
sec->shdr.sh_size);
|
||||||
}
|
}
|
||||||
if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
|
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
|
||||||
die("Seek to %d failed: %s\n",
|
die("Seek to %d failed: %s\n",
|
||||||
shdr[i].sh_offset, strerror(errno));
|
sec->shdr.sh_offset, strerror(errno));
|
||||||
}
|
}
|
||||||
if (fread(strtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
|
if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
|
||||||
|
!= sec->shdr.sh_size) {
|
||||||
die("Cannot read symbol table: %s\n",
|
die("Cannot read symbol table: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -297,28 +308,31 @@ static void read_strtabs(FILE *fp)
|
||||||
static void read_symtabs(FILE *fp)
|
static void read_symtabs(FILE *fp)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
for(i = 0; i < ehdr.e_shnum; i++) {
|
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||||
if (shdr[i].sh_type != SHT_SYMTAB) {
|
struct section *sec = &secs[i];
|
||||||
|
if (sec->shdr.sh_type != SHT_SYMTAB) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
symtab[i] = malloc(shdr[i].sh_size);
|
sec->symtab = malloc(sec->shdr.sh_size);
|
||||||
if (!symtab[i]) {
|
if (!sec->symtab) {
|
||||||
die("malloc of %d bytes for symtab failed\n",
|
die("malloc of %d bytes for symtab failed\n",
|
||||||
shdr[i].sh_size);
|
sec->shdr.sh_size);
|
||||||
}
|
}
|
||||||
if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
|
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
|
||||||
die("Seek to %d failed: %s\n",
|
die("Seek to %d failed: %s\n",
|
||||||
shdr[i].sh_offset, strerror(errno));
|
sec->shdr.sh_offset, strerror(errno));
|
||||||
}
|
}
|
||||||
if (fread(symtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
|
if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
|
||||||
|
!= sec->shdr.sh_size) {
|
||||||
die("Cannot read symbol table: %s\n",
|
die("Cannot read symbol table: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
for(j = 0; j < shdr[i].sh_size/sizeof(symtab[i][0]); j++) {
|
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
|
||||||
symtab[i][j].st_name = elf32_to_cpu(symtab[i][j].st_name);
|
Elf32_Sym *sym = &sec->symtab[j];
|
||||||
symtab[i][j].st_value = elf32_to_cpu(symtab[i][j].st_value);
|
sym->st_name = elf32_to_cpu(sym->st_name);
|
||||||
symtab[i][j].st_size = elf32_to_cpu(symtab[i][j].st_size);
|
sym->st_value = elf32_to_cpu(sym->st_value);
|
||||||
symtab[i][j].st_shndx = elf16_to_cpu(symtab[i][j].st_shndx);
|
sym->st_size = elf32_to_cpu(sym->st_size);
|
||||||
|
sym->st_shndx = elf16_to_cpu(sym->st_shndx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,26 +341,29 @@ static void read_symtabs(FILE *fp)
|
||||||
static void read_relocs(FILE *fp)
|
static void read_relocs(FILE *fp)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
for(i = 0; i < ehdr.e_shnum; i++) {
|
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||||
if (shdr[i].sh_type != SHT_REL) {
|
struct section *sec = &secs[i];
|
||||||
|
if (sec->shdr.sh_type != SHT_REL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
reltab[i] = malloc(shdr[i].sh_size);
|
sec->reltab = malloc(sec->shdr.sh_size);
|
||||||
if (!reltab[i]) {
|
if (!sec->reltab) {
|
||||||
die("malloc of %d bytes for relocs failed\n",
|
die("malloc of %d bytes for relocs failed\n",
|
||||||
shdr[i].sh_size);
|
sec->shdr.sh_size);
|
||||||
}
|
}
|
||||||
if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) {
|
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
|
||||||
die("Seek to %d failed: %s\n",
|
die("Seek to %d failed: %s\n",
|
||||||
shdr[i].sh_offset, strerror(errno));
|
sec->shdr.sh_offset, strerror(errno));
|
||||||
}
|
}
|
||||||
if (fread(reltab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) {
|
if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
|
||||||
|
!= sec->shdr.sh_size) {
|
||||||
die("Cannot read symbol table: %s\n",
|
die("Cannot read symbol table: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
|
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
|
||||||
reltab[i][j].r_offset = elf32_to_cpu(reltab[i][j].r_offset);
|
Elf32_Rel *rel = &sec->reltab[j];
|
||||||
reltab[i][j].r_info = elf32_to_cpu(reltab[i][j].r_info);
|
rel->r_offset = elf32_to_cpu(rel->r_offset);
|
||||||
|
rel->r_info = elf32_to_cpu(rel->r_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,19 +374,21 @@ static void print_absolute_symbols(void)
|
||||||
int i;
|
int i;
|
||||||
printf("Absolute symbols\n");
|
printf("Absolute symbols\n");
|
||||||
printf(" Num: Value Size Type Bind Visibility Name\n");
|
printf(" Num: Value Size Type Bind Visibility Name\n");
|
||||||
for(i = 0; i < ehdr.e_shnum; i++) {
|
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||||
|
struct section *sec = &secs[i];
|
||||||
char *sym_strtab;
|
char *sym_strtab;
|
||||||
Elf32_Sym *sh_symtab;
|
Elf32_Sym *sh_symtab;
|
||||||
int j;
|
int j;
|
||||||
if (shdr[i].sh_type != SHT_SYMTAB) {
|
|
||||||
|
if (sec->shdr.sh_type != SHT_SYMTAB) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sh_symtab = symtab[i];
|
sh_symtab = sec->symtab;
|
||||||
sym_strtab = strtab[shdr[i].sh_link];
|
sym_strtab = sec->link->strtab;
|
||||||
for(j = 0; j < shdr[i].sh_size/sizeof(symtab[0][0]); j++) {
|
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
const char *name;
|
const char *name;
|
||||||
sym = &symtab[i][j];
|
sym = &sec->symtab[j];
|
||||||
name = sym_name(sym_strtab, sym);
|
name = sym_name(sym_strtab, sym);
|
||||||
if (sym->st_shndx != SHN_ABS) {
|
if (sym->st_shndx != SHN_ABS) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -389,26 +408,27 @@ static void print_absolute_relocs(void)
|
||||||
{
|
{
|
||||||
int i, printed = 0;
|
int i, printed = 0;
|
||||||
|
|
||||||
for(i = 0; i < ehdr.e_shnum; i++) {
|
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||||
|
struct section *sec = &secs[i];
|
||||||
|
struct section *sec_applies, *sec_symtab;
|
||||||
char *sym_strtab;
|
char *sym_strtab;
|
||||||
Elf32_Sym *sh_symtab;
|
Elf32_Sym *sh_symtab;
|
||||||
unsigned sec_applies, sec_symtab;
|
|
||||||
int j;
|
int j;
|
||||||
if (shdr[i].sh_type != SHT_REL) {
|
if (sec->shdr.sh_type != SHT_REL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sec_symtab = shdr[i].sh_link;
|
sec_symtab = sec->link;
|
||||||
sec_applies = shdr[i].sh_info;
|
sec_applies = &secs[sec->shdr.sh_info];
|
||||||
if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) {
|
if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sh_symtab = symtab[sec_symtab];
|
sh_symtab = sec_symtab->symtab;
|
||||||
sym_strtab = strtab[shdr[sec_symtab].sh_link];
|
sym_strtab = sec_symtab->link->strtab;
|
||||||
for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
|
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
|
||||||
Elf32_Rel *rel;
|
Elf32_Rel *rel;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
const char *name;
|
const char *name;
|
||||||
rel = &reltab[i][j];
|
rel = &sec->reltab[j];
|
||||||
sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
|
sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
|
||||||
name = sym_name(sym_strtab, sym);
|
name = sym_name(sym_strtab, sym);
|
||||||
if (sym->st_shndx != SHN_ABS) {
|
if (sym->st_shndx != SHN_ABS) {
|
||||||
|
@ -456,26 +476,28 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
/* Walk through the relocations */
|
/* Walk through the relocations */
|
||||||
for(i = 0; i < ehdr.e_shnum; i++) {
|
for (i = 0; i < ehdr.e_shnum; i++) {
|
||||||
char *sym_strtab;
|
char *sym_strtab;
|
||||||
Elf32_Sym *sh_symtab;
|
Elf32_Sym *sh_symtab;
|
||||||
unsigned sec_applies, sec_symtab;
|
struct section *sec_applies, *sec_symtab;
|
||||||
int j;
|
int j;
|
||||||
if (shdr[i].sh_type != SHT_REL) {
|
struct section *sec = &secs[i];
|
||||||
|
|
||||||
|
if (sec->shdr.sh_type != SHT_REL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sec_symtab = shdr[i].sh_link;
|
sec_symtab = sec->link;
|
||||||
sec_applies = shdr[i].sh_info;
|
sec_applies = &secs[sec->shdr.sh_info];
|
||||||
if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) {
|
if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sh_symtab = symtab[sec_symtab];
|
sh_symtab = sec_symtab->symtab;
|
||||||
sym_strtab = strtab[shdr[sec_symtab].sh_link];
|
sym_strtab = sec->link->strtab;
|
||||||
for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) {
|
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
|
||||||
Elf32_Rel *rel;
|
Elf32_Rel *rel;
|
||||||
Elf32_Sym *sym;
|
Elf32_Sym *sym;
|
||||||
unsigned r_type;
|
unsigned r_type;
|
||||||
rel = &reltab[i][j];
|
rel = &sec->reltab[j];
|
||||||
sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
|
sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
|
||||||
r_type = ELF32_R_TYPE(rel->r_info);
|
r_type = ELF32_R_TYPE(rel->r_info);
|
||||||
/* Don't visit relocations to absolute symbols */
|
/* Don't visit relocations to absolute symbols */
|
||||||
|
@ -539,7 +561,7 @@ static void emit_relocs(int as_text)
|
||||||
*/
|
*/
|
||||||
printf(".section \".data.reloc\",\"a\"\n");
|
printf(".section \".data.reloc\",\"a\"\n");
|
||||||
printf(".balign 4\n");
|
printf(".balign 4\n");
|
||||||
for(i = 0; i < reloc_count; i++) {
|
for (i = 0; i < reloc_count; i++) {
|
||||||
printf("\t .long 0x%08lx\n", relocs[i]);
|
printf("\t .long 0x%08lx\n", relocs[i]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -550,7 +572,7 @@ static void emit_relocs(int as_text)
|
||||||
/* Print a stop */
|
/* Print a stop */
|
||||||
printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
|
printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
|
||||||
/* Now print each relocation */
|
/* Now print each relocation */
|
||||||
for(i = 0; i < reloc_count; i++) {
|
for (i = 0; i < reloc_count; i++) {
|
||||||
buf[0] = (relocs[i] >> 0) & 0xff;
|
buf[0] = (relocs[i] >> 0) & 0xff;
|
||||||
buf[1] = (relocs[i] >> 8) & 0xff;
|
buf[1] = (relocs[i] >> 8) & 0xff;
|
||||||
buf[2] = (relocs[i] >> 16) & 0xff;
|
buf[2] = (relocs[i] >> 16) & 0xff;
|
||||||
|
@ -577,7 +599,7 @@ int main(int argc, char **argv)
|
||||||
show_absolute_relocs = 0;
|
show_absolute_relocs = 0;
|
||||||
as_text = 0;
|
as_text = 0;
|
||||||
fname = NULL;
|
fname = NULL;
|
||||||
for(i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
char *arg = argv[i];
|
char *arg = argv[i];
|
||||||
if (*arg == '-') {
|
if (*arg == '-') {
|
||||||
if (strcmp(argv[1], "--abs-syms") == 0) {
|
if (strcmp(argv[1], "--abs-syms") == 0) {
|
||||||
|
|
|
@ -28,6 +28,8 @@ static char *cpu_name(int level)
|
||||||
if (level == 64) {
|
if (level == 64) {
|
||||||
return "x86-64";
|
return "x86-64";
|
||||||
} else {
|
} else {
|
||||||
|
if (level == 15)
|
||||||
|
level = 6;
|
||||||
sprintf(buf, "i%d86", level);
|
sprintf(buf, "i%d86", level);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,6 +165,10 @@ void main(void)
|
||||||
/* Set the video mode */
|
/* Set the video mode */
|
||||||
set_video();
|
set_video();
|
||||||
|
|
||||||
|
/* Parse command line for 'quiet' and pass it to decompressor. */
|
||||||
|
if (cmdline_find_option_bool("quiet"))
|
||||||
|
boot_params.hdr.loadflags |= QUIET_FLAG;
|
||||||
|
|
||||||
/* Do the last things and invoke protected mode */
|
/* Do the last things and invoke protected mode */
|
||||||
go_to_protected_mode();
|
go_to_protected_mode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ protected_mode_jump:
|
||||||
movw %cs, %bx
|
movw %cs, %bx
|
||||||
shll $4, %ebx
|
shll $4, %ebx
|
||||||
addl %ebx, 2f
|
addl %ebx, 2f
|
||||||
|
jmp 1f # Short jump to serialize on 386/486
|
||||||
|
1:
|
||||||
|
|
||||||
movw $__BOOT_DS, %cx
|
movw $__BOOT_DS, %cx
|
||||||
movw $__BOOT_TSS, %di
|
movw $__BOOT_TSS, %di
|
||||||
|
@ -40,8 +42,6 @@ protected_mode_jump:
|
||||||
movl %cr0, %edx
|
movl %cr0, %edx
|
||||||
orb $X86_CR0_PE, %dl # Protected mode
|
orb $X86_CR0_PE, %dl # Protected mode
|
||||||
movl %edx, %cr0
|
movl %edx, %cr0
|
||||||
jmp 1f # Short jump to serialize on 386/486
|
|
||||||
1:
|
|
||||||
|
|
||||||
# Transition to 32-bit mode
|
# Transition to 32-bit mode
|
||||||
.byte 0x66, 0xea # ljmpl opcode
|
.byte 0x66, 0xea # ljmpl opcode
|
||||||
|
|
|
@ -40,6 +40,7 @@ struct setup_header {
|
||||||
__u8 type_of_loader;
|
__u8 type_of_loader;
|
||||||
__u8 loadflags;
|
__u8 loadflags;
|
||||||
#define LOADED_HIGH (1<<0)
|
#define LOADED_HIGH (1<<0)
|
||||||
|
#define QUIET_FLAG (1<<5)
|
||||||
#define KEEP_SEGMENTS (1<<6)
|
#define KEEP_SEGMENTS (1<<6)
|
||||||
#define CAN_USE_HEAP (1<<7)
|
#define CAN_USE_HEAP (1<<7)
|
||||||
__u16 setup_move_size;
|
__u16 setup_move_size;
|
||||||
|
|
Loading…
Reference in a new issue