From e90eaa4abc0d7070ea76737db12d9628d1c57ea2 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 30 Dec 2014 19:46:13 +0000 Subject: [PATCH] [grub] add GRUB 2.0 versioning and enable external core.img download * Closes #419 * Also updated Bled to latest --- res/grub/grub_version.h | 5 +++ res/grub2/grub2_version.h | 5 +++ res/localization/rufus.loc | 9 ++++++ src/bled/bled.c | 5 +++ src/bled/libbb.h | 5 +-- src/format.c | 25 ++++++++++----- src/iso.c | 40 ++++++++++++++++++++++++ src/msapi_utf8.h | 2 +- src/rufus.c | 63 ++++++++++++++++++++++++++++++++++++++ src/rufus.h | 1 + src/rufus.rc | 16 +++++----- 11 files changed, 158 insertions(+), 18 deletions(-) create mode 100644 res/grub/grub_version.h create mode 100644 res/grub2/grub2_version.h diff --git a/res/grub/grub_version.h b/res/grub/grub_version.h new file mode 100644 index 00000000..92a32673 --- /dev/null +++ b/res/grub/grub_version.h @@ -0,0 +1,5 @@ +/* + * This file contains the version string of the Grub4Dos 2.x binary embedded in Rufus. + * Should be the same as the grub4dos_version file in the source Grub4Dos was compiled from. + */ +#define GRUB4DOS_VERSION "0.4.5c" diff --git a/res/grub2/grub2_version.h b/res/grub2/grub2_version.h new file mode 100644 index 00000000..7b069ed0 --- /dev/null +++ b/res/grub2/grub2_version.h @@ -0,0 +1,5 @@ +/* + * This file contains the version string of the GRUB 2.x binary embedded in Rufus. + * Should be the same as GRUB's PACKAGE_VERSION in config.h. + */ +#define GRUB2_PACKAGE_VERSION "2.02~beta2" diff --git a/res/localization/rufus.loc b/res/localization/rufus.loc index 721ad308..0138952c 100644 --- a/res/localization/rufus.loc +++ b/res/localization/rufus.loc @@ -305,6 +305,15 @@ t MSG_114 "This image uses Syslinux %s%s but this application only includes the "Note: The files will be downloaded in the current application directory and will be reused " "automatically if present.\n" t MSG_115 "Download required" +t MSG_116 "This image uses Grub %s but the application only includes the installation files for " + "Grub %s.\n\nAs different versions of Grub may not be compatible with one another, and it is " + "not possible to include them all, Rufus will attempt to locate a version of the Grub " + "installation file ('core.img') that matches the one from your image:\n" + "- Select 'Yes' to connect to the Internet and attempt to download it\n" + "- Select 'No' to use the embedded version regardless\n" + "- Select 'Cancel' to abort the operation\n\n" + "Note: The file will be downloaded in the current application directory and will be reused " + "automatically if present. If no match can be found, then the embedded version will be used.\n" # Tootips # Partition Scheme and Target Type t MSG_150 "Usually the safest choice. If you have an UEFI computer and want to install " diff --git a/src/bled/bled.c b/src/bled/bled.c index 66dbc067..08d70a2c 100644 --- a/src/bled/bled.c +++ b/src/bled/bled.c @@ -23,6 +23,7 @@ uint64_t bb_total_rb; printf_t bled_printf = NULL; progress_t bled_progress = NULL; static bool bled_initialized = 0; +jmp_buf bb_error_jmp; static long long int unpack_none(transformer_state_t *xstate) { @@ -72,6 +73,8 @@ int64_t bled_uncompress(const char* src, const char* dst, int type) goto err; } + if (setjmp(bb_error_jmp)) + goto err; ret = unpacker[type](&xstate); _close(xstate.src_fd); _close(xstate.dst_fd); @@ -116,6 +119,8 @@ int64_t bled_uncompress_with_handles(HANDLE hSrc, HANDLE hDst, int type) return -1; } + if (setjmp(bb_error_jmp)) + return -1; return unpacker[type](&xstate); } diff --git a/src/bled/libbb.h b/src/bled/libbb.h index 8f73266b..0cdc92bb 100644 --- a/src/bled/libbb.h +++ b/src/bled/libbb.h @@ -110,6 +110,7 @@ typedef unsigned int uid_t; extern smallint bb_got_signal; extern uint32_t *global_crc32_table; +extern jmp_buf bb_error_jmp; uint32_t* crc32_filltable(uint32_t *crc_table, int endian); uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len, uint32_t *crc32table_le); @@ -135,10 +136,11 @@ typedef struct _llist_t { extern void (*bled_printf) (const char* format, ...); extern void (*bled_progress) (const uint64_t processed_bytes); +#define xfunc_die() longjmp(bb_error_jmp, 1) #define bb_printf(...) do { if (bled_printf != NULL) bled_printf(__VA_ARGS__); \ else { printf(__VA_ARGS__); putchar('\n'); } } while(0) #define bb_error_msg bb_printf -#define bb_error_msg_and_die(...) do {bb_printf(__VA_ARGS__); return;} while(0) +#define bb_error_msg_and_die(...) do {bb_printf(__VA_ARGS__); xfunc_die();} while(0) #define bb_error_msg_and_err(...) do {bb_printf(__VA_ARGS__); goto err;} while(0) #define bb_perror_msg bb_error_msg #define bb_perror_msg_and_die bb_error_msg_and_die @@ -185,7 +187,6 @@ static inline ssize_t full_read(int fd, void *buf, size_t count) { #define xzalloc(x) calloc(x, 1) #define malloc_or_warn malloc #define xopen3 open -#define xfunc_die() do { bb_printf("not implemented"); return -1; } while(0) #define mkdir(x, y) _mkdirU(x) #if defined(_MSC_VER) diff --git a/src/format.c b/src/format.c index 031cfb4c..86893b66 100644 --- a/src/format.c +++ b/src/format.c @@ -58,6 +58,8 @@ extern const int nb_steps[FS_MAX]; extern uint32_t dur_mins, dur_secs; static int fs_index = 0; BOOL force_large_fat32 = FALSE, enable_ntfs_compression = FALSE; +uint8_t *grub2_buf = NULL; +long grub2_len; static BOOL WritePBR(HANDLE hLogicalDrive); /* @@ -952,7 +954,7 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive) { // TODO: Do we need anything special for 4K sectors? DWORD size, max_size, mbr_size = 0x200; - int dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); + int r, dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); unsigned char* buf = NULL; FILE fake_fd = { 0 }; @@ -969,6 +971,7 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive) switch (dt) { case DT_GRUB4DOS: + uprintf("Writing Grub4Dos SBR..."); buf = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_GR_GRUB_GRLDR_MBR), _RT_RCDATA, "grldr.mbr", &size, FALSE); if ((buf == NULL) || (size <= mbr_size)) { uprintf("grldr.mbr is either not present or too small"); @@ -978,10 +981,17 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive) size -= mbr_size; break; case DT_GRUB2: - buf = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_GR_GRUB2_CORE_IMG), _RT_RCDATA, "core.img", &size, FALSE); - if (buf == NULL) { - uprintf("Could not access core.img"); - return FALSE; + if (grub2_buf != NULL) { + uprintf("Writing Grub 2.0 SBR (from download)..."); + buf = grub2_buf; + size = (DWORD)grub2_len; + } else { + uprintf("Writing Grub 2.0 SBR (from embedded)..."); + buf = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_GR_GRUB2_CORE_IMG), _RT_RCDATA, "core.img", &size, FALSE); + if (buf == NULL) { + uprintf("Could not access core.img"); + return FALSE; + } } break; default: @@ -989,12 +999,13 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive) return TRUE; } - uprintf("Writing SBR (Secondary Boot record)"); if (size > max_size) { uprintf(" SBR size is too large - You may need to uncheck 'Add fixes for old BIOSes'."); return FALSE; } - return (write_data(&fake_fd, mbr_size, buf, (uint64_t)size) != 0); + r = write_data(&fake_fd, mbr_size, buf, (uint64_t)size); + safe_free(grub2_buf); + return (r != 0); } /* diff --git a/src/iso.c b/src/iso.c index 69744419..f841d7f5 100644 --- a/src/iso.c +++ b/src/iso.c @@ -552,6 +552,27 @@ out: return r; } +void GetGrubVersion(char* buf, size_t buf_size) +{ + char *p, unauthorized[] = {'<', '>', ':', '|', '*', '?', '\\', '/'}; + size_t i; + const char grub_version_str[] = "GRUB version %s"; + + for (i=0; i 0) + grub2_buf = malloc(grub2_len); + + // grub2_buf was set to NULL at the beginning of this call + if ((grub2_buf == NULL) || (fread(grub2_buf, 1, (size_t)grub2_len, fd) != (size_t)grub2_len)) { + uprintf("Failed to read existing '%s' data - will use embedded version", core_img); + safe_free(grub2_buf); + } + fclose(fd); + } else { + r = MessageBoxU(hMainDialog, lmprintf(MSG_116, iso_report.grub2_version, embedded_grub2_version), + lmprintf(MSG_115), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL); + if (r == IDCANCEL) + return FALSE; + else if (r == IDYES) { + static_sprintf(tmp, "%s-%s", grub, iso_report.grub2_version); + IGNORE_RETVAL(_mkdir(tmp)); + static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, iso_report.grub2_version, core_img); + SetWindowTextU(hISOProgressDlg, lmprintf(MSG_085, tmp)); + SetWindowTextU(hISOFileName, tmp); + PromptOnError = FALSE; + grub2_len = (long)DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hISOProgressDlg); + PromptOnError = TRUE; + if (grub2_len <= 0) + uprintf("%s was not found - will use embedded version\n", tmp); + else { + fd = fopen(&tmp[sizeof(FILES_URL)], "rb"); + grub2_buf = malloc(grub2_len); + if ((fd == NULL) || (grub2_buf == NULL) || (fread(grub2_buf, 1, (size_t)grub2_len, fd) != (size_t)grub2_len)) { + uprintf("Failed to read '%s' data - will use embedded version", core_img); + safe_free(grub2_buf); + } + if (fd != NULL) + fclose(fd); + } + } + } + } + if (HAS_SYSLINUX(iso_report)) { if (SL_MAJOR(iso_report.sl_version) < 5) { IGNORE_RETVAL(_chdirU(app_dir)); @@ -1434,6 +1496,7 @@ void InitDialog(HWND hDlg) } uprintf("Syslinux versions: %s%s, %s%s", embedded_sl_version_str[0], embedded_sl_version_ext[0], embedded_sl_version_str[1], embedded_sl_version_ext[1]); + uprintf("Grub versions: %s, %s", embedded_grub_version, embedded_grub2_version); uprintf("Windows version: %s\n", WindowsVersionStr); uprintf("Locale ID: 0x%04X\n", GetUserDefaultUILanguage()); diff --git a/src/rufus.h b/src/rufus.h index e4021275..ee2434e8 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -263,6 +263,7 @@ typedef struct { uint16_t sl_version; // Syslinux/Isolinux version char sl_version_str[12]; char sl_version_ext[32]; + char grub2_version[32]; } RUFUS_ISO_REPORT; /* Isolate the Syslinux version numbers */ diff --git a/src/rufus.rc b/src/rufus.rc index e516f85a..3d43d7f4 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 242, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 1.5.0.563" +CAPTION "Rufus 1.5.0.564" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,291,50,14 @@ -164,7 +164,7 @@ END IDD_DIALOG_XP DIALOGEX 12, 12, 242, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 1.5.0.563" +CAPTION "Rufus 1.5.0.564" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,291,50,14 @@ -297,7 +297,7 @@ END IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 1.5.0.563" +CAPTION "Rufus 1.5.0.564" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,291,50,14 @@ -437,7 +437,7 @@ END IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 1.5.0.563" +CAPTION "Rufus 1.5.0.564" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,291,50,14 @@ -703,8 +703,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,0,563 - PRODUCTVERSION 1,5,0,563 + FILEVERSION 1,5,0,564 + PRODUCTVERSION 1,5,0,564 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -721,13 +721,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.5.0.563" + VALUE "FileVersion", "1.5.0.564" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.5.0.563" + VALUE "ProductVersion", "1.5.0.564" END END BLOCK "VarFileInfo"