#include "hw.h"
-const char* other_filesystems[] = {
- "/dev",
- "/proc",
- "/sys",
- NULL
-};
-
static int system_chroot(const char* output, const char* path, const char* cmd) {
char chroot_cmd[STRING_SIZE];
if (ret == 0)
snprintf(hw->arch, sizeof(hw->arch), "%s", uname_data.machine);
- // Detect if we are running in EFI mode
- ret = access("/sys/firmware/efi", R_OK);
- if (ret == 0)
- hw->efi_supported = 1;
-
// Should we install in EFI mode?
if ((strcmp(hw->arch, "x86_64") == 0) || (strcmp(hw->arch, "aarch64") == 0))
hw->efi = 1;
}
}
- int r = mount(source, target, fs, flags, NULL);
+ return mount(source, target, fs, flags, NULL);
+}
- if (r) {
- fprintf(stderr, "Error mounting %s to %s (fs = %s, flags = %d): %s\n",
- source, target, fs, flags, strerror(r));
+static int hw_bind_mount(const char* source, const char* prefix) {
+ if (!source || !prefix) {
+ errno = EINVAL;
+ return 1;
}
- return r;
+ char target[PATH_MAX];
+ int r;
+
+ // Format target
+ r = snprintf(target, sizeof(target) - 1, "%s/%s", prefix, source);
+ if (r < 0)
+ return 1;
+
+ // Ensure target exists
+ mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO);
+
+ return hw_mount(source, target, NULL, MS_BIND);
}
-int hw_umount(const char* target) {
- int r = umount2(target, 0);
+int hw_umount(const char* source, const char* prefix) {
+ char target[PATH_MAX];
+ int r;
+
+ if (prefix)
+ r = snprintf(target, sizeof(target) - 1, "%s/%s", prefix, source);
+ else
+ r = snprintf(target, sizeof(target) - 1, "%s", source);
+ if (r < 0)
+ return r;
+
+ // Perform umount
+ r = umount2(target, 0);
+ if (r) {
+ switch (errno) {
+ // Try again with force if umount wasn't successful
+ case EBUSY:
+ sleep(1);
+
+ r = umount2(target, MNT_FORCE);
+ break;
- if (r && errno == EBUSY) {
- // Give it a moment to settle
- sleep(1);
+ // target wasn't a mountpoint. Ignore.
+ case EINVAL:
+ r = 0;
+ break;
- r = umount2(target, MNT_FORCE);
+ // target doesn't exist
+ case ENOENT:
+ r = 0;
+ break;
+ }
}
return r;
static int hw_test_source_medium(const char* path) {
int ret = hw_mount(path, SOURCE_MOUNT_PATH, "iso9660", MS_RDONLY);
+ if (ret != 0) {
+ // 2nd try, ntfs for a rufus converted usb key
+ ret = hw_mount(path, SOURCE_MOUNT_PATH, "ntfs3", MS_RDONLY);
+ }
+ if (ret != 0) {
+ // 3rd try, vfat for a rufus converted usb key
+ ret = hw_mount(path, SOURCE_MOUNT_PATH, "vfat", MS_RDONLY);
+ }
+
// If the source could not be mounted we
// cannot proceed.
if (ret != 0)
ret = access(SOURCE_TEST_FILE, R_OK);
// Umount the test device.
- hw_umount(SOURCE_MOUNT_PATH);
+ hw_umount(SOURCE_MOUNT_PATH, NULL);
return ret;
}
struct hw_disk** ret = hw_create_disks();
struct hw_disk** disks = ret;
+ // Determine the disk device of source if it is a partition
+ char* sourcedisk = NULL;
+ char syssource[PATH_MAX];
+ (void)snprintf(syssource, sizeof(syssource) - 1, "/sys/class/block/%s", sourcedrive + 5);
+ struct udev_device* s_dev = udev_device_new_from_syspath(hw->udev, syssource);
+ const char* s_devtype = udev_device_get_property_value(s_dev, "DEVTYPE");
+ if (s_devtype && (strcmp(s_devtype, "partition") == 0)) {
+ struct udev_device* p_dev = udev_device_get_parent_with_subsystem_devtype(s_dev,"block","disk");
+ if (p_dev) {
+ sourcedisk = udev_device_get_devnode(p_dev);
+ }
+ }
+ if (!sourcedisk) sourcedisk = sourcedrive;
+
struct udev_enumerate* enumerate = udev_enumerate_new(hw->udev);
udev_enumerate_add_match_subsystem(enumerate, "block");
continue;
}
- // Skip sourcedrive if we need to
- if (sourcedrive && (strcmp(dev_path, sourcedrive) == 0)) {
+ // Skip sourcedisk if we need to
+ if (sourcedisk && (strcmp(dev_path, sourcedisk) == 0)) {
udev_device_unref(dev);
continue;
}
snprintf(dest->part_boot_efi, sizeof(dest->part_boot_efi),
"%s%d", path, part_idx++);
- } else
+ } else {
*dest->part_boot_efi = '\0';
+ dest->part_boot_efi_idx = 0;
+ }
if (dest->size_swap > 0)
snprintf(dest->part_swap, sizeof(dest->part_swap), "%s%d", path, part_idx++);
if (*dest->part_bootldr) {
asprintf(&cmd, "%s set %d bios_grub on", cmd, dest->part_boot_idx);
}
- asprintf(&cmd, "%s disk_set pmbr_boot on", cmd);
}
r = mysystem(output, cmd);
}
// bind-mount misc filesystems
- char** otherfs = other_filesystems;
- while (*otherfs) {
- snprintf(target, sizeof(target), "%s%s", prefix, *otherfs);
+ r = hw_bind_mount("/dev", prefix);
+ if (r)
+ return r;
- mkdir(target, S_IRWXU|S_IRWXG|S_IRWXO);
- r = hw_mount(*otherfs, target, NULL, MS_BIND);
- if (r) {
- hw_umount_filesystems(dest, prefix);
+ r = hw_bind_mount("/proc", prefix);
+ if (r)
+ return r;
- return r;
- }
+ r = hw_bind_mount("/sys", prefix);
+ if (r)
+ return r;
- otherfs++;
- }
+ r = hw_bind_mount("/sys/firmware/efi/efivars", prefix);
+ if (r && errno != ENOENT)
+ return r;
return 0;
}
// ESP
if (*dest->part_boot_efi) {
- snprintf(target, sizeof(target), "%s%s", prefix, HW_PATH_BOOT_EFI);
- r = hw_umount(target);
+ r = hw_umount(HW_PATH_BOOT_EFI, prefix);
if (r)
return -1;
}
// boot
if (*dest->part_boot) {
- snprintf(target, sizeof(target), "%s%s", prefix, HW_PATH_BOOT);
- r = hw_umount(target);
+ r = hw_umount(HW_PATH_BOOT, prefix);
if (r)
return -1;
}
}
// misc filesystems
- char** otherfs = other_filesystems;
- while (*otherfs) {
- snprintf(target, sizeof(target), "%s%s", prefix, *otherfs++);
- r = hw_umount(target);
- if (r)
- return -1;
- }
+ r = hw_umount("/sys/firmware/efi/efivars", prefix);
+ if (r)
+ return -1;
+
+ r = hw_umount("/sys", prefix);
+ if (r)
+ return -1;
+
+ r = hw_umount("/proc", prefix);
+ if (r)
+ return -1;
+
+ r = hw_umount("/dev", prefix);
+ if (r)
+ return -1;
// root
- r = hw_umount(prefix);
+ r = hw_umount(prefix, NULL);
if (r)
return -1;
int hw_install_bootloader(struct hw* hw, struct hw_destination* dest, const char* output) {
char cmd[STRING_SIZE];
- int r;
-
- char cmd_grub[STRING_SIZE];
- snprintf(cmd_grub, sizeof(cmd_grub), "/usr/sbin/grub-install --target=i386-pc"
- " --no-floppy --recheck");
-
- if (dest->is_raid) {
- snprintf(cmd, sizeof(cmd), "%s %s", cmd_grub, dest->disk1->path);
- r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd);
- if (r)
- return r;
-
- snprintf(cmd, sizeof(cmd), "%s %s", cmd_grub, dest->disk2->path);
- r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd);
- if (r)
- return r;
- } else {
- snprintf(cmd, sizeof(cmd), "%s %s", cmd_grub, dest->path);
- r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd);
- if (r)
- return r;
- }
-
- // Install GRUB in EFI mode
- if (hw->efi) {
- for (int removable = 0; removable < 1; removable++) {
- snprintf(cmd, sizeof(cmd), "/usr/sbin/grub-install"
- " --target=%s-efi --efi-directory=%s %s %s",
- hw->arch, HW_PATH_BOOT_EFI,
- (hw->efi_supported) ? "" : "--no-nvram",
- (removable) ? "--removable" : "");
-
- r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd);
- if (r)
- return r;
- }
- }
- // Generate configuration file
- snprintf(cmd, sizeof(cmd), "/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg");
- r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd);
+ snprintf(cmd, sizeof(cmd), "/usr/bin/install-bootloader %s", dest->path);
+ int r = system_chroot(output, DESTINATION_MOUNT_PATH, cmd);
if (r)
return r;