Here's a newer version of the Multiboot patch. It fixes a memory map parsing problem, and adds support for cmdline parameter (so e.g. serial port can be used).
It's targetted at memtest86+ (not memtest86), but it can be backported to memtest86 with minimal effort. -- Robert Millan The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and how) you may access your data; but nobody's threatening your freedom: we still allow you to remove your data and not access it at all."
diff -x debian -Nur memtest86+-2.11.old/head.S memtest86+-2.11/head.S --- memtest86+-2.11.old/head.S 2008-11-16 01:18:14.000000000 +0100 +++ memtest86+-2.11/head.S 2009-03-12 00:08:25.000000000 +0100 @@ -38,6 +38,13 @@ cld cli + /* Store MBI pointer */ + xorl %ecx, %ecx + cmpl $0x2BADB002, %eax + jne 0f + movl %ebx, %ecx +0: + /* Ensure I have a stack pointer */ testl %esp, %esp jnz 0f @@ -50,6 +57,20 @@ 0: popl %ebx addl $_GLOBAL_OFFSET_TABLE_+[.-0b], %ebx + /* Move MBI pointer to a safe place */ + testl %ecx, %ecx + je 0f + movl %ecx, mbi...@gotoff(%ebx) +0: + + jmp 0f + /* Multiboot header */ +.align 4 + .long 0x1BADB002 + .long 0 + .long -0x1BADB002 +0: + /* Pick the appropriate stack address */ leal stack_...@gotoff(%ebx), %esp @@ -956,6 +977,9 @@ movl $1, %eax ret +.globl mbiptr +mbiptr: + .long 0 realptr: .word real - RSTART .word 0x0000 diff -x debian -Nur memtest86+-2.11.old/init.c memtest86+-2.11/init.c --- memtest86+-2.11.old/init.c 2008-11-17 14:15:21.000000000 +0100 +++ memtest86+-2.11/init.c 2009-03-11 02:02:55.000000000 +0100 @@ -14,6 +14,7 @@ #include "controller.h" #include "pci.h" #include "io.h" +#include "multiboot.h" #define rdmsr(msr,val1,val2) \ __asm__ __volatile__("rdmsr" \ @@ -96,7 +97,10 @@ /* Determine the memory map */ if ((firmware == FIRMWARE_UNKNOWN) && (memsz_mode != SZ_MODE_PROBE)) { - if (query_linuxbios()) { + if (query_multiboot()) { + firmware = FIRMWARE_MULTIBOOT; + } + else if (query_linuxbios()) { firmware = FIRMWARE_LINUXBIOS; } else if (query_pcbios()) { diff -x debian -Nur memtest86+-2.11.old/main.c memtest86+-2.11/main.c --- memtest86+-2.11.old/main.c 2008-11-16 01:18:14.000000000 +0100 +++ memtest86+-2.11/main.c 2009-03-12 00:12:47.000000000 +0100 @@ -11,6 +11,7 @@ #include "test.h" #include "defs.h" #include "config.h" +#include "multiboot.h" #undef TEST_TIMES #define DEFTESTS 9 @@ -149,11 +150,18 @@ if (cmdline_parsed) return; - if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC) - return; + if (mbiptr && (mbiptr->flags & MB_INFO_CMDLINE)) { + cmdline = (void *) mbiptr->cmdline; + /* skip first parameter (filename) */ + while (*cmdline && *cmdline != ' ') + cmdline++; + } else { + if (*OLD_CL_MAGIC_ADDR != OLD_CL_MAGIC) + return; - unsigned short offset = *OLD_CL_OFFSET_ADDR; - cmdline = MK_PTR(INITSEG, offset); + unsigned short offset = *OLD_CL_OFFSET_ADDR; + cmdline = MK_PTR(INITSEG, offset); + } /* skip leading spaces */ while (*cmdline == ' ') diff -x debian -Nur memtest86+-2.11.old/Makefile memtest86+-2.11/Makefile --- memtest86+-2.11.old/Makefile 2009-03-10 22:20:59.000000000 +0100 +++ memtest86+-2.11/Makefile 2009-03-11 22:32:16.000000000 +0100 @@ -15,7 +15,7 @@ OBJS= head.o reloc.o main.o test.o init.o lib.o patn.o screen_buffer.o \ config.o linuxbios.o memsize.o pci.o controller.o random.o extra.o \ - spd.o error.o dmi.o + spd.o error.o dmi.o multiboot.o all: memtest.bin memtest diff -x debian -Nur memtest86+-2.11.old/memsize.c memtest86+-2.11/memsize.c --- memtest86+-2.11.old/memsize.c 2008-11-16 01:18:14.000000000 +0100 +++ memtest86+-2.11/memsize.c 2009-09-10 00:48:34.000000000 +0200 @@ -79,7 +79,7 @@ static void memsize_bios(int res) { - if (firmware == FIRMWARE_PCBIOS) { + if (firmware == FIRMWARE_PCBIOS || firmware == FIRMWARE_MULTIBOOT) { memsize_820(res); } else if (firmware == FIRMWARE_LINUXBIOS) { diff -x debian -Nur memtest86+-2.11.old/multiboot.c memtest86+-2.11/multiboot.c --- memtest86+-2.11.old/multiboot.c 1970-01-01 01:00:00.000000000 +0100 +++ memtest86+-2.11/multiboot.c 2009-03-11 01:25:52.000000000 +0100 @@ -0,0 +1,55 @@ +/* multiboot.c + * + * Copyright (C) 2008,2009 Robert Millan + * + * Loosely based on linuxbios.c, which is: + * + * Released under version 2 of the Gnu Public License. + * By Eric Biederman + */ + +#include "multiboot.h" +#include "test.h" + +struct multiboot_mmap_entry +{ + uint32_t size; + uint64_t addr; + uint64_t len; + uint32_t type; +} __attribute__((packed)); + +int query_multiboot(void) +{ + struct multiboot_mmap_entry *mem; + int i; + + if (!mbiptr) { + return 0; + } + if (!mbiptr->mmap_addr) { + return 1; + } + if ((mbiptr->flags & MB_INFO_MEM_MAP) == 0) { + return 1; + } + + mem = (struct multiboot_mmap_entry *) mbiptr->mmap_addr; + mem_info.e820_nr = 0; + + for (i = 0; i < E820MAX; i++) { + if ((uint32_t) mem >= (mbiptr->mmap_addr + mbiptr->mmap_length)) { + break; + } + + mem_info.e820[mem_info.e820_nr].addr = mem->addr; + mem_info.e820[mem_info.e820_nr].size = mem->len; + /* Multiboot spec defines available / reserved types to match with E820. */ + mem_info.e820[mem_info.e820_nr].type = mem->type; + mem_info.e820_nr++; + + mem = (struct multiboot_mmap_entry *) ((uint32_t) mem + mem->size + sizeof (mem->size)); + } + + return 1; +} diff -x debian -Nur memtest86+-2.11.old/multiboot.h memtest86+-2.11/multiboot.h --- memtest86+-2.11.old/multiboot.h 1970-01-01 01:00:00.000000000 +0100 +++ memtest86+-2.11/multiboot.h 2009-03-11 02:15:20.000000000 +0100 @@ -0,0 +1,182 @@ +/* multiboot.h - multiboot header file. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef MULTIBOOT_MACHINE_HEADER +#define MULTIBOOT_MACHINE_HEADER 1 + +#include <stdint.h> + +/* How many bytes from the start of the file we search for the header. */ +#define MB_SEARCH 8192 + +/* The magic field should contain this. */ +#define MB_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MB_MAGIC2 0x2BADB002 + +/* The bits in the required part of flags field we don't support. */ +#define MB_UNSUPPORTED 0x0000fffc + +/* Alignment of multiboot modules. */ +#define MB_MOD_ALIGN 0x00001000 + +/* + * Flags set in the 'flags' member of the multiboot header. + */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MB_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MB_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MB_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MB_AOUT_KLUDGE 0x00010000 + +/* + * Flags to be set in the 'flags' member of the multiboot info structure. + */ + +/* is there basic lower/upper memory information? */ +#define MB_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MB_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MB_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MB_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MB_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MB_INFO_ELF_SHDR 0x00000020 + +/* is there a full memory map? */ +#define MB_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MB_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MB_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MB_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MB_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MB_INFO_VIDEO_INFO 0x00000800 + +struct multiboot_header +{ + /* Must be MB_MAGIC - see above. */ + uint32_t magic; + + /* Feature flags. */ + uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + uint32_t checksum; + + /* These are only valid if MB_AOUT_KLUDGE is set. */ + uint32_t header_addr; + uint32_t load_addr; + uint32_t load_end_addr; + uint32_t bss_end_addr; + uint32_t entry_addr; + + /* These are only valid if MB_VIDEO_MODE is set. */ + uint32_t mode_type; + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +struct multiboot_info +{ + /* Multiboot info version number */ + uint32_t flags; + + /* Available memory from BIOS */ + uint32_t mem_lower; + uint32_t mem_upper; + + /* "root" partition */ + uint32_t boot_device; + + /* Kernel command line */ + uint32_t cmdline; + + /* Boot-Module list */ + uint32_t mods_count; + uint32_t mods_addr; + + uint32_t syms[4]; + + /* Memory Mapping buffer */ + uint32_t mmap_length; + uint32_t mmap_addr; + + /* Drive Info buffer */ + uint32_t drives_length; + uint32_t drives_addr; + + /* ROM configuration table */ + uint32_t config_table; + + /* Boot Loader Name */ + uint32_t boot_loader_name; + + /* APM table */ + uint32_t apm_table; + + /* Video */ + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; +}; + +struct mod_list +{ + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + uint32_t mod_start; + uint32_t mod_end; + + /* Module command line */ + uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + uint32_t pad; +}; + +extern struct multiboot_info *mbiptr; + +#endif /* ! MULTIBOOT_MACHINE_HEADER */ diff -x debian -Nur memtest86+-2.11.old/test.h memtest86+-2.11/test.h --- memtest86+-2.11.old/test.h 2008-11-16 01:18:14.000000000 +0100 +++ memtest86+-2.11/test.h 2009-03-10 22:23:28.000000000 +0100 @@ -103,6 +103,7 @@ void *memmove(void *dest, const void *src, ulong n); int query_linuxbios(void); int query_pcbios(void); +int query_multiboot(void); int insertaddress(ulong); void printpatn(void); void printpatn(void); @@ -331,6 +332,7 @@ #define FIRMWARE_UNKNOWN 0 #define FIRMWARE_PCBIOS 1 #define FIRMWARE_LINUXBIOS 2 +#define FIRMWARE_MULTIBOOT 3 extern struct vars * const v; extern unsigned char _start[], _end[], startup_32[];