|
|
f96e0b |
From be56f8f0420fa5efc55ac9789d41c6307a84bef0 Mon Sep 17 00:00:00 2001
|
|
|
f96e0b |
From: "C. Masloch" <pushbx@38.de>
|
|
|
f96e0b |
Date: Sun, 27 Jan 2013 16:07:25 +0100
|
|
|
f96e0b |
Subject: [PATCH 142/482] Improve FreeDOS direct loading support
|
|
|
f96e0b |
compatibility.
|
|
|
f96e0b |
|
|
|
f96e0b |
* include/grub/i386/relocator.h (grub_relocator16_state):
|
|
|
f96e0b |
New member ebp.
|
|
|
f96e0b |
* grub-core/lib/i386/relocator.c (grub_relocator16_ebp): New extern
|
|
|
f96e0b |
variable.
|
|
|
f96e0b |
(grub_relocator16_boot): Handle %ebp.
|
|
|
f96e0b |
* grub-core/lib/i386/relocator16.S: Likewise.
|
|
|
f96e0b |
* grub-core/loader/i386/pc/freedos.c:
|
|
|
f96e0b |
Load BPB to pass kernel which partition to load from.
|
|
|
f96e0b |
Check that kernel file is not too large.
|
|
|
f96e0b |
Set register dl to BIOS unit number as well.
|
|
|
f96e0b |
---
|
|
|
f96e0b |
ChangeLog | 15 ++++++++++
|
|
|
f96e0b |
grub-core/lib/i386/relocator.c | 2 ++
|
|
|
f96e0b |
grub-core/lib/i386/relocator16.S | 5 ++++
|
|
|
f96e0b |
grub-core/loader/i386/pc/freedos.c | 61 ++++++++++++++++++++++++++++++++++----
|
|
|
f96e0b |
include/grub/i386/relocator.h | 1 +
|
|
|
f96e0b |
5 files changed, 79 insertions(+), 5 deletions(-)
|
|
|
f96e0b |
|
|
|
f96e0b |
diff --git a/ChangeLog b/ChangeLog
|
|
|
f96e0b |
index 8c4d087..f5cb7dc 100644
|
|
|
f96e0b |
--- a/ChangeLog
|
|
|
f96e0b |
+++ b/ChangeLog
|
|
|
f96e0b |
@@ -1,3 +1,18 @@
|
|
|
f96e0b |
+2013-01-27 C. Masloch <pushbx@38.de>
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ Improve FreeDOS direct loading support compatibility.
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ * include/grub/i386/relocator.h (grub_relocator16_state):
|
|
|
f96e0b |
+ New member ebp.
|
|
|
f96e0b |
+ * grub-core/lib/i386/relocator.c (grub_relocator16_ebp): New extern
|
|
|
f96e0b |
+ variable.
|
|
|
f96e0b |
+ (grub_relocator16_boot): Handle %ebp.
|
|
|
f96e0b |
+ * grub-core/lib/i386/relocator16.S: Likewise.
|
|
|
f96e0b |
+ * grub-core/loader/i386/pc/freedos.c:
|
|
|
f96e0b |
+ Load BPB to pass kernel which partition to load from.
|
|
|
f96e0b |
+ Check that kernel file is not too large.
|
|
|
f96e0b |
+ Set register dl to BIOS unit number as well.
|
|
|
f96e0b |
+
|
|
|
f96e0b |
2013-01-22 Colin Watson <cjwatson@ubuntu.com>
|
|
|
f96e0b |
|
|
|
f96e0b |
* util/grub-reboot.in (usage): Document the need for
|
|
|
f96e0b |
diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c
|
|
|
f96e0b |
index df25b30..0170eed 100644
|
|
|
f96e0b |
--- a/grub-core/lib/i386/relocator.c
|
|
|
f96e0b |
+++ b/grub-core/lib/i386/relocator.c
|
|
|
f96e0b |
@@ -54,6 +54,7 @@ extern grub_uint16_t grub_relocator16_sp;
|
|
|
f96e0b |
extern grub_uint32_t grub_relocator16_edx;
|
|
|
f96e0b |
extern grub_uint32_t grub_relocator16_ebx;
|
|
|
f96e0b |
extern grub_uint32_t grub_relocator16_esi;
|
|
|
f96e0b |
+extern grub_uint32_t grub_relocator16_ebp;
|
|
|
f96e0b |
|
|
|
f96e0b |
extern grub_uint16_t grub_relocator16_keep_a20_enabled;
|
|
|
f96e0b |
|
|
|
f96e0b |
@@ -225,6 +226,7 @@ grub_relocator16_boot (struct grub_relocator *rel,
|
|
|
f96e0b |
grub_relocator16_ss = state.ss;
|
|
|
f96e0b |
grub_relocator16_sp = state.sp;
|
|
|
f96e0b |
|
|
|
f96e0b |
+ grub_relocator16_ebp = state.ebp;
|
|
|
f96e0b |
grub_relocator16_ebx = state.ebx;
|
|
|
f96e0b |
grub_relocator16_edx = state.edx;
|
|
|
f96e0b |
grub_relocator16_esi = state.esi;
|
|
|
f96e0b |
diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S
|
|
|
f96e0b |
index e79d875..c8d6f86 100644
|
|
|
f96e0b |
--- a/grub-core/lib/i386/relocator16.S
|
|
|
f96e0b |
+++ b/grub-core/lib/i386/relocator16.S
|
|
|
f96e0b |
@@ -259,6 +259,11 @@ VARIABLE(grub_relocator16_edx)
|
|
|
f96e0b |
VARIABLE(grub_relocator16_ebx)
|
|
|
f96e0b |
.long 0
|
|
|
f96e0b |
|
|
|
f96e0b |
+ /* movl imm32, %ebp. */
|
|
|
f96e0b |
+ .byte 0x66, 0xbd
|
|
|
f96e0b |
+VARIABLE(grub_relocator16_ebp)
|
|
|
f96e0b |
+ .long 0
|
|
|
f96e0b |
+
|
|
|
f96e0b |
/* Cleared direction flag is of no problem with any current
|
|
|
f96e0b |
payload and makes this implementation easier. */
|
|
|
f96e0b |
cld
|
|
|
f96e0b |
diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c
|
|
|
f96e0b |
index f1eed57..e685c6e 100644
|
|
|
f96e0b |
--- a/grub-core/loader/i386/pc/freedos.c
|
|
|
f96e0b |
+++ b/grub-core/loader/i386/pc/freedos.c
|
|
|
f96e0b |
@@ -32,6 +32,7 @@
|
|
|
f96e0b |
#include <grub/video.h>
|
|
|
f96e0b |
#include <grub/mm.h>
|
|
|
f96e0b |
#include <grub/cpu/relocator.h>
|
|
|
f96e0b |
+#include <grub/machine/chainloader.h>
|
|
|
f96e0b |
|
|
|
f96e0b |
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
f96e0b |
|
|
|
f96e0b |
@@ -40,8 +41,23 @@ static struct grub_relocator *rel;
|
|
|
f96e0b |
static grub_uint32_t ebx = 0xffffffff;
|
|
|
f96e0b |
|
|
|
f96e0b |
#define GRUB_FREEDOS_SEGMENT 0x60
|
|
|
f96e0b |
+#define GRUB_FREEDOS_ADDR (GRUB_FREEDOS_SEGMENT << 4)
|
|
|
f96e0b |
#define GRUB_FREEDOS_STACK_SEGMENT 0x1fe0
|
|
|
f96e0b |
-#define GRUB_FREEDOS_STACK_POINTER 0x8000
|
|
|
f96e0b |
+#define GRUB_FREEDOS_STACK_BPB_POINTER 0x7c00
|
|
|
f96e0b |
+#define GRUB_FREEDOS_BPB_ADDR ((GRUB_FREEDOS_STACK_SEGMENT << 4) \
|
|
|
f96e0b |
+ + GRUB_FREEDOS_STACK_BPB_POINTER)
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+/* FreeDOS boot.asm passes register sp as exactly this. Importantly,
|
|
|
f96e0b |
+ it must point below the BPB (to avoid overwriting any of it). */
|
|
|
f96e0b |
+#define GRUB_FREEDOS_STACK_POINTER (GRUB_FREEDOS_STACK_BPB_POINTER \
|
|
|
f96e0b |
+ - 0x60)
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+/* In this, the additional 8192 bytes are the stack reservation; the
|
|
|
f96e0b |
+ remaining parts trivially give the maximum allowed size. */
|
|
|
f96e0b |
+#define GRUB_FREEDOS_MAX_SIZE ((GRUB_FREEDOS_STACK_SEGMENT << 4) \
|
|
|
f96e0b |
+ + GRUB_FREEDOS_STACK_POINTER \
|
|
|
f96e0b |
+ - GRUB_FREEDOS_ADDR \
|
|
|
f96e0b |
+ - 8192)
|
|
|
f96e0b |
|
|
|
f96e0b |
static grub_err_t
|
|
|
f96e0b |
grub_freedos_boot (void)
|
|
|
f96e0b |
@@ -49,14 +65,16 @@ grub_freedos_boot (void)
|
|
|
f96e0b |
struct grub_relocator16_state state = {
|
|
|
f96e0b |
.cs = GRUB_FREEDOS_SEGMENT,
|
|
|
f96e0b |
.ip = 0,
|
|
|
f96e0b |
- .ds = 0,
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ .ds = GRUB_FREEDOS_STACK_SEGMENT,
|
|
|
f96e0b |
.es = 0,
|
|
|
f96e0b |
.fs = 0,
|
|
|
f96e0b |
.gs = 0,
|
|
|
f96e0b |
.ss = GRUB_FREEDOS_STACK_SEGMENT,
|
|
|
f96e0b |
.sp = GRUB_FREEDOS_STACK_POINTER,
|
|
|
f96e0b |
+ .ebp = GRUB_FREEDOS_STACK_BPB_POINTER,
|
|
|
f96e0b |
.ebx = ebx,
|
|
|
f96e0b |
- .edx = 0,
|
|
|
f96e0b |
+ .edx = ebx,
|
|
|
f96e0b |
.a20 = 1
|
|
|
f96e0b |
};
|
|
|
f96e0b |
grub_video_set_mode ("text", 0, 0);
|
|
|
f96e0b |
@@ -79,8 +97,9 @@ grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)),
|
|
|
f96e0b |
{
|
|
|
f96e0b |
grub_file_t file = 0;
|
|
|
f96e0b |
grub_err_t err;
|
|
|
f96e0b |
- void *kernelsys;
|
|
|
f96e0b |
+ void *bs, *kernelsys;
|
|
|
f96e0b |
grub_size_t kernelsyssize;
|
|
|
f96e0b |
+ grub_device_t dev;
|
|
|
f96e0b |
|
|
|
f96e0b |
if (argc == 0)
|
|
|
f96e0b |
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
|
|
f96e0b |
@@ -95,12 +114,44 @@ grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)),
|
|
|
f96e0b |
if (! file)
|
|
|
f96e0b |
goto fail;
|
|
|
f96e0b |
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ grub_relocator_chunk_t ch;
|
|
|
f96e0b |
+ err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_BPB_ADDR,
|
|
|
f96e0b |
+ GRUB_DISK_SECTOR_SIZE);
|
|
|
f96e0b |
+ if (err)
|
|
|
f96e0b |
+ goto fail;
|
|
|
f96e0b |
+ bs = get_virtual_current_address (ch);
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+
|
|
|
f96e0b |
ebx = grub_get_root_biosnumber ();
|
|
|
f96e0b |
+ dev = grub_device_open (0);
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ if (dev && dev->disk)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs);
|
|
|
f96e0b |
+ if (err)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ grub_device_close (dev);
|
|
|
f96e0b |
+ goto fail;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ grub_chainloader_patch_bpb (bs, dev, ebx);
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ if (dev)
|
|
|
f96e0b |
+ grub_device_close (dev);
|
|
|
f96e0b |
|
|
|
f96e0b |
kernelsyssize = grub_file_size (file);
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ if (kernelsyssize > GRUB_FREEDOS_MAX_SIZE)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ grub_error (GRUB_ERR_BAD_OS,
|
|
|
f96e0b |
+ N_("file `%s' is too large"), argv[0]);
|
|
|
f96e0b |
+ goto fail;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+
|
|
|
f96e0b |
{
|
|
|
f96e0b |
grub_relocator_chunk_t ch;
|
|
|
f96e0b |
- err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_SEGMENT << 4,
|
|
|
f96e0b |
+ err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_ADDR,
|
|
|
f96e0b |
kernelsyssize);
|
|
|
f96e0b |
if (err)
|
|
|
f96e0b |
goto fail;
|
|
|
f96e0b |
diff --git a/include/grub/i386/relocator.h b/include/grub/i386/relocator.h
|
|
|
f96e0b |
index 46becb8..5f89a7e 100644
|
|
|
f96e0b |
--- a/include/grub/i386/relocator.h
|
|
|
f96e0b |
+++ b/include/grub/i386/relocator.h
|
|
|
f96e0b |
@@ -49,6 +49,7 @@ struct grub_relocator16_state
|
|
|
f96e0b |
grub_uint32_t ebx;
|
|
|
f96e0b |
grub_uint32_t edx;
|
|
|
f96e0b |
grub_uint32_t esi;
|
|
|
f96e0b |
+ grub_uint32_t ebp;
|
|
|
f96e0b |
int a20;
|
|
|
f96e0b |
};
|
|
|
f96e0b |
|
|
|
f96e0b |
--
|
|
|
f96e0b |
1.8.2.1
|
|
|
f96e0b |
|