All of lore.kernel.org
 help / color / mirror / Atom feed
From: "C. Masloch" <pushbx@38.de>
To: "The development of GNU GRUB" <grub-devel@gnu.org>
Subject: Re: [PATCH] Improve FreeDOS direct loading support compatibility.
Date: Sun, 08 Jul 2012 10:28:36 +0200	[thread overview]
Message-ID: <op.wg4chy1a6p67p9@isor> (raw)
In-Reply-To: <4FF82A25.9070504@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 432 bytes --]


Thanks for the help. The attached patch includes spaces around all  
operators, doesn't include the void cast, and doesn't mention (E)DR-DOS  
any longer. I recently learned that the dl register requirement is present  
in prior releases of the FreeDOS kernel too, still called DOS-C. These  
DOS-C releases already are under GPLv2+ so I hope it is okay to mention  
them in the comment, as the attached patch does.

Regards,
Chris

[-- Attachment #2: improve-freedos-compatibility-2.diff --]
[-- Type: application/octet-stream, Size: 7257 bytes --]

Subject: [PATCH] Improve FreeDOS direct loading support compatibility
Date: Sun, 08 Jul 2012 10:08:29 +0200
From: "C. Masloch" <pushbx@38.de>

 ChangeLog                          |  15 ++++++
 grub-core/lib/i386/relocator.c     |   2 +
 grub-core/lib/i386/relocator16.S   |   5 ++
 grub-core/loader/i386/pc/freedos.c |  82 +++++++++++++++++++++++++++++++++++--
 include/grub/i386/relocator.h      |   1 +
 5 files changed, 100 insertions(+), 5 deletions(-)

# HG changeset patch
# User C. Masloch <pushbx@38.de>
# Date 1341734778 -7200
# Node ID 3c587f7d6d1e80c73ec0c4a664feebb788f00ed1
# Parent  73948d0f69334ef6b60e60c16389742c402c2f3e
Improve FreeDOS direct loading support compatibility.

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2012-06-30  C. Masloch  <pushbx@38.de>
+
+	Improve FreeDOS direct loading support compatibility.
+
+	* include/grub/i386/relocator.h (grub_relocator16_state):
+	New member ebp.
+	* grub-core/lib/i386/relocator.c (grub_relocator16_ebp): New extern
+	variable.
+	(grub_relocator16_boot): Handle %ebp.
+	* grub-core/lib/i386/relocator16.S: Likewise.
+	* grub-core/loader/i386/pc/freedos.c:
+	Load BPB to pass kernel which partition to load from.
+	Check that kernel file is not too large.
+	Set register dl to BIOS unit number as well.
+
 2012-06-27  Vladimir Serbinenko  <phcoder@gmail.com>
 
 	* configure.ac: Bump version to 2.00.
diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c
--- a/grub-core/lib/i386/relocator.c
+++ b/grub-core/lib/i386/relocator.c
@@ -54,6 +54,7 @@
 extern grub_uint32_t grub_relocator16_edx;
 extern grub_uint32_t grub_relocator16_ebx;
 extern grub_uint32_t grub_relocator16_esi;
+extern grub_uint32_t grub_relocator16_ebp;
 
 extern grub_uint16_t grub_relocator16_keep_a20_enabled;
 
@@ -225,6 +226,7 @@
   grub_relocator16_ss = state.ss;
   grub_relocator16_sp = state.sp;
 
+  grub_relocator16_ebp = state.ebp;
   grub_relocator16_ebx = state.ebx;
   grub_relocator16_edx = state.edx;
   grub_relocator16_esi = state.esi;
diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S
--- a/grub-core/lib/i386/relocator16.S
+++ b/grub-core/lib/i386/relocator16.S
@@ -259,6 +259,11 @@
 VARIABLE(grub_relocator16_ebx)
 	.long	0
 
+	/* movl imm32, %ebp.  */
+	.byte	0x66, 0xbd
+VARIABLE(grub_relocator16_ebp)
+	.long	0
+
 	/* Cleared direction flag is of no problem with any current
 	   payload and makes this implementation easier.  */
 	cld
diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c
--- a/grub-core/loader/i386/pc/freedos.c
+++ b/grub-core/loader/i386/pc/freedos.c
@@ -32,6 +32,7 @@
 #include <grub/video.h>
 #include <grub/mm.h>
 #include <grub/cpu/relocator.h>
+#include <grub/machine/chainloader.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -40,8 +41,23 @@
 static grub_uint32_t ebx = 0xffffffff;
 
 #define GRUB_FREEDOS_SEGMENT         0x60
+#define GRUB_FREEDOS_ADDR            (GRUB_FREEDOS_SEGMENT << 4)
 #define GRUB_FREEDOS_STACK_SEGMENT         0x1fe0
-#define GRUB_FREEDOS_STACK_POINTER         0x8000
+#define GRUB_FREEDOS_STACK_BPB_POINTER     0x7c00
+#define GRUB_FREEDOS_BPB_ADDR        ((GRUB_FREEDOS_STACK_SEGMENT << 4) \
+                                       + GRUB_FREEDOS_STACK_BPB_POINTER)
+
+/* FreeDOS boot.asm passes register sp as exactly this. Importantly,
+   it must point below the BPB (to avoid overwriting any of it). */
+#define GRUB_FREEDOS_STACK_POINTER         (GRUB_FREEDOS_STACK_BPB_POINTER \
+                                             - 0x60)
+
+/* In this, the additional 8192 bytes are the stack reservation; the
+   remaining parts trivially give the maximum allowed size. */
+#define GRUB_FREEDOS_MAX_SIZE        ((GRUB_FREEDOS_STACK_SEGMENT << 4) \
+                                       + GRUB_FREEDOS_STACK_POINTER \
+                                       - GRUB_FREEDOS_ADDR \
+                                       - 8192)
 
 static grub_err_t
 grub_freedos_boot (void)
