Re: [PATCH] docs: Update for stopping small mbr gap support

2020-03-05 Thread C. Masloch
Two small suggestions inlined in the quoted part.

Regards,
ecm


On at 2020-03-05 15:38 +0100, Daniel Kiper wrote:
> On Thu, Mar 05, 2020 at 06:40:01PM +0800, Michael Chang wrote:
>> Further to the discussion about disabling btrfs zstd support for
>> i386-pc[1], this paragraph in manual about mbr gap size doesn't seem to
>> hold true any longer.
>>
>> "You must ensure that the first partition starts at least 31 KiB (63
>> sectors) from the start of the disk"
>>
>> As in many occasions we inevitablely have to provide core image size
>> that goes beyond 31 KiB, this statement becomes a true liability as
>> people would be misguided and think it is still fine to use small MBR
>> gap, that has always been a headache in distribution's upgrade path as
>> growing new feature would render the size requirement bigger but no way
>> for the user to relocate their partitions.
> 
> Could you split this paragraph into a few sentences? Now it does not
> read very well...
> 
>> The patch tries to correct the paragraph with a more practical size that
>> works for grub and also for modern computer systems in general.
>>
>> [1] https://lists.gnu.org/archive/html/grub-devel/2019-11/msg00025.html
>>
>> Signed-off-by: Michael Chang 
>> ---
>>  docs/grub.texi | 20 ++--
>>  1 file changed, 14 insertions(+), 6 deletions(-)
>>
>> diff --git a/docs/grub.texi b/docs/grub.texi
>> index 83979af38..651468268 100644
>> --- a/docs/grub.texi
>> +++ b/docs/grub.texi
>> @@ -845,12 +845,20 @@ only be used if the @file{/boot} filesystem is on the 
>> same disk that the
>>  BIOS boots from, so that GRUB does not have to rely on guessing BIOS drive
>>  numbers.
>>
>> -The GRUB development team generally recommends embedding GRUB before the
>> -first partition, unless you have special requirements.  You must ensure that
>> -the first partition starts at least 31 KiB (63 sectors) from the start of
>> -the disk; on modern disks, it is often a performance advantage to align
>> -partitions on larger boundaries anyway, so the first partition might start 1
>> -MiB from the start of the disk.
>> +The GRUB development team generally recommends embedding GRUB before the 
>> first
>> +partition, unless you have special requirements. You must ensure that the 
>> first
>> +partition starts at least 1 MiB from the start of the disk; on modern 
>> disks, it
> 
> s/; on modern disks, it/. Additionally, on modern disks it/
> 
>> +is often a performance advantage to align partitions on larger boundaries 
>> and 1
>> +MiB is the least common multiple of many used alignment sizes. For SSD, it
> 
> s/For SSD, it/E.g. SSD, it/
> 
>> +became crucial to have the partition correctly aligned to avoid excessive
>> +read-modify-write cycles and thus modern tools set to use 1 MiB as a 
>> stardard
>> +practice.

s/stardard/standard

>> +
>> +In case legacy systems that cannot boot if first partition not on the 
>> cylinder
> 
> s/In case legacy/In case of legacy/
> s/partition not/partition is not/
> 
>> +boundary, the fallback blocklist install method should remain working for 
>> them
>> +if the core image growing too much someday. Here we just can't advertise 
>> that

s/growing/grows/

>> +31 KiB (63 sectors) is a sensible size any longer as that would pose great
>> +constraint to include new features as time goes by.
> 
> Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH] Fix FreeDOS command booting large files (near or above 64 KiB)

2019-12-20 Thread C. Masloch
While testing the 86-DOS lDebug [1] booting from GRUB2, newer versions of the
debugger would fail to load when booted using GRUB's freedos command. The
behaviour observed in a qemu i386 machine was that the ROM-BIOS's boot load
would start anew, instead of loading the selected debugger as kernel.

It came to light that there was a size limit: Kernel files that were 58880
bytes (E600h) long or shorter succeeded to boot, while files that were 64000
bytes or longer failed in the manner described.

