summaryrefslogtreecommitdiff
path: root/extlinux/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'extlinux/main.c')
-rw-r--r--extlinux/main.c147
1 files changed, 74 insertions, 73 deletions
diff --git a/extlinux/main.c b/extlinux/main.c
index 6ba16e1e..a7ebd49a 100644
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -14,7 +14,7 @@
/*
* extlinux.c
*
- * Install the syslinux boot block on an fat, ntfs, ext2/3/4, btrfs, xfs,
+ * Install the syslinux boot block on a fat, ntfs, ext2/3/4, btrfs, xfs,
* and ufs1/2 filesystem.
*/
@@ -56,6 +56,7 @@
#include "version.h"
#include "syslxint.h"
#include "syslxcom.h" /* common functions shared with extlinux and syslinux */
+#include "syslxrw.h"
#include "syslxfs.h"
#include "setadv.h"
#include "syslxopt.h" /* unified options */
@@ -337,6 +338,59 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
return rv;
}
+static int ext_read_adv_offset(int devfd, off_t offset)
+{
+ const size_t adv_size = 2 * ADV_SIZE;
+
+ if (xpread(devfd, syslinux_adv, adv_size, offset) != adv_size)
+ return -1;
+
+ return syslinux_validate_adv(syslinux_adv) ? 1 : 0;
+}
+
+static int ext_read_adv(const char *path, int devfd, const char **namep)
+{
+ int err;
+ const char *name;
+
+ if (fs_type == BTRFS) {
+ /* btrfs "ldlinux.sys" is in 64k blank area */
+ return ext_read_adv_offset(devfd, BTRFS_ADV_OFFSET);
+ } else if (fs_type == XFS) {
+ /* XFS "ldlinux.sys" is in the first 2048 bytes of the primary AG */
+ return ext_read_adv_offset(devfd, boot_image_len);
+ } else {
+ err = read_adv(path, name = "ldlinux.sys");
+ if (err == 2) /* ldlinux.sys does not exist */
+ err = read_adv(path, name = "extlinux.sys");
+ if (namep)
+ *namep = name;
+ return err;
+ }
+}
+
+static int ext_write_adv_offset(int devfd, off_t offset)
+{
+ const size_t adv_size = 2 * ADV_SIZE;
+
+ if (xpwrite(devfd, syslinux_adv, adv_size, offset) != adv_size) {
+ perror("writing adv");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int ext_write_adv(const char *path, const char *cfg, int devfd)
+{
+ if (fs_type == BTRFS) {
+ /* btrfs "ldlinux.sys" is in 64k blank area */
+ return ext_write_adv_offset(devfd, BTRFS_ADV_OFFSET);
+ } else {
+ return write_adv(path, cfg);
+ }
+}
+
/*
* Install the boot block on the specified device.
* Must be run AFTER install_file()!
@@ -392,11 +446,11 @@ int install_bootblock(int fd, const char *device)
if (sb5.sb_magicnum == *(u32 *)XFS_SB_MAGIC) {
if (be32_to_cpu(sb5.sb_blocksize) != XFS_SUPPORTED_BLOCKSIZE) {
fprintf(stderr,
- "You need to have 4 KiB filesystem block size for "
- " being able to install Syslinux in your XFS "
- "partition (because there is no enough space in MBR to "
- "determine where Syslinux bootsector can be installed "
- "regardless the filesystem block size)\n");
+ "You need to have 4 KiB filesystem block size for"
+ " being able to install Syslinux in your XFS"
+ " partition (because there is not enough space in MBR to"
+ " determine where Syslinux bootsector can be installed"
+ " regardless of the filesystem block size)\n");
return 1;
}
@@ -419,8 +473,8 @@ int install_bootblock(int fd, const char *device)
if (!ok) {
fprintf(stderr,
- "no fat, ntfs, ext2/3/4, btrfs, xfs "
- "or ufs1/2 superblock found on %s\n",
+ "no fat, ntfs, ext2/3/4, btrfs, xfs"
+ " or ufs1/2 superblock found on %s\n",
device);
return 1;
}
@@ -483,8 +537,7 @@ static int rewrite_boot_image(int devfd, const char *path, const char *filename)
}
/* Write ADV */
- ret = xpwrite(fd, syslinux_adv, 2 * ADV_SIZE, boot_image_len);
- if (ret != 2 * ADV_SIZE) {
+ if (ext_write_adv_offset(fd, boot_image_len)) {
fprintf(stderr, "%s: write failure on %s\n", program, filename);
goto error;
}
@@ -597,9 +650,12 @@ bail:
return 1;
}
-/* btrfs has to install the ldlinux.sys in the first 64K blank area, which
- is not managered by btrfs tree, so actually this is not installed as files.
- since the cow feature of btrfs will move the ldlinux.sys every where */
+/* btrfs has to install ldlinux.sys to a boot area, which is not managed by
+ btrfs tree, so actually this is not installed as a file, since the cow
+ feature of btrfs would move the ldlinux.sys file everywhere. Older
+ versions installed it to the first 64kiB (aka Boot Area A) but as of
+ commit ID 37eef640 (before 6.03-pre12, before 6.03), it is now in Boot
+ Area B (a 768kiB blank space at offset 256kiB). */
int btrfs_install_file(const char *path, int devfd, struct stat *rst)
{
char *file;
@@ -613,9 +669,7 @@ int btrfs_install_file(const char *path, int devfd, struct stat *rst)
return 1;
}
dprintf("write boot_image to 0x%x\n", BTRFS_EXTLINUX_OFFSET);
- if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE, BTRFS_ADV_OFFSET)
- != 2 * ADV_SIZE) {
- perror("writing adv");
+ if (ext_write_adv_offset(devfd, BTRFS_ADV_OFFSET)) {
return 1;
}
dprintf("write adv to 0x%x\n", BTRFS_ADV_OFFSET);
@@ -661,7 +715,7 @@ int btrfs_install_file(const char *path, int devfd, struct stat *rst)
* Due to historical reasons (SGI IRIX's design of disk layouts), the first
* sector in the primary AG on XFS filesystems contains the superblock, which is
* a problem with bootloaders that rely on BIOSes (that load VBRs which are
- * (located in the first sector of the partition).
+ * located in the first sector of the partition).
*
* Thus, we need to handle this issue, otherwise Syslinux will damage the XFS's
* superblock.
@@ -750,7 +804,7 @@ bail:
* * test if path is a subvolume:
* * this function return
* * 0-> path exists but it is not a subvolume
- * * 1-> path exists and it is a subvolume
+ * * 1-> path exists and it is a subvolume
* * -1 -> path is unaccessible
* */
static int test_issubvolume(char *path)
@@ -1384,8 +1438,8 @@ static int open_device(const char *path, struct stat *st, char **_devname)
if (!fs_type) {
fprintf(stderr,
- "%s: not a fat, ntfs, ext2/3/4, btrfs, xfs or"
- "ufs1/2 filesystem: %s\n",
+ "%s: not a fat, ntfs, ext2/3/4, btrfs, xfs"
+ " or ufs1/2 filesystem: %s\n",
program, path);
return -1;
}
@@ -1414,59 +1468,6 @@ static int open_device(const char *path, struct stat *st, char **_devname)
return devfd;
}
-static int btrfs_read_adv(int devfd)
-{
- if (xpread(devfd, syslinux_adv, 2 * ADV_SIZE, BTRFS_ADV_OFFSET)
- != 2 * ADV_SIZE)
- return -1;
-
- return syslinux_validate_adv(syslinux_adv) ? 1 : 0;
-}
-
-static inline int xfs_read_adv(int devfd)
-{
- const size_t adv_size = 2 * ADV_SIZE;
-
- if (xpread(devfd, syslinux_adv, adv_size, boot_image_len) != adv_size)
- return -1;
-
- return syslinux_validate_adv(syslinux_adv) ? 1 : 0;
-}
-
-static int ext_read_adv(const char *path, int devfd, const char **namep)
-{
- int err;
- const char *name;
-
- if (fs_type == BTRFS) {
- /* btrfs "ldlinux.sys" is in 64k blank area */
- return btrfs_read_adv(devfd);
- } else if (fs_type == XFS) {
- /* XFS "ldlinux.sys" is in the first 2048 bytes of the primary AG */
- return xfs_read_adv(devfd);
- } else {
- err = read_adv(path, name = "ldlinux.sys");
- if (err == 2) /* ldlinux.sys does not exist */
- err = read_adv(path, name = "extlinux.sys");
- if (namep)
- *namep = name;
- return err;
- }
-}
-
-static int ext_write_adv(const char *path, const char *cfg, int devfd)
-{
- if (fs_type == BTRFS) { /* btrfs "ldlinux.sys" is in 64k blank area */
- if (xpwrite(devfd, syslinux_adv, 2 * ADV_SIZE,
- BTRFS_ADV_OFFSET) != 2 * ADV_SIZE) {
- perror("writing adv");
- return 1;
- }
- return 0;
- }
- return write_adv(path, cfg);
-}
-
static int install_loader(const char *path, int update_only)
{
struct stat st, fst;