[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Backup old boot sectors before installation
From: |
Zhu Yi |
Subject: |
[PATCH] Backup old boot sectors before installation |
Date: |
Fri, 11 Dec 2009 17:26:01 +0800 |
Add a feature to backup the old boot sectors before overwritting
them with grub2 boot and core images. Users can later recover the
previous boot sectors with grub-install --recover option.
P.S. I found this might be a useful feature after I overwrote my
second PGP encrypted hard disk (Windows XP installed) boot sectors
by grub2 by mistake.
Signed-off-by: Zhu Yi <address@hidden>
---
diff --git a/util/i386/pc/grub-install.in b/util/i386/pc/grub-install.in
index 8a06213..c33bd87 100644
--- a/util/i386/pc/grub-install.in
+++ b/util/i386/pc/grub-install.in
@@ -51,6 +51,7 @@ no_floppy=
force_lba=
recheck=no
debug=no
+recover=
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
disk_module=biosdisk
@@ -77,6 +78,7 @@ Install GRUB on your drive.
--no-floppy do not probe any floppy drive
--recheck probe a device map even if it already exists
--force install even if problems are detected
+ --recover restore the previous boot sectors
EOF
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
cat <<EOF
@@ -129,6 +131,10 @@ for option in "$@"; do
debug=yes ;;
-f | --force)
setup_force="--force" ;;
+ --recover)
+ recover="$grub_prefix/bootsectors.bak" ;;
+ --recover=*)
+ recover=`echo "$option" | sed 's/--recover=//'` ;;
-*)
echo "Unrecognized option \`$option'" 1>&2
usage
@@ -203,6 +209,37 @@ else
exit 1
fi
+if test -f "$recover"; then
+ if test `stat -c%s $recover` -eq 512; then
+ echo "The backup file $recover contains MBR only. Did you install"
+ echo "grub2 using UNRELIABLE blocklist with --force? If so, try to"
+ echo "recover with `dd if=$recover of=$1 bs=512 count=1`. But you"
+ echo "take your own risk!"
+ exit 1
+ fi
+ start=`od -j512 -N8 -An -td8 $recover`
+ start2=`od -j92 -N8 -An -td8 $grubdir/boot.img`
+
+ # Synaty check for the recovery file
+ if test $start -ne $start2; then
+ echo "Error: start position of $recover doesn't match with boot.img"
+ exit 1
+ fi
+ if test $((`stat -c%s $recover` - 520)) -ne \
+ `stat -c%s $grubdir/core.img`; then
+ echo "Error: $recover doesn't match current core.img"
+ exit 1
+ fi
+
+ # Recovery
+ dd if=$recover of=$install_device bs=512 count=1 > /dev/null 2>&1
+ dd if=$recover of=$install_device skip=520 seek=`expr $start \* 512` \
+ bs=1 > /dev/null 2>&1
+ rm -f $recover
+ echo "Recover boot sectors from $recover successfully"
+ exit 0
+fi
+
# Create the GRUB directory if it is not present.
test -d "$bootdir" || mkdir "$bootdir" || exit 1
test -d "$grubdir" || mkdir "$grubdir" || exit 1
diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
index c536be0..e862e9b 100644
--- a/util/i386/pc/grub-setup.c
+++ b/util/i386/pc/grub-setup.c
@@ -45,7 +45,9 @@ static const grub_gpt_part_type_t
grub_gpt_partition_type_bios_boot = GRUB_GPT_P
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include <dirent.h>
+#include <errno.h>
#include <grub/util/getroot.h>
#define _GNU_SOURCE 1
@@ -53,6 +55,7 @@ static const grub_gpt_part_type_t
grub_gpt_partition_type_bios_boot = GRUB_GPT_P
#define DEFAULT_BOOT_FILE "boot.img"
#define DEFAULT_CORE_FILE "core.img"
+#define DEFAULT_BACKUP_FILE "bootsectors.bak"
/* This is the blocklist used in the diskboot image. */
struct boot_blocklist
@@ -85,7 +88,7 @@ grub_refresh (void)
static void
setup (const char *dir,
- const char *boot_file, const char *core_file,
+ const char *boot_file, const char *core_file, const char *backup_file,
const char *root, const char *dest, int must_embed, int force, int
fs_probe)
{
char *boot_path, *core_path, *core_path_dev;
@@ -396,6 +399,63 @@ setup (const char *dir,
block->len = 0;
block->segment = 0;
+ int grub_disk_backup(grub_disk_t disk, grub_disk_addr_t sector,
+ grub_off_t offset, grub_size_t size, const char *path)
+ {
+ char *tmp_buf;
+ char mbr[GRUB_DISK_SECTOR_SIZE];
+ int fd;
+
+ grub_util_info ("opening the backup file `%s'", path);
+ fd = open (path, O_CREAT|O_EXCL|O_WRONLY);
+ if (fd < 0) {
+ if (errno == EEXIST)
+ return 0;
+ else {
+ fprintf (stderr, "couldn't open backup file `%s'", path);
+ return -1;
+ }
+ }
+
+ fp = fdopen (fd, "wb");
+ if (! fp) {
+ close (fd);
+ return -1;
+ }
+
+ /* Backup MBR */
+ if (grub_disk_read (disk, 0, 0, GRUB_DISK_SECTOR_SIZE, mbr) !=
+ GRUB_ERR_NONE) {
+ fclose (fp);
+ return -1;
+ }
+
+ grub_util_write_image (mbr, GRUB_DISK_SECTOR_SIZE, fp);
+
+ /* Record the start position of core image */
+ if (fwrite(§or, sizeof(sector), 1, fp) != 1) {
+ fclose (fp);
+ return -1;
+ }
+
+ /* Backup the sectors will be overwritten by core image */
+ tmp_buf = xmalloc (size);
+ if (grub_disk_read (disk, sector, offset, size, tmp_buf) != GRUB_ERR_NONE)
{
+ fclose (fp);
+ return -1;
+ }
+
+ grub_util_write_image (tmp_buf, size, fp);
+
+ fclose (fp);
+ return 0;
+ }
+
+ /* Backup MBR and the sectors will be overwritten by core image */
+ if (grub_disk_backup (dest_dev->disk, embed_region.start, 0, core_size,
+ grub_util_get_path (dir, backup_file)))
+ grub_util_error ("failed to backup previous boot sectors");
+
/* Write the core image onto the disk. */
if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size,
core_img))
grub_util_error ("%s", grub_errmsg);
@@ -548,6 +608,11 @@ unable_to_embed:
grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp);
fclose (fp);
+ /* Backup MBR */
+ if (grub_disk_backup (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE,
+ grub_util_get_path (dir, backup_file)))
+ grub_util_error ("failed to backup previous boot sectors");
+
/* Write the boot image onto the disk. */
if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img))
grub_util_error ("%s", grub_errmsg);
@@ -596,6 +661,7 @@ DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\
-d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\
-m, --device-map=FILE use FILE as the device map [default=%s]\n\
-r, --root-device=DEV use DEV as the root device [default=guessed]\n\
+ -k, --backup-file=FILE use FILE as the backup file [default=%s]\n\
-f, --force install even if problems are detected\n\
-s, --skip-fs-probe do not probe for filesystems in DEVICE\n\
-h, --help display this message and exit\n\
@@ -605,7 +671,7 @@ DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\
Report bugs to <%s>.\n\
",
DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY,
- DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
+ DEFAULT_DEVICE_MAP, DEFAULT_BACKUP_FILE, PACKAGE_BUGREPORT);
exit (status);
}
@@ -627,6 +693,7 @@ main (int argc, char *argv[])
{
char *boot_file = 0;
char *core_file = 0;
+ char *backup_file = 0;
char *dir = 0;
char *dev_map = 0;
char *root_dev = 0;
@@ -638,7 +705,7 @@ main (int argc, char *argv[])
/* Check for options. */
while (1)
{
- int c = getopt_long (argc, argv, "b:c:d:m:r:hVvf", options, 0);
+ int c = getopt_long (argc, argv, "b:c:d:m:r:k:hVvf", options, 0);
if (c == -1)
break;
@@ -680,6 +747,13 @@ main (int argc, char *argv[])
root_dev = xstrdup (optarg);
break;
+ case 'k':
+ if (backup_file)
+ free (backup_file);
+
+ backup_file = xstrdup (optarg);
+ break;
+
case 'f':
force = 1;
break;
@@ -789,6 +863,7 @@ main (int argc, char *argv[])
setup (dir ? : DEFAULT_DIRECTORY,
boot_file ? : DEFAULT_BOOT_FILE,
core_file ? : DEFAULT_CORE_FILE,
+ backup_file ? : DEFAULT_BACKUP_FILE,
root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force,
fs_probe);
}
}
@@ -798,6 +873,7 @@ main (int argc, char *argv[])
setup (dir ? : DEFAULT_DIRECTORY,
boot_file ? : DEFAULT_BOOT_FILE,
core_file ? : DEFAULT_CORE_FILE,
+ backup_file ? : DEFAULT_BACKUP_FILE,
root_dev, dest_dev, must_embed, force, fs_probe);
/* Free resources. */
@@ -806,6 +882,7 @@ main (int argc, char *argv[])
free (boot_file);
free (core_file);
+ free (backup_file);
free (dir);
free (dev_map);
free (root_dev);
- [PATCH] Backup old boot sectors before installation,
Zhu Yi <=
- Re: [PATCH] Backup old boot sectors before installation, Felix Zielcke, 2009/12/11
- Re: [PATCH] Backup old boot sectors before installation, Carles Pina i Estany, 2009/12/11
- Re: [PATCH] Backup old boot sectors before installation, Zhu Yi, 2009/12/13
- Re: [PATCH] Backup old boot sectors before installation, kashyap garimella, 2009/12/13
- Re: [PATCH] Backup old boot sectors before installation, address@hidden, 2009/12/13
- Re: [PATCH] Backup old boot sectors before installation, Isaac Dupree, 2009/12/13
- Re: [PATCH] Backup old boot sectors before installation, Zhu Yi, 2009/12/13
- Re: [PATCH] Backup old boot sectors before installation, Isaac Dupree, 2009/12/13