@@ -49,14 +65,29 @@
   struct grub_relocator16_state state = { 
     .cs = GRUB_FREEDOS_SEGMENT,
     .ip = 0,
-    .ds = 0,
+
+    /* This is not strictly necessary for the current FreeDOS kernel
+       but improves potential compatibility with others.
+       There is no harm in setting this. */
+    .ds = GRUB_FREEDOS_STACK_SEGMENT,
     .es = 0,
     .fs = 0,
     .gs = 0,
     .ss = GRUB_FREEDOS_STACK_SEGMENT,
     .sp = GRUB_FREEDOS_STACK_POINTER,
+    .ebp = GRUB_FREEDOS_STACK_BPB_POINTER,
     .ebx = ebx,
-    .edx = 0,
+
+    /* This is not strictly necessary for the current FreeDOS kernel
+       but is crucial for potential compatibility with the load
+       protocols of other DOS-like kernels and loaders (including
+       the older FreeDOS kernel releases called DOS-C).
+       (Among those, FreeDOS's new load protocol must be considered
+       a special case in that it doesn't require register dl to pass
+       the unit number. Incidentally, the current FreeDOS boot.asm
+       does pass it in both registers.)
+       There is no harm in setting this. */
+    .edx = ebx,
     .a20 = 1
   };
   grub_video_set_mode ("text", 0, 0);
@@ -79,8 +110,9 @@
 {
   grub_file_t file = 0;
   grub_err_t err;
-  void *kernelsys;
+  void *bs, *kernelsys;
   grub_size_t kernelsyssize;
+  grub_device_t dev;
 
   if (argc == 0)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -95,12 +127,52 @@
   if (! file)
     goto fail;
 
+  {
+    grub_relocator_chunk_t ch;
+    err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_BPB_ADDR,
+					   GRUB_DISK_SECTOR_SIZE);
+    if (err)
+      goto fail;
+    bs = get_virtual_current_address (ch);
+  }
+
   ebx = grub_get_root_biosnumber ();
+  dev = grub_device_open (0);
+
+  if (dev && dev->disk)
+    {
+      err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs);
+      if (err)
+	{
+	  grub_device_close (dev);
+	  goto fail;
+	}
+      grub_chainloader_patch_bpb (bs, dev, ebx);
+    }
+
+  if (dev)
+    grub_device_close (dev);
 
   kernelsyssize = grub_file_size (file);
+
+  /* This check could be considered optional, but it provides a more
+     specific error message than grub_relocator_alloc_chunk_addr would,
+     and additionally it insures that a little is set aside for the
+     initial stack as well.
+     Quirkily, because of its size constraints FreeDOS's original loader
+     doesn't perform such a check at all (and crashes instead). The file
+     size limit is documented though. */
+  if (kernelsyssize > GRUB_FREEDOS_MAX_SIZE)
+    {
+      grub_error (GRUB_ERR_BAD_OS,
+		  "file `%s' is too large for a valid"
+		  " FreeDOS kernel.sys", argv[0]);
+      goto fail;
+    }
+
   {
     grub_relocator_chunk_t ch;
-    err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_SEGMENT << 4,
+    err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_FREEDOS_ADDR,
 					   kernelsyssize);
     if (err)
       goto fail;
diff --git a/include/grub/i386/relocator.h b/include/grub/i386/relocator.h
--- a/include/grub/i386/relocator.h
+++ b/include/grub/i386/relocator.h
@@ -49,6 +49,7 @@
   grub_uint32_t ebx;
   grub_uint32_t edx;
   grub_uint32_t esi;
+  grub_uint32_t ebp;
   int a20;
 };
 

  reply	other threads:[~2012-07-08  8:28 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-30  5:43 [PATCH] Improve FreeDOS direct loading support compatibility C. Masloch
2012-07-07 12:23 ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-07-08  8:28   ` C. Masloch [this message]
2012-09-09 19:49     ` Vladimir 'φ-coder/phcoder' Serbinenko
2012-09-09 21:37       ` C. Masloch
2013-01-27 15:08     ` Vladimir 'φ-coder/phcoder' Serbinenko

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=op.wg4chy1a6p67p9@isor \
    --to=pushbx@38.de \
    --cc=grub-devel@gnu.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 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.