Eventually it turned out that the relocator16 stub succeeded whenever it was
placed completely within the first 64 KiB of the Low Memory Area. The chunk
for the relocator is allocated with a minimum address of 0x8010 and a maximum
address just below 0xA [2]. That means if the kernel is, for instance,
E600h bytes long, then the kernel will be allocated memory starting at 00600h
(the fixed FreeDOS kernel load address) up to E600h + 00600h = 0EC00h, which
leaves 1400h (5120) bytes for the relocator to stay in the first 64 KiB.
If the kernel is 64000 bytes (FA00h) long, then the relocator must go to
FA00h + 00600h = 1h at least which is outside the first 64 KiB.

The problem is that the relocator16 initialises the DS register with a
"pseudo real mode" descriptor, which is defined with a segment limit of
64 KiB and a segment base of zero. After that, the relocator addressed
parts of itself (implicitly) using the DS register, with an offset from
ESI, which holds the linear address of the relocator's base [3]. With the
larger kernel files this would lead to accessing data beyond the 64 KiB
segment limit, presumably leading to a fault and perhaps a subsequent
triple-fault or such.

This patch fixes the relocator to set the segment base of the descriptors
to the base address of the relocator; then, the subsequent accesses to
the relocator's variables are done without the ESI register as an index.
This does not interfere with the relocator's or its target's normal
operation; the segment limits are still loaded with 64 KiB and all the
segment bases are subsequently reset by the relocator anyway.

Current versions of the debugger to test are uploaded to [4]. The file
ldebugnh.com (LZ4-compressed and built with -D_EXTHELP=0) at 58368 bytes
loads successfully, whereas ldebug.com at 64000 bytes fails. Loading one
of these files requires setting root to a FAT FS partition and using the
freedos command to specify the file as kernel:

set root='(hd0,msdos1)'
freedos /ldebug.com
boot

Booting the file using the multiboot command (which uses a WIP entrypoint
of the debugger) works, as it does not use GRUB's relocator16 but instead
includes a loader in the kernel itself, which drops it back to 86 Mode.

[1]: https://hg.ulukai.org/ecm/ldebug
[2]: 
http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/lib/i386/relocator.c?id=495781f5ed1b48bf27f16c53940d6700c181c74c#n127
[3]: 
http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/lib/i386/relocator16.S?id=495781f5ed1b48bf27f16c53940d6700c181c74c#n97
[4]: https://ulukai.org/ecm/lDebug-5479a7988d21-nohelp.zip

Signed-off-by: C. Masloch 
---
 grub-core/lib/i386/relocator16.S | 26 +++---
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S
index 371a2ed69..e9238119b 100644
--- a/grub-core/lib/i386/relocator16.S
+++ b/grub-core/lib/i386/relocator16.S
@@ -38,15 +38,21 @@ VARIABLE(grub_relocator16_start)
 #ifdef __APPLE__
LOCAL(cs_base_bytes12_offset) = LOCAL (cs_base_bytes12) - LOCAL (base)
LOCAL(cs_base_byte3_offset) = LOCAL (cs_base_byte3) - LOCAL (base)
+   LOCAL(ds_base_bytes12_offset) = LOCAL (ds_base_bytes12) - LOCAL (base)
+   LOCAL(ds_base_byte3_offset) = LOCAL (ds_base_byte3) - LOCAL (base)
movl%esi, %eax
movw%ax, (LOCAL(cs_base_bytes12_offset)) (RSI, 1)
+   movw%ax, (LOCAL(ds_base_bytes12_offset)) (RSI, 1)
shrl$16, %eax
movb%al, (LOCAL (cs_base_byte3_offset)) (RSI, 1)
+   movb%al, (LOCAL (ds_base_byte3_offset)) (RSI, 1)
 #else
movl%esi, %eax
movw%ax, (LOCAL (cs_base_bytes12) - LOCAL (base)) (RSI, 1)
+   movw%ax, (LOCAL (ds_base_bytes12) - LOCAL (base)) (RSI, 1)
shrl$16, %eax
movb%al, (LOCAL (cs_base_byte3) - LOCAL (base)) (RSI, 1)
+   movb%al, (LOCAL (ds_base_byte3) - LOCAL (base)) (RSI, 1)
 #endif
 
RELOAD_GDT
@@ -88,15 +94,15 @@ VARIABLE(grub_relocator16_start)
LOCAL(segment_offset) = LOCAL (segment) - LOCAL (base)
LOCAL(idt_offset) = LOCAL(relocator16_idt) - LOCAL (base)
LOCAL(cont2_offset) = LOCAL (cont2) - LOCAL(base)
-   movw%ax, LOCAL(segment_offset) (%esi, 1)
-   lidt LOCAL(idt_offset) (%esi, 1)
+   movw%ax, (LOCAL(segment_offset))
+   lidt (LOCAL(idt_offset))

/* jump to a 16 bit segment */
ljmp$PSEUDO_REAL_CSEG, $(LOCAL(co

Re: [PATCH] chainloader: patch in BPB's sectors_per_track and num_heads

2018-03-03 Thread C. Masloch
Hello,

Was this overlooked?

I think I should check whether dev->disk->data actually is a (struct
grub_biosdisk_data *) but I don't know how!

Regards,
ecm


On at 2018-02-01 15:51 +01:00, C. Masloch wrote:
> 
> These fields must reflect the ROM-BIOS's geometry for CHS-based
> loaders to correctly load their next stage. Most loaders do not
> query the ROM-BIOS (Int13.08), relying on the BPB fields to hold
> the correct values already.
> 
> Tested with lDebug booted in qemu via grub2's
> FreeDOS direct loading support, refer to
> https://bitbucket.org/ecm/ldosboot + https://bitbucket.org/ecm/ldebug
> (For this test, lDebug's iniload.asm must be assembled with
> -D_QUERY_GEOMETRY=0 to leave the BPB values provided by grub.)
> 
> Signed-off-by: C. Masloch <pus...@38.de>
> ---
>  grub-core/loader/i386/pc/chainloader.c | 20 ++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/grub-core/loader/i386/pc/chainloader.c
> b/grub-core/loader/i386/pc/chainloader.c
> index 18220b7aa..ef3a322b7 100644
> --- a/grub-core/loader/i386/pc/chainloader.c
> +++ b/grub-core/loader/i386/pc/chainloader.c
> @@ -19,6 +19,7 @@
> 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -86,9 +87,16 @@ grub_chainloader_unload (void)
>  void
>  grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
>  {
> -  grub_uint32_t part_start = 0;
> +  grub_uint32_t part_start = 0, heads = 0, sectors = 0;
>if (dev && dev->disk)
> -part_start = grub_partition_get_start (dev->disk->partition);
> +{
> +  part_start = grub_partition_get_start (dev->disk->partition);
> +  if (dev->disk->data)
> +{
> +  heads = ((struct grub_biosdisk_data *)(dev->disk->data))->heads;
> +  sectors = ((struct grub_biosdisk_data
> *)(dev->disk->data))->sectors;
> +}
> +}
>if (grub_memcmp ((char *) &((struct grub_ntfs_bpb *) bs)->oem_name,
>  "NTFS", 4) == 0)
>  {
> @@ -127,12 +135,20 @@ grub_chainloader_patch_bpb (void *bs,
> grub_device_t dev, grub_uint8_t dl)
>   {
> bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
> bpb->version_specific.fat12_or_fat16.num_ph_drive = dl;
> +  if (sectors)
> +bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
> +  if (heads)
> +bpb->num_heads = grub_cpu_to_le16 (heads);
> return;
>   }
>if (bpb->version_specific.fat32.sectors_per_fat_32)
>   {
> bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
> bpb->version_specific.fat32.num_ph_drive = dl;
> +  if (sectors)
> +bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
> +  if (heads)
> +bpb->num_heads = grub_cpu_to_le16 (heads);
> return;
>   }
>break;
> 


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v2] chainloader: Fix wrong break condition (must be AND not, OR)

2018-02-24 Thread C. Masloch
On at 2018-02-23 23:05 +01:00, Daniel Kiper wrote:
> Applied!
> 
> FYI, this is last time when I sent commit confirmation.
> If I send one in the future then this will be rather
> exception than rule. So, if you receive my reviewed-by
> and patch is not committed in a week or two then it means
> that it fallen into abyss and you have to ping me.
> 
> Have a nice weekend,
> 
> Daniel

Thanks, I'll keep that in mind.

Regards,
ecm

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v2] chainloader: Fix wrong break condition (must be AND not, OR)

2018-02-19 Thread C. Masloch
The definition of bpb's num_total_sectors_16 and num_total_sectors_32
is that either the 16-bit field is non-zero and is used (in which case
eg mkfs.fat sets the 32-bit field to zero), or it is zero and the
32-bit field is used. Therefore, a BPB is invalid only if *both*
fields are zero; having one field as zero and the other as non-zero is
the case to be expected. (Indeed, according to Microsoft's specification
one of the fields *must* be zero, and the other non-zero.)

This affects all users of grub_chainloader_patch_bpb which are in
chainloader.c, freedos.c, and ntldr.c

Some descriptions of the semantics of these two fields:

https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html

> The old 2-byte fields "total number of sectors" and "number of
> sectors per FAT" are now zero; this information is now found in
> the new 4-byte fields.

(Here given in the FAT32 EBPB section but the total sectors 16/32 bit
fields semantic is true of FAT12 and FAT16 too.)

https://wiki.osdev.org/FAT#BPB_.28BIOS_Parameter_Block.29

> 19 | 2 | The total sectors in the logical volume. If this value is 0,
> it means there are more than 65535 sectors in the volume, and the actual
> count is stored in "Large Sectors (bytes 32-35).

> 32 | 4 | Large amount of sector on media. This field is set if there
> are more than 65535 sectors in the volume.

(Doesn't specify what the "large" field is set to when unused, but as
mentioned mkfs.fat sets it to zero then.)

https://technet.microsoft.com/en-us/library/cc976796.aspx

> 0x13 | WORD | 0x |
> Small Sectors . The number of sectors on the volume represented in 16
> bits (< 65,536). For volumes larger than 65,536 sectors, this field
> has a value of zero and the Large Sectors field is used instead.

> 0x20 | DWORD | 0x01F03E00 |
> Large Sectors . If the value of the Small Sectors field is zero, this
> field contains the total number of sectors in the FAT16 volume. If the
> value of the Small Sectors field is not zero, the value of this field
> is zero.

https://staff.washington.edu/dittrich/misc/fatgen103.pdf page 10

> BPB_TotSec16 | 19 | 2 |
> This field is the old 16-bit total count of sectors on the volume.
> This count includes the count of all sectors in all four regions of the
> volume. This field can be 0; if it is 0, then BPB_TotSec32 must be
> non-zero. For FAT32 volumes, this field must be 0. For FAT12 and
> FAT16 volumes, this field contains the sector count, and
> BPB_TotSec32 is 0 if the total sector count “fits” (is less than
> 0x1).

> BPB_TotSec32 | 32 | 4 |
> This field is the new 32-bit total count of sectors on the volume.
> This count includes the count of all sectors in all four regions of the
> volume. This field can be 0; if it is 0, then BPB_TotSec16 must be
> non-zero. For FAT32 volumes, this field must be non-zero. For
> FAT12/FAT16 volumes, this field contains the sector count if
> BPB_TotSec16 is 0 (count is greater than or equal to 0x1).

(This specifies that an unused BPB_TotSec32 field is set to zero.)

Tested with lDebug booted in qemu via grub2's
FreeDOS direct loading support, refer to
https://bitbucket.org/ecm/ldosboot + https://bitbucket.org/ecm/ldebug

Signed-off-by: C. Masloch <pus...@38.de>
---
 grub-core/loader/i386/pc/chainloader.c |  2 +-
 include/grub/fat.h | 17 ++---
 2 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/grub-core/loader/i386/pc/chainloader.c 
b/grub-core/loader/i386/pc/chainloader.c
index c79c4fe0f..18220b7aa 100644
--- a/grub-core/loader/i386/pc/chainloader.c
+++ b/grub-core/loader/i386/pc/chainloader.c
@@ -117,7 +117,7 @@ grub_chainloader_patch_bpb (void *bs, grub_device_t dev, 
grub_uint8_t dl)
 
   if (bpb->num_reserved_sectors == 0)
break;
-  if (bpb->num_total_sectors_16 == 0 || bpb->num_total_sectors_32 == 0)
+  if (bpb->num_total_sectors_16 == 0 && bpb->num_total_sectors_32 == 0)
break;
 
   if (bpb->num_fats == 0)
diff --git a/include/grub/fat.h b/include/grub/fat.h
index 4a5aab793..8d7e4a1e5 100644
--- a/include/grub/fat.h
+++ b/include/grub/fat.h
@@ -28,20 +28,15 @@ struct grub_fat_bpb
   grub_uint16_t bytes_per_sector;
   grub_uint8_t sectors_per_cluster;
   grub_uint16_t num_reserved_sectors;
-  grub_uint8_t num_fats;
-  /* 0x10 */
+  grub_uint8_t num_fats;   /* 0x10 */
   grub_uint16_t num_root_entries;
   grub_uint16_t num_total_sectors_16;
-  grub_uint8_t media;
-  /*0 x15 */
+  grub_uint8_t media;  /* 0x15 */
   grub_uint16_t sectors_per_fat_16;
-  grub_uint16_t sectors_per_track;
-  /*0 x19 */
-  grub_uint16_t num_heads;
-  /*0 x1b */
-  grub_uint32_t num_hidden_sectors;
-  /* 0x1f */
-  grub_uint32_t num_total_sectors_32;
+  grub_uint16_t sectors_per_track; /* 0x18 */
+  grub_uint16_t num_he

Re: [PATCH] chainloader: Fix wrong break condition (must be AND not OR)

2018-02-19 Thread C. Masloch
On at 2018-02-06 16:41 +01:00, Daniel Kiper wrote:
>>> I am happy that you fix that issue but
>>>   https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#BPB331_OFS_15h
>>> shows that life is more complicated.
>>>
>>> Could you take that into account?
>>
>> MS-DOS 3.20 and 3.30 BPBs aren't supported anyway. The special case for
> 
> Aren't supported by whom? GRUB2?

Yes. If you look at include/grub/fat.h, the format is that which is
specified as "DOS 3.31" BPB by the Wikipedia article (plus FAT32 EBPB).
(Note that some of the offsets in the comments of struct grub_fat_bpb
are wrong. I'll change these in the patch v2.)

>> using a partition table entry's partition length field isn't applicable
>> here. (If it were, the function simply shouldn't check these fields.)
> 
> Please say why exactly it is not applicable here.

Because we are using these fields. If it was to be made applicable, it
should just not check the fields.

>> And this is the first I've read of that DR-DOS extension. (And again,
>> the simple solution to that one is also not to check the fields for zeros.)
>>
>>>> Tested with lDebug booted in qemu via grub2's
>>>> FreeDOS direct loading support, refer to
>>>> https://bitbucket.org/ecm/ldosboot + https://bitbucket.org/ecm/ldebug
>>>
>>> Could you put your SOB here?
>>
>> Like this?
>>
>> Signed-off-by: C. Masloch <pus...@38.de>
> 
> Yep.
> 
>> (Should I submit a PATCH v2 for this?)
> 
> Yes, please. I am happy to commit this patch if you provide
> such a nice and detailed explanation like above but with better
> formating. And please add some stuff which I asked for too.

Am about to mail the patch v2. (I found out how to make Thunderbird not
wrap long lines! mail.wrap_long_lines = false and mailnews.wraplength = 0.)

Regards,
ecm

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH] chainloader: patch in BPB's sectors_per_track and num_heads

2018-02-01 Thread C. Masloch

These fields must reflect the ROM-BIOS's geometry for CHS-based
loaders to correctly load their next stage. Most loaders do not
query the ROM-BIOS (Int13.08), relying on the BPB fields to hold
the correct values already.

Tested with lDebug booted in qemu via grub2's
FreeDOS direct loading support, refer to
https://bitbucket.org/ecm/ldosboot + https://bitbucket.org/ecm/ldebug
(For this test, lDebug's iniload.asm must be assembled with
-D_QUERY_GEOMETRY=0 to leave the BPB values provided by grub.)

Signed-off-by: C. Masloch <pus...@38.de>
---
 grub-core/loader/i386/pc/chainloader.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/grub-core/loader/i386/pc/chainloader.c
b/grub-core/loader/i386/pc/chainloader.c
index 18220b7aa..ef3a322b7 100644
--- a/grub-core/loader/i386/pc/chainloader.c
+++ b/grub-core/loader/i386/pc/chainloader.c
@@ -19,6 +19,7 @@

 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -86,9 +87,16 @@ grub_chainloader_unload (void)
 void
 grub_chainloader_patch_bpb (void *bs, grub_device_t dev, grub_uint8_t dl)
 {
-  grub_uint32_t part_start = 0;
+  grub_uint32_t part_start = 0, heads = 0, sectors = 0;
   if (dev && dev->disk)
-part_start = grub_partition_get_start (dev->disk->partition);
+{
+  part_start = grub_partition_get_start (dev->disk->partition);
+  if (dev->disk->data)
+{
+  heads = ((struct grub_biosdisk_data *)(dev->disk->data))->heads;
+  sectors = ((struct grub_biosdisk_data
*)(dev->disk->data))->sectors;
+}
+}
   if (grub_memcmp ((char *) &((struct grub_ntfs_bpb *) bs)->oem_name,
   "NTFS", 4) == 0)
 {
@@ -127,12 +135,20 @@ grub_chainloader_patch_bpb (void *bs,
grub_device_t dev, grub_uint8_t dl)
{
  bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
  bpb->version_specific.fat12_or_fat16.num_ph_drive = dl;
+  if (sectors)
+bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
+  if (heads)
+bpb->num_heads = grub_cpu_to_le16 (heads);
  return;
}
   if (bpb->version_specific.fat32.sectors_per_fat_32)
{
  bpb->num_hidden_sectors = grub_cpu_to_le32 (part_start);
  bpb->version_specific.fat32.num_ph_drive = dl;
+  if (sectors)
+bpb->sectors_per_track = grub_cpu_to_le16 (sectors);
+  if (heads)
+bpb->num_heads = grub_cpu_to_le16 (heads);
  return;
}
   break;
-- 
2.11.0

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH] chainloader: Fix wrong break condition (must be AND not OR)

2018-01-31 Thread C. Masloch
On at 2018-01-29 18:09 +01:00, Daniel Kiper wrote:
> On Sun, Jan 21, 2018 at 04:02:10PM +0100, C. Masloch wrote:
>> The definition of bpb's num_total_sectors_16 and num_total_sectors_32
>> is that either the 16-bit field is non-zero and is used (in which case
>> eg mkfs.fat sets the 32-bit field to zero), or it is zero and the
>> 32-bit field is used. Therefore, a BPB is invalid only if *both*
>> fields are zero; having one field as zero and the other as non-zero is
>> the case to be expected.
> 
> Could you provide reference to the spec which says that?

Here's a few descriptions pointing to that fact:


https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html

>  The old 2-byte fields "total number of sectors" and "number of
sectors per FAT" are now zero; this information is now found in the new
4-byte fields.

(Here given in the FAT32 EBPB section but the total sectors 16/32 bit
fields semantic is true of FAT12 and FAT16 too.)


https://wiki.osdev.org/FAT#BPB_.28BIOS_Parameter_Block.29

> 19 | 2 | The total sectors in the logical volume. If this value is 0,
it means there are more than 65535 sectors in the volume, and the actual
count is stored in "Large Sectors (bytes 32-35).

> 32 | 4 | Large amount of sector on media. This field is set if there
are more than 65535 sectors in the volume.

(Doesn't specify what the "large" field is set to when unused, but as
mentioned mkfs.fat sets it to zero then.)


https://technet.microsoft.com/en-us/library/cc976796.aspx

> 0x13 | WORD | 0x |
> Small Sectors . The number of sectors on the volume represented in 16
> bits (< 65,536). For volumes larger than 65,536 sectors, this field
> has a value of zero and the Large Sectors field is used instead.

> 0x20 | DWORD | 0x01F03E00 |
> Large Sectors . If the value of the Small Sectors field is zero, this
> field contains the total number of sectors in the FAT16 volume. If the
> value of the Small Sectors field is not zero, the value of this field
> is zero.


https://staff.washington.edu/dittrich/misc/fatgen103.pdf page 10

> BPB_TotSec16 | 19 | 2 |
> This field is the old 16-bit total count of sectors on the volume.
> This count includes the count of all sectors in all four regions of the
> volume. This field can be 0; if it is 0, then BPB_TotSec32 must be
> non-zero. For FAT32 volumes, this field must be 0. For FAT12 and
> FAT16 volumes, this field contains the sector count, and
> BPB_TotSec32 is 0 if the total sector count “fits” (is less than
> 0x1).

> BPB_TotSec32 | 32 | 4 |
> This field is the new 32-bit total count of sectors on the volume.
> This count includes the count of all sectors in all four regions of the
> volume. This field can be 0; if it is 0, then BPB_TotSec16 must be
> non-zero. For FAT32 volumes, this field must be non-zero. For
> FAT12/FAT16 volumes, this field contains the sector count if
> BPB_TotSec16 is 0 (count is greater than or equal to 0x1).

(This specifies that an unused BPB_TotSec32 field is set to zero.)


>> This affects all users of grub_chainloader_patch_bpb which are in
>> chainloader.c, freedos.c, and ntldr.c
> 
> I am happy that you fix that issue but
>   https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system#BPB331_OFS_15h
> shows that life is more complicated.
>
> Could you take that into account?

MS-DOS 3.20 and 3.30 BPBs aren't supported anyway. The special case for
using a partition table entry's partition length field isn't applicable
here. (If it were, the function simply shouldn't check these fields.)
And this is the first I've read of that DR-DOS extension. (And again,
the simple solution to that one is also not to check the fields for zeros.)

>> Tested with lDebug booted in qemu via grub2's
>> FreeDOS direct loading support, refer to
>> https://bitbucket.org/ecm/ldosboot + https://bitbucket.org/ecm/ldebug
> 
> Could you put your SOB here?

Like this?

Signed-off-by: C. Masloch <pus...@38.de>

(Should I submit a PATCH v2 for this?)

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH] chainloader: Fix wrong break condition (must be AND not OR)

2018-01-21 Thread C. Masloch
The definition of bpb's num_total_sectors_16 and num_total_sectors_32
is that either the 16-bit field is non-zero and is used (in which case
eg mkfs.fat sets the 32-bit field to zero), or it is zero and the
32-bit field is used. Therefore, a BPB is invalid only if *both*
fields are zero; having one field as zero and the other as non-zero is
the case to be expected.

This affects all users of grub_chainloader_patch_bpb which are in
chainloader.c, freedos.c, and ntldr.c

Tested with lDebug booted in qemu via grub2's
FreeDOS direct loading support, refer to
https://bitbucket.org/ecm/ldosboot + https://bitbucket.org/ecm/ldebug
---
 grub-core/loader/i386/pc/chainloader.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/loader/i386/pc/chainloader.c
b/grub-core/loader/i386/pc/chainloader.c
index c79c4fe0f..18220b7aa 100644
--- a/grub-core/loader/i386/pc/chainloader.c
+++ b/grub-core/loader/i386/pc/chainloader.c
@@ -117,7 +117,7 @@ grub_chainloader_patch_bpb (void *bs, grub_device_t
dev, grub_uint8_t dl)

   if (bpb->num_reserved_sectors == 0)
break;
-  if (bpb->num_total_sectors_16 == 0 || bpb->num_total_sectors_32 == 0)
+  if (bpb->num_total_sectors_16 == 0 && bpb->num_total_sectors_32 == 0)
break;

   if (bpb->num_fats == 0)
-- 
2.11.0

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH] Improve FreeDOS direct loading support compatibility.

2012-09-09 Thread C. Masloch

On 2012-09-09 21:49 +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote:


+  {
+grub_relocator_chunk_t ch;
+err = grub_relocator_alloc_chunk_addr (rel, ch,  
GRUB_FREEDOS_BPB_ADDR,

+  GRUB_DISK_SECTOR_SIZE);


I don't understand this. Shouldn't it be at 0x7c00 ?


This is intended to be at 0x27a00, not 0x7c00. GRUB_FREEDOS_BPB_ADDR  
should evaluate to 0x27a00. I'll try to explain the reasoning for this -  
if any of the following is unclear, please feel free to ask for  
clarification. Sorry that it's so verbose; I suggest you read the summary  
first if you prefer.


-

The FreeDOS kernel's original boot loader (boot/boot.asm in the kernel's  
repo) first relocates itself to linear address 2_7A00h (formed as  
segmented destination address 1FE0h:7C00h, the segmented source address  
being h:7C00h). This is an adjustment from other/earlier loaders that  
left the (boot sector) loader at (linear) 0_7C00h and thus restricted the  
next stage* to be loaded from disk to about 29 KiB, if it is to be loaded  
into contiguous space starting at a lower address (used to be 0_0700h, now  
0_0600h for current FreeDOS kernel releases). With this adjustment, the  
limit is increased to about 157 KiB.


[* Earlier DOS-C (ie FreeDOS kernel) releases loaded a subsequent IPL  
stage first, possibly motivated by this ca. 29 KiB limit as well. Current  
FreeDOS kernel releases typically directly load the whole kernel.]


In principle, GRUB could of course write the BPB anywhere up to the top of  
conventional memory (below A_h, or below an EBDA if present there)  
and incidentally raise the file size limit. (Or potentially the kernel  
could be loaded to eg 0_8000h with the BPB placed somewhere below that,  
also raising the file size limit - however 0_0600h is clearly documented  
as the canonical load address of the current protocol and the kernel might  
rely on it.)


However, various programs might assume that the FreeDOS load protocol  
places the BPB at exactly 2_7A00h (with ss:bp and ds:bp specifying  
1FE0h:7C00h). I don't know whether the current kernel itself relies on  
this. I'm aware that at least MetaBoot** does search at that particular  
(linear) address, so placing the BPB/sector there is necessary (though not  
sufficient) for it. (MetaBoot's only purpose is to reload a different  
next-stage file, hence loading it from GRUB isn't important because GRUB  
can instead directly load the desired next-stage file. I merely mentioned  
MetaBoot for its assumption that this particular position is implied by  
the load protocol.)


[** MetaBoot belongs to the MetaKern loader for FreeDOS, developed by  
FreeDOS kernel maintainer Eric Auer. It is covered by the GPL 2 with an  
additional loading exception/permission, and distributed as part of  
FreeDOS.]


In addition, arguably there is little use in raising the file size limit  
above what the original loader can work with. This differs from my  
opinion, but might be a relevant view for GRUB to consider.


-

So, summing it all up, the resulting 2_7A00h address of the BPB is to most  
closely mimic the original loader, which arrived there to partially raise  
a limit caused by that loader's size constraints (from the original 29 KiB  
limit to 157 KiB). That level of compatibility might be unnecessary (for  
the kernel itself), but apart from reproducing the original's more recent  
file size limit there is no harm in it.


Note that in GRUB's ntldr.c, the BPB is written at 0_7C00h and no  
equivalent file size limit exists because the next stage (NTLDR) file is  
loaded starting at a higher address, 2_h.



Do you plan to contribute more? If so I'd prefer to make you sign a
copyright assignment, otherwise this patch can go in, once it's clear
with addresses.


I could gladly sign an assignment, however I don't yet plan to contribute  
more.


Regards,
Chris Masloch

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH] Improve FreeDOS direct loading support compatibility.

2012-07-08 Thread C. Masloch


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

improve-freedos-compatibility-2.diff
Description: Binary data
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH] Improve FreeDOS direct loading support compatibility.

2012-06-29 Thread C. Masloch

Hello,

A bit about me first; feel free to skip this paragraph. I know 86 assembly  
language well and have been involved in FreeDOS kernel development. On the  
freedos-user list I read that GRUB 2.00 added FreeDOS direct loading  
support. I have reviewed GRUB's implementation of the FreeDOS load  
protocol.


The attached patch improves compatibility to the FreeDOS kernel and its  
original loader as well as potential compatibility to other DOS-like  
kernels and loaders. In particular, some requirements of the current  
EDR-DOS load protocol are implemented by this as well (though possibly not  
all of them) without harming the loading of FreeDOS kernels.


Regards,
Chris Masloch

improve-freedos-compatibility.diff
Description: Binary data
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel