From efce87e5ab98664c57e5f4e3955a2f3747df5737 Mon Sep 17 00:00:00 2001
|
From: Robert Yang <liezhi.yang@windriver.com>
|
Date: Fri, 2 Jan 2015 12:26:46 +0800
|
Subject: [PATCH] libinstaller/syslinuxext: implement syslinux_patch_bootsect()
|
|
Move the related from extlinux/main.c to libinstaller/syslinuxext.c, the
|
syslinux_patch_bootsect() are used by both extlinux/main.c and
|
linux/syslinux.c.
|
|
Upstream-Status: Submitted
|
|
Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
|
Tested-by: Du Dolpher <dolpher.du@intel.com>
|
|
Edited to include sysmacros.h
|
|
Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
|
---
|
extlinux/Makefile | 3 +-
|
extlinux/main.c | 167 +-----------------------------------
|
libinstaller/syslinuxext.c | 171 +++++++++++++++++++++++++++++++++++++
|
3 files changed, 176 insertions(+), 165 deletions(-)
|
|
diff --git a/extlinux/Makefile b/extlinux/Makefile
|
index 1721ee54..62a49728 100644
|
--- a/extlinux/Makefile
|
+++ b/extlinux/Makefile
|
@@ -32,7 +32,8 @@ SRCS = main.c \
|
../libinstaller/advio.c \
|
../libinstaller/bootsect_bin.c \
|
../libinstaller/ldlinuxc32_bin.c \
|
- ../libinstaller/ldlinux_bin.c
|
+ ../libinstaller/ldlinux_bin.c \
|
+ ../libinstaller/syslinuxext.c
|
OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
|
|
.SUFFIXES: .c .o .i .s .S
|
diff --git a/extlinux/main.c b/extlinux/main.c
|
index ebff7eae..9add50fb 100644
|
--- a/extlinux/main.c
|
+++ b/extlinux/main.c
|
@@ -62,6 +62,7 @@
|
#include "setadv.h"
|
#include "syslxopt.h" /* unified options */
|
#include "mountinfo.h"
|
+#include "syslinuxext.h"
|
|
#ifdef DEBUG
|
# define dprintf printf
|
@@ -69,10 +70,6 @@
|
# define dprintf(...) ((void)0)
|
#endif
|
|
-#ifndef EXT2_SUPER_OFFSET
|
-#define EXT2_SUPER_OFFSET 1024
|
-#endif
|
-
|
/* Since we have unused 2048 bytes in the primary AG of an XFS partition,
|
* we will use the first 0~512 bytes starting from 2048 for the Syslinux
|
* boot sector.
|
@@ -93,136 +90,6 @@ static char subvol[BTRFS_SUBVOL_MAX];
|
#define BTRFS_ADV_OFFSET (BTRFS_BOOT_AREA_A_OFFSET + BTRFS_BOOT_AREA_A_SIZE \
|
- 2*ADV_SIZE)
|
|
-/*
|
- * Get the size of a block device
|
- */
|
-static uint64_t get_size(int devfd)
|
-{
|
- uint64_t bytes;
|
- uint32_t sects;
|
- struct stat st;
|
-
|
-#ifdef BLKGETSIZE64
|
- if (!ioctl(devfd, BLKGETSIZE64, &bytes))
|
- return bytes;
|
-#endif
|
- if (!ioctl(devfd, BLKGETSIZE, §s))
|
- return (uint64_t) sects << 9;
|
- else if (!fstat(devfd, &st) && st.st_size)
|
- return st.st_size;
|
- else
|
- return 0;
|
-}
|
-
|
-/*
|
- * Get device geometry and partition offset
|
- */
|
-struct geometry_table {
|
- uint64_t bytes;
|
- struct hd_geometry g;
|
-};
|
-
|
-static int sysfs_get_offset(int devfd, unsigned long *start)
|
-{
|
- struct stat st;
|
- char sysfs_name[128];
|
- FILE *f;
|
- int rv;
|
-
|
- if (fstat(devfd, &st))
|
- return -1;
|
-
|
- if ((size_t)snprintf(sysfs_name, sizeof sysfs_name,
|
- "/sys/dev/block/%u:%u/start",
|
- major(st.st_rdev), minor(st.st_rdev))
|
- >= sizeof sysfs_name)
|
- return -1;
|
-
|
- f = fopen(sysfs_name, "r");
|
- if (!f)
|
- return -1;
|
-
|
- rv = fscanf(f, "%lu", start);
|
- fclose(f);
|
-
|
- return (rv == 1) ? 0 : -1;
|
-}
|
-
|
-/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
|
- (x/64/32) is the final fallback. I don't know what LS-240 has
|
- as its geometry, since I don't have one and don't know anyone that does,
|
- and Google wasn't helpful... */
|
-static const struct geometry_table standard_geometries[] = {
|
- {360 * 1024, {2, 9, 40, 0}},
|
- {720 * 1024, {2, 9, 80, 0}},
|
- {1200 * 1024, {2, 15, 80, 0}},
|
- {1440 * 1024, {2, 18, 80, 0}},
|
- {1680 * 1024, {2, 21, 80, 0}},
|
- {1722 * 1024, {2, 21, 80, 0}},
|
- {2880 * 1024, {2, 36, 80, 0}},
|
- {3840 * 1024, {2, 48, 80, 0}},
|
- {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */
|
- {0, {0, 0, 0, 0}}
|
-};
|
-
|
-int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
|
-{
|
- struct floppy_struct fd_str;
|
- struct loop_info li;
|
- struct loop_info64 li64;
|
- const struct geometry_table *gp;
|
- int rv = 0;
|
-
|
- memset(geo, 0, sizeof *geo);
|
-
|
- if (!ioctl(devfd, HDIO_GETGEO, geo)) {
|
- goto ok;
|
- } else if (!ioctl(devfd, FDGETPRM, &fd_str)) {
|
- geo->heads = fd_str.head;
|
- geo->sectors = fd_str.sect;
|
- geo->cylinders = fd_str.track;
|
- geo->start = 0;
|
- goto ok;
|
- }
|
-
|
- /* Didn't work. Let's see if this is one of the standard geometries */
|
- for (gp = standard_geometries; gp->bytes; gp++) {
|
- if (gp->bytes == totalbytes) {
|
- memcpy(geo, &gp->g, sizeof *geo);
|
- goto ok;
|
- }
|
- }
|
-
|
- /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is
|
- what zipdisks use, so this would help if someone has a USB key that
|
- they're booting in USB-ZIP mode. */
|
-
|
- geo->heads = opt.heads ? : 64;
|
- geo->sectors = opt.sectors ? : 32;
|
- geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT);
|
- geo->start = 0;
|
-
|
- if (!opt.sectors && !opt.heads) {
|
- fprintf(stderr,
|
- "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n"
|
- " (on hard disks, this is usually harmless.)\n",
|
- geo->heads, geo->sectors);
|
- rv = 1; /* Suboptimal result */
|
- }
|
-
|
-ok:
|
- /* If this is a loopback device, try to set the start */
|
- if (!ioctl(devfd, LOOP_GET_STATUS64, &li64))
|
- geo->start = li64.lo_offset >> SECTOR_SHIFT;
|
- else if (!ioctl(devfd, LOOP_GET_STATUS, &li))
|
- geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT;
|
- else if (!sysfs_get_offset(devfd, &geo->start)) {
|
- /* OK */
|
- }
|
-
|
- return rv;
|
-}
|
-
|
/*
|
* Query the device geometry and put it into the boot sector.
|
* Map the file and put the map in the boot sector and file.
|
@@ -233,11 +100,8 @@ ok:
|
static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
|
{
|
struct stat dirst, xdst;
|
- struct hd_geometry geo;
|
sector_t *sectp;
|
- uint64_t totalbytes, totalsectors;
|
int nsect;
|
- struct fat_boot_sector *sbs;
|
char *dirpath, *subpath, *xdirpath;
|
int rv;
|
|
@@ -281,33 +145,8 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
|
/* Now subpath should contain the path relative to the fs base */
|
dprintf("subpath = %s\n", subpath);
|
|
- totalbytes = get_size(devfd);
|
- get_geometry(devfd, totalbytes, &geo);
|
-
|
- if (opt.heads)
|
- geo.heads = opt.heads;
|
- if (opt.sectors)
|
- geo.sectors = opt.sectors;
|
-
|
- /* Patch this into a fake FAT superblock. This isn't because
|
- FAT is a good format in any way, it's because it lets the
|
- early bootstrap share code with the FAT version. */
|
- dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
|
-
|
- sbs = (struct fat_boot_sector *)syslinux_bootsect;
|
-
|
- totalsectors = totalbytes >> SECTOR_SHIFT;
|
- if (totalsectors >= 65536) {
|
- set_16(&sbs->bsSectors, 0);
|
- } else {
|
- set_16(&sbs->bsSectors, totalsectors);
|
- }
|
- set_32(&sbs->bsHugeSectors, totalsectors);
|
-
|
- set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
|
- set_16(&sbs->bsSecPerTrack, geo.sectors);
|
- set_16(&sbs->bsHeads, geo.heads);
|
- set_32(&sbs->bsHiddenSecs, geo.start);
|
+ /* Patch syslinux_bootsect */
|
+ syslinux_patch_bootsect(devfd);
|
|
/* Construct the boot file map */
|
|
diff --git a/libinstaller/syslinuxext.c b/libinstaller/syslinuxext.c
|
index bb54cefc..9ae82884 100644
|
--- a/libinstaller/syslinuxext.c
|
+++ b/libinstaller/syslinuxext.c
|
@@ -1,7 +1,178 @@
|
#define _GNU_SOURCE
|
|
+#include <sys/stat.h>
|
+#include <sys/types.h>
|
+#include <sys/sysmacros.h>
|
+#include <getopt.h>
|
+#include <ext2fs/ext2fs.h>
|
+
|
+#include "linuxioctl.h"
|
+#include "syslinux.h"
|
+#include "syslxint.h"
|
+#include "syslxopt.h"
|
+
|
+/*
|
+ * Get the size of a block device
|
+ */
|
+static uint64_t get_size(int dev_fd)
|
+{
|
+ uint64_t bytes;
|
+ uint32_t sects;
|
+ struct stat st;
|
+
|
+#ifdef BLKGETSIZE64
|
+ if (!ioctl(dev_fd, BLKGETSIZE64, &bytes))
|
+ return bytes;
|
+#endif
|
+ if (!ioctl(dev_fd, BLKGETSIZE, §s))
|
+ return (uint64_t) sects << 9;
|
+ else if (!fstat(dev_fd, &st) && st.st_size)
|
+ return st.st_size;
|
+ else
|
+ return 0;
|
+}
|
+
|
+/*
|
+ * Get device geometry and partition offset
|
+ */
|
+static struct geometry_table {
|
+ uint64_t bytes;
|
+ struct hd_geometry g;
|
+};
|
+
|
+static int sysfs_get_offset(int dev_fd, unsigned long *start)
|
+{
|
+ struct stat st;
|
+ char sysfs_name[128];
|
+ FILE *f;
|
+ int rv;
|
+
|
+ if (fstat(dev_fd, &st))
|
+ return -1;
|
+
|
+ if ((size_t)snprintf(sysfs_name, sizeof sysfs_name,
|
+ "/sys/dev/block/%u:%u/start",
|
+ major(st.st_rdev), minor(st.st_rdev))
|
+ >= sizeof sysfs_name)
|
+ return -1;
|
+
|
+ f = fopen(sysfs_name, "r");
|
+ if (!f)
|
+ return -1;
|
+
|
+ rv = fscanf(f, "%lu", start);
|
+ fclose(f);
|
+
|
+ return (rv == 1) ? 0 : -1;
|
+}
|
+
|
+/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
|
+ (x/64/32) is the final fallback. I don't know what LS-240 has
|
+ as its geometry, since I don't have one and don't know anyone that does,
|
+ and Google wasn't helpful... */
|
+static const struct geometry_table standard_geometries[] = {
|
+ {360 * 1024, {2, 9, 40, 0}},
|
+ {720 * 1024, {2, 9, 80, 0}},
|
+ {1200 * 1024, {2, 15, 80, 0}},
|
+ {1440 * 1024, {2, 18, 80, 0}},
|
+ {1680 * 1024, {2, 21, 80, 0}},
|
+ {1722 * 1024, {2, 21, 80, 0}},
|
+ {2880 * 1024, {2, 36, 80, 0}},
|
+ {3840 * 1024, {2, 48, 80, 0}},
|
+ {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */
|
+ {0, {0, 0, 0, 0}}
|
+};
|
+
|
+static int get_geometry(int dev_fd, uint64_t totalbytes, struct hd_geometry *geo)
|
+{
|
+ struct floppy_struct fd_str;
|
+ struct loop_info li;
|
+ struct loop_info64 li64;
|
+ const struct geometry_table *gp;
|
+ int rv = 0;
|
+
|
+ memset(geo, 0, sizeof *geo);
|
+
|
+ if (!ioctl(dev_fd, HDIO_GETGEO, geo)) {
|
+ goto ok;
|
+ } else if (!ioctl(dev_fd, FDGETPRM, &fd_str)) {
|
+ geo->heads = fd_str.head;
|
+ geo->sectors = fd_str.sect;
|
+ geo->cylinders = fd_str.track;
|
+ geo->start = 0;
|
+ goto ok;
|
+ }
|
+
|
+ /* Didn't work. Let's see if this is one of the standard geometries */
|
+ for (gp = standard_geometries; gp->bytes; gp++) {
|
+ if (gp->bytes == totalbytes) {
|
+ memcpy(geo, &gp->g, sizeof *geo);
|
+ goto ok;
|
+ }
|
+ }
|
+
|
+ /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is
|
+ what zipdisks use, so this would help if someone has a USB key that
|
+ they're booting in USB-ZIP mode. */
|
+
|
+ geo->heads = opt.heads ? : 64;
|
+ geo->sectors = opt.sectors ? : 32;
|
+ geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT);
|
+ geo->start = 0;
|
+
|
+ if (!opt.sectors && !opt.heads) {
|
+ fprintf(stderr,
|
+ "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n"
|
+ " (on hard disks, this is usually harmless.)\n",
|
+ geo->heads, geo->sectors);
|
+ rv = 1; /* Suboptimal result */
|
+ }
|
+
|
+ok:
|
+ /* If this is a loopback device, try to set the start */
|
+ if (!ioctl(dev_fd, LOOP_GET_STATUS64, &li64))
|
+ geo->start = li64.lo_offset >> SECTOR_SHIFT;
|
+ else if (!ioctl(dev_fd, LOOP_GET_STATUS, &li))
|
+ geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT;
|
+ else if (!sysfs_get_offset(dev_fd, &geo->start)) {
|
+ /* OK */
|
+ }
|
+
|
+ return rv;
|
+}
|
+
|
+
|
/* Patch syslinux_bootsect */
|
void syslinux_patch_bootsect(int dev_fd)
|
{
|
+ uint64_t totalbytes, totalsectors;
|
+ struct hd_geometry geo;
|
+ struct fat_boot_sector *sbs;
|
+
|
+ totalbytes = get_size(dev_fd);
|
+ get_geometry(dev_fd, totalbytes, &geo);
|
+
|
+ if (opt.heads)
|
+ geo.heads = opt.heads;
|
+ if (opt.sectors)
|
+ geo.sectors = opt.sectors;
|
+
|
+ /* Patch this into a fake FAT superblock. This isn't because
|
+ FAT is a good format in any way, it's because it lets the
|
+ early bootstrap share code with the FAT version. */
|
+ sbs = (struct fat_boot_sector *)syslinux_bootsect;
|
+
|
+ totalsectors = totalbytes >> SECTOR_SHIFT;
|
+ if (totalsectors >= 65536) {
|
+ set_16(&sbs->bsSectors, 0);
|
+ } else {
|
+ set_16(&sbs->bsSectors, totalsectors);
|
+ }
|
+ set_32(&sbs->bsHugeSectors, totalsectors);
|
+
|
+ set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
|
+ set_16(&sbs->bsSecPerTrack, geo.sectors);
|
+ set_16(&sbs->bsHeads, geo.heads);
|
+ set_32(&sbs->bsHiddenSecs, geo.start);
|
}
|
|
--
|
2.17.1
|