[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[grub #38] [PATCH] "grub" command says nothing but "cannot fit into mem
From: |
kabe |
Subject: |
[grub #38] [PATCH] "grub" command says nothing but "cannot fit into memory" |
Date: |
Tue, 04 Feb 2003 19:42:52 +0900 |
Reporter: address@hidden
Summary: [PATCH] "grub" command says nothing but "cannot fit into memory"
Version: 0.93
Type: software bug
Message:
"grub" command (one invoked from commandline, not the bootloader)
says nothing but ERR_WONT_FIT.
This turns out to be mbi struct incorrectly initialized to
mbi.mem_lower = mbi.mem_upper = 0,
which in turn cuz the code assumes the
struct mmar_desc/AddrRangeDesc is packed.
gcc 2.95.2 && 2.95.3 both aligns these struct members to 8.
(Probably of the "long long" needed to be aligned to 8)
Platform: QNX 6.2
Compiler: gcc 2.95.3
If the struct was padded to 8 bytes, the second struct member
will be at offset 8, not offset 4,
as common.c:init_bios_info() et al assumes. (comment inserted in patch)
mb_info.h:
struct AddrRangeDesc
{
unsigned long size; /*offset 0*/
unsigned long long BaseAddr; /*code assumes 4, actually 8*/
...
}
Trapping at above location and examining the
SECOND instance of AddrRangeSpec, i.e
((struct AddrRangeSpec*)mbi.mmap_addr)[1] will reveal weird things assigned.
Now the patch below is simply ((packed)); I'm not a AT BIOS guru
so the "correctness" of it is delegated to the maintainer.
Instead of hardcoding +4, you could use
offsetof(struct AddrRangeDesc, BaseAddr) if the
struct don't have to be packed.
sizeof() can't be used as it'll be always 4.
*note: offsetof() is ANSI and glibc, but not necessarily portable.
Dunno why this was working for other OS.
patch:
Index: stage2/common.c
===================================================================
RCS file: /root6.1/CVSroot/grub/stage2/common.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- stage2/common.c 2003/01/31 04:41:28 1.1
+++ stage2/common.c 2003/01/31 04:50:58 1.2
@@ -185,6 +185,7 @@
if (! *((unsigned long *) addr))
break;
+ /*XXX should be "+ offsetof(struct mmar_desc, addr)"; can be +8
if padded to 8 bytes */
mbi.mmap_length += *((unsigned long *) addr) + 4;
addr += *((unsigned long *) addr) + 4;
}
Index: stage2/mb_info.h
===================================================================
RCS file: /root6.1/CVSroot/grub/stage2/mb_info.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- stage2/mb_info.h 2003/01/31 04:41:27 1.1
+++ stage2/mb_info.h 2003/01/31 04:50:58 1.2
@@ -50,7 +50,7 @@
unsigned long Type;
/* unspecified optional padding... */
-};
+} __attribute__ ((packed)) /* should be in sync with struct mmar_desc */;
/* usable memory "Type", all others are reserved. */
#define MB_ARD_MEMORY 1
Index: stage2/shared.h
===================================================================
RCS file: /root6.1/CVSroot/grub/stage2/shared.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- stage2/shared.h 2003/01/31 04:41:27 1.1
+++ stage2/shared.h 2003/01/31 04:50:59 1.2
@@ -412,7 +412,7 @@
unsigned long long addr; /* Base address. */
unsigned long long length; /* Length in bytes. */
unsigned long type; /* Type of address range. */
-};
+} __attribute__ ((packed)) /* don't pad desc_len to 8bytes; there's too many
+4s already */;
/* VBE controller information. */
struct vbe_controller
----
Please send followups to <address@hidden>.
- [grub #38] [PATCH] "grub" command says nothing but "cannot fit into memory",
kabe <=