Attached is a patch to fix the issue with jump instruction and boot code is corrupted with random bytes after fat is resized.
Thanks goes to Tom Yan, Dirk Eberhardt, and others who reported the problem and provided additional details. This detailed information helped with my understanding of the issue. The portion of this email after my signature delves further into the problem investigation and solution. Regards, Curtis Gedak PROBLEM ------- Windows does not recognize FAT32 after resizing with utilities (for example GParted) that use parted-3.2 libraries. CONFIRMATION ------------ Steps to confirm are: 1) Create a single FAT32 partition (e.g. 500 MiB) on a device such as a USB drive. When I created FAT32 partition using GParted the boot sector started with: $ sudo hexdump -n 7k -C /dev/sda1 00000000 eb 58 90 6d 6b 66 73 |.X.mkfs| 00000007 $ 2) Use GParted linked with parted-3.2 libraries to shrink the FAT32 partition (e.g. 450 MiB). After FAT32 resizing using GParted the boot sector started with: $ sudo hexdump -n 7k -C /dev/sda1 00000000 d0 02 30 4d 53 57 49 |..0MSWI| 00000007 $ The important distinction is that the first three hexadecimal values were randomly changed. These values represent the "boot jump" code and Windows requires these values to be correctly set. 3) Try to use the FAT32 partition with Windows (e.g. insert USB drive in Windows computer). The FAT32 file system is not recognized. Regarding boot_jump (and system_id) see: http://git.savannah.gnu.org/cgit/parted.git/tree/doc/FAT?id=v3.2#n176 If the libraries from parted 3.1, or versions 2.4 and earlier are used, then the resized FAT32 partition is recognized by Windows. INVESTIGATION ------------- The problem with Windows FAT32 recognition was introduced with: Fix filesystem detection on non 512 byte sectors 80678bdd957cf49a9ccfc8b88ba3fb8b4c63fc12 The cause of the problem is that when the parted library is resizing FAT32, there is one too many boot_sector memory allocations. The calling structure is as follows: fat_resize (...) { ... ctx = create_resize_context (...); # Allocates new boot_sector # memory and copies content # from old boot sector ... fat_boot_sector_generate (...) # Allocates new boot_sector # memory AGAIN! # Copied content lost! fat_boot_sector_write (...) ... } SOLUTION -------- Remove new boot sector memory allocation from fat_boot_sector_generate(...). The function fat_boot_sector_generate(...) is also called from fat_create(...). Note that access to fat_create(...) via ped_file_system_create(...) is no longer possible since parted-3.0 because all file system operations were removed. See: http://git.savannah.gnu.org/cgit/parted.git/tree/NEWS?id=v3.0 In parted-3.1, access to fat_create(...) via ped_file_system_create(...) was not re-introduced. See: http://git.savannah.gnu.org/cgit/parted.git/tree/NEWS?id=v3.1 Although fat_create(...) in inaccessible, I thought it best to move the new boot_sector memory allocation to where it is needed in fat_boot_sector_set_boot_code(...). That way the code should still work if it is ever re-instated. REFERENCES ---------- GNU bug report logs - #22266: [libparted] jump instruction and boot code is corrupted with random bytes after fat is resized http://debbugs.gnu.org/cgi/bugreport.cgi?bug=22266 GNU bug report logs - #22710: libparted 3.2 fat32 bootsector incompatible w. windows http://debbugs.gnu.org/cgi/bugreport.cgi?bug=22710 GParted Bug Report: Bug 759916 - fat(32) resizing generates boot sector(s) with invalid jump instruction and pseudo-random boot code https://bugzilla.gnome.org/show_bug.cgi?id=759916 GParted Forum: Vista/XP don't accept a shrinked Fat32 partition (USB-stick) http://gparted-forum.surf4.info/viewtopic.php?id=17318
>From d9a424a6fd922f5275183ea96e911af9abb9b745 Mon Sep 17 00:00:00 2001 From: Curtis Gedak <ged...@gmail.com> Date: Sun, 10 Apr 2016 11:38:41 -0600 Subject: [PATCH] lib-fs-resize: Fix recognition of FAT file system after resizing When resizing a FAT partition, an extra boot_sector memory allocation was causing the original boot_sector information to be lost. The resulting FAT file system was still recognized by GNU/Linux, but not recognized by the proprietary Windows operating system. The problem with Windows FAT32 recognition was introduced with: Fix filesystem detection on non 512 byte sectors 80678bdd957cf49a9ccfc8b88ba3fb8b4c63fc12 Fix by removing the extra boot_sector memory allocation. Note that since parted-3.0 another code path to the extra memory allocation of fat_create(...) via ped_file_system_create(...) is inaccessible. In an effort to maintain the ability to re-instate the code, add a new boot_sector memory allocation where it is needed in the alternate code path. GNU bug report logs - #22266 [libparted] jump instruction and boot code is corrupted with random bytes after fat is resized http://debbugs.gnu.org/cgi/bugreport.cgi?bug=22266 --- libparted/fs/r/fat/bootsector.c | 9 +++++++-- libparted/fs/r/fat/bootsector.h | 2 +- libparted/fs/r/fat/fat.c | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libparted/fs/r/fat/bootsector.c b/libparted/fs/r/fat/bootsector.c index 1d2b601..99d788d 100644 --- a/libparted/fs/r/fat/bootsector.c +++ b/libparted/fs/r/fat/bootsector.c @@ -281,8 +281,13 @@ fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs) #ifndef DISCOVER_ONLY int -fat_boot_sector_set_boot_code (FatBootSector* bs) +fat_boot_sector_set_boot_code (FatBootSector** bsp, const PedFileSystem* fs) { + FatSpecific* fs_info = FAT_SPECIFIC (fs); + + PED_ASSERT (bsp != NULL); + *bsp = ped_malloc (fs->geom->dev->sector_size); + FatBootSector *bs = *bsp; PED_ASSERT (bs != NULL); memset (bs, 0, 512); @@ -297,8 +302,8 @@ fat_boot_sector_generate (FatBootSector** bsp, const PedFileSystem* fs) FatSpecific* fs_info = FAT_SPECIFIC (fs); PED_ASSERT (bsp != NULL); - *bsp = ped_malloc (fs->geom->dev->sector_size); FatBootSector *bs = *bsp; + PED_ASSERT (bs != NULL); memcpy (bs->system_id, "MSWIN4.1", 8); bs->sector_size = PED_CPU_TO_LE16 (fs_info->logical_sector_size * 512); diff --git a/libparted/fs/r/fat/bootsector.h b/libparted/fs/r/fat/bootsector.h index e92842c..3f84d7f 100644 --- a/libparted/fs/r/fat/bootsector.h +++ b/libparted/fs/r/fat/bootsector.h @@ -120,7 +120,7 @@ int fat_boot_sector_read (FatBootSector** bs, const PedGeometry* geom); FatType fat_boot_sector_probe_type (const FatBootSector* bs, const PedGeometry* geom); int fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs); -int fat_boot_sector_set_boot_code (FatBootSector* bs); +int fat_boot_sector_set_boot_code (FatBootSector** bs, const PedFileSystem* fs); int fat_boot_sector_generate (FatBootSector** bs, const PedFileSystem* fs); int fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs); diff --git a/libparted/fs/r/fat/fat.c b/libparted/fs/r/fat/fat.c index 4ecf5c5..444668d 100644 --- a/libparted/fs/r/fat/fat.c +++ b/libparted/fs/r/fat/fat.c @@ -310,7 +310,7 @@ fat_create (PedGeometry* geom, FatType fat_type, PedTimer* timer) fs_info->serial_number = generate_random_uint32 (); - if (!fat_boot_sector_set_boot_code (fs_info->boot_sector)) + if (!fat_boot_sector_set_boot_code (&fs_info->boot_sector, fs)) goto error_free_buffers; if (!fat_boot_sector_generate (&fs_info->boot_sector, fs)) goto error_free_buffers; -- 1.9.1