1 From 78d76b87a4b855e6b661ae457283a63f385c04c9 Mon Sep 17 00:00:00 2001
2 From: Robert Yang <liezhi.yang@windriver.com>
3 Date: Fri, 2 Jan 2015 12:26:46 +0800
4 Subject: [PATCH 8/9] libinstaller/syslinuxext: implement
5 syslinux_patch_bootsect()
7 Move the related from extlinux/main.c to libinstaller/syslinuxext.c, the
8 syslinux_patch_bootsect() are used by both extlinux/main.c and
11 Upstream-Status: Submitted
13 Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
14 Tested-by: Du Dolpher <dolpher.du@intel.com>
16 extlinux/Makefile | 3 +-
17 extlinux/main.c | 167 +-------------------------------------------
18 libinstaller/syslinuxext.c | 170 +++++++++++++++++++++++++++++++++++++++++++++
19 3 files changed, 175 insertions(+), 165 deletions(-)
21 diff --git a/extlinux/Makefile b/extlinux/Makefile
22 index 02d1db5..90dd92f 100644
23 --- a/extlinux/Makefile
24 +++ b/extlinux/Makefile
25 @@ -31,7 +31,8 @@ SRCS = main.c \
26 ../libinstaller/advio.c \
27 ../libinstaller/bootsect_bin.c \
28 ../libinstaller/ldlinuxc32_bin.c \
29 - ../libinstaller/ldlinux_bin.c
30 + ../libinstaller/ldlinux_bin.c \
31 + ../libinstaller/syslinuxext.c
32 OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
34 .SUFFIXES: .c .o .i .s .S
35 diff --git a/extlinux/main.c b/extlinux/main.c
36 index 09740bd..6fe026e 100644
41 #include "syslxopt.h" /* unified options */
42 #include "mountinfo.h"
43 +#include "syslinuxext.h"
46 # define dprintf printf
48 # define dprintf(...) ((void)0)
51 -#ifndef EXT2_SUPER_OFFSET
52 -#define EXT2_SUPER_OFFSET 1024
55 /* Since we have unused 2048 bytes in the primary AG of an XFS partition,
56 * we will use the first 0~512 bytes starting from 2048 for the Syslinux
58 @@ -92,136 +89,6 @@ static char subvol[BTRFS_SUBVOL_MAX];
62 - * Get the size of a block device
64 -static uint64_t get_size(int devfd)
71 - if (!ioctl(devfd, BLKGETSIZE64, &bytes))
74 - if (!ioctl(devfd, BLKGETSIZE, §s))
75 - return (uint64_t) sects << 9;
76 - else if (!fstat(devfd, &st) && st.st_size)
83 - * Get device geometry and partition offset
85 -struct geometry_table {
87 - struct hd_geometry g;
90 -static int sysfs_get_offset(int devfd, unsigned long *start)
93 - char sysfs_name[128];
97 - if (fstat(devfd, &st))
100 - if ((size_t)snprintf(sysfs_name, sizeof sysfs_name,
101 - "/sys/dev/block/%u:%u/start",
102 - major(st.st_rdev), minor(st.st_rdev))
103 - >= sizeof sysfs_name)
106 - f = fopen(sysfs_name, "r");
110 - rv = fscanf(f, "%lu", start);
113 - return (rv == 1) ? 0 : -1;
116 -/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
117 - (x/64/32) is the final fallback. I don't know what LS-240 has
118 - as its geometry, since I don't have one and don't know anyone that does,
119 - and Google wasn't helpful... */
120 -static const struct geometry_table standard_geometries[] = {
121 - {360 * 1024, {2, 9, 40, 0}},
122 - {720 * 1024, {2, 9, 80, 0}},
123 - {1200 * 1024, {2, 15, 80, 0}},
124 - {1440 * 1024, {2, 18, 80, 0}},
125 - {1680 * 1024, {2, 21, 80, 0}},
126 - {1722 * 1024, {2, 21, 80, 0}},
127 - {2880 * 1024, {2, 36, 80, 0}},
128 - {3840 * 1024, {2, 48, 80, 0}},
129 - {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */
133 -int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
135 - struct floppy_struct fd_str;
136 - struct loop_info li;
137 - struct loop_info64 li64;
138 - const struct geometry_table *gp;
141 - memset(geo, 0, sizeof *geo);
143 - if (!ioctl(devfd, HDIO_GETGEO, geo)) {
145 - } else if (!ioctl(devfd, FDGETPRM, &fd_str)) {
146 - geo->heads = fd_str.head;
147 - geo->sectors = fd_str.sect;
148 - geo->cylinders = fd_str.track;
153 - /* Didn't work. Let's see if this is one of the standard geometries */
154 - for (gp = standard_geometries; gp->bytes; gp++) {
155 - if (gp->bytes == totalbytes) {
156 - memcpy(geo, &gp->g, sizeof *geo);
161 - /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is
162 - what zipdisks use, so this would help if someone has a USB key that
163 - they're booting in USB-ZIP mode. */
165 - geo->heads = opt.heads ? : 64;
166 - geo->sectors = opt.sectors ? : 32;
167 - geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT);
170 - if (!opt.sectors && !opt.heads) {
172 - "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n"
173 - " (on hard disks, this is usually harmless.)\n",
174 - geo->heads, geo->sectors);
175 - rv = 1; /* Suboptimal result */
179 - /* If this is a loopback device, try to set the start */
180 - if (!ioctl(devfd, LOOP_GET_STATUS64, &li64))
181 - geo->start = li64.lo_offset >> SECTOR_SHIFT;
182 - else if (!ioctl(devfd, LOOP_GET_STATUS, &li))
183 - geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT;
184 - else if (!sysfs_get_offset(devfd, &geo->start)) {
192 * Query the device geometry and put it into the boot sector.
193 * Map the file and put the map in the boot sector and file.
194 * Stick the "current directory" inode number into the file.
195 @@ -231,11 +98,8 @@ ok:
196 static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
198 struct stat dirst, xdst;
199 - struct hd_geometry geo;
201 - uint64_t totalbytes, totalsectors;
203 - struct fat_boot_sector *sbs;
204 char *dirpath, *subpath, *xdirpath;
207 @@ -279,33 +143,8 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
208 /* Now subpath should contain the path relative to the fs base */
209 dprintf("subpath = %s\n", subpath);
211 - totalbytes = get_size(devfd);
212 - get_geometry(devfd, totalbytes, &geo);
215 - geo.heads = opt.heads;
217 - geo.sectors = opt.sectors;
219 - /* Patch this into a fake FAT superblock. This isn't because
220 - FAT is a good format in any way, it's because it lets the
221 - early bootstrap share code with the FAT version. */
222 - dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
224 - sbs = (struct fat_boot_sector *)syslinux_bootsect;
226 - totalsectors = totalbytes >> SECTOR_SHIFT;
227 - if (totalsectors >= 65536) {
228 - set_16(&sbs->bsSectors, 0);
230 - set_16(&sbs->bsSectors, totalsectors);
232 - set_32(&sbs->bsHugeSectors, totalsectors);
234 - set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
235 - set_16(&sbs->bsSecPerTrack, geo.sectors);
236 - set_16(&sbs->bsHeads, geo.heads);
237 - set_32(&sbs->bsHiddenSecs, geo.start);
238 + /* Patch syslinux_bootsect */
239 + syslinux_patch_bootsect(devfd);
241 /* Construct the boot file map */
243 diff --git a/libinstaller/syslinuxext.c b/libinstaller/syslinuxext.c
244 index bb54cef..5a4423b 100644
245 --- a/libinstaller/syslinuxext.c
246 +++ b/libinstaller/syslinuxext.c
250 +#include <sys/stat.h>
251 +#include <sys/types.h>
253 +#include <ext2fs/ext2fs.h>
255 +#include "linuxioctl.h"
256 +#include "syslinux.h"
257 +#include "syslxint.h"
258 +#include "syslxopt.h"
261 + * Get the size of a block device
263 +static uint64_t get_size(int dev_fd)
270 + if (!ioctl(dev_fd, BLKGETSIZE64, &bytes))
273 + if (!ioctl(dev_fd, BLKGETSIZE, §s))
274 + return (uint64_t) sects << 9;
275 + else if (!fstat(dev_fd, &st) && st.st_size)
282 + * Get device geometry and partition offset
284 +static struct geometry_table {
286 + struct hd_geometry g;
289 +static int sysfs_get_offset(int dev_fd, unsigned long *start)
292 + char sysfs_name[128];
296 + if (fstat(dev_fd, &st))
299 + if ((size_t)snprintf(sysfs_name, sizeof sysfs_name,
300 + "/sys/dev/block/%u:%u/start",
301 + major(st.st_rdev), minor(st.st_rdev))
302 + >= sizeof sysfs_name)
305 + f = fopen(sysfs_name, "r");
309 + rv = fscanf(f, "%lu", start);
312 + return (rv == 1) ? 0 : -1;
315 +/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
316 + (x/64/32) is the final fallback. I don't know what LS-240 has
317 + as its geometry, since I don't have one and don't know anyone that does,
318 + and Google wasn't helpful... */
319 +static const struct geometry_table standard_geometries[] = {
320 + {360 * 1024, {2, 9, 40, 0}},
321 + {720 * 1024, {2, 9, 80, 0}},
322 + {1200 * 1024, {2, 15, 80, 0}},
323 + {1440 * 1024, {2, 18, 80, 0}},
324 + {1680 * 1024, {2, 21, 80, 0}},
325 + {1722 * 1024, {2, 21, 80, 0}},
326 + {2880 * 1024, {2, 36, 80, 0}},
327 + {3840 * 1024, {2, 48, 80, 0}},
328 + {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */
332 +static int get_geometry(int dev_fd, uint64_t totalbytes, struct hd_geometry *geo)
334 + struct floppy_struct fd_str;
335 + struct loop_info li;
336 + struct loop_info64 li64;
337 + const struct geometry_table *gp;
340 + memset(geo, 0, sizeof *geo);
342 + if (!ioctl(dev_fd, HDIO_GETGEO, geo)) {
344 + } else if (!ioctl(dev_fd, FDGETPRM, &fd_str)) {
345 + geo->heads = fd_str.head;
346 + geo->sectors = fd_str.sect;
347 + geo->cylinders = fd_str.track;
352 + /* Didn't work. Let's see if this is one of the standard geometries */
353 + for (gp = standard_geometries; gp->bytes; gp++) {
354 + if (gp->bytes == totalbytes) {
355 + memcpy(geo, &gp->g, sizeof *geo);
360 + /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is
361 + what zipdisks use, so this would help if someone has a USB key that
362 + they're booting in USB-ZIP mode. */
364 + geo->heads = opt.heads ? : 64;
365 + geo->sectors = opt.sectors ? : 32;
366 + geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT);
369 + if (!opt.sectors && !opt.heads) {
371 + "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n"
372 + " (on hard disks, this is usually harmless.)\n",
373 + geo->heads, geo->sectors);
374 + rv = 1; /* Suboptimal result */
378 + /* If this is a loopback device, try to set the start */
379 + if (!ioctl(dev_fd, LOOP_GET_STATUS64, &li64))
380 + geo->start = li64.lo_offset >> SECTOR_SHIFT;
381 + else if (!ioctl(dev_fd, LOOP_GET_STATUS, &li))
382 + geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT;
383 + else if (!sysfs_get_offset(dev_fd, &geo->start)) {
391 /* Patch syslinux_bootsect */
392 void syslinux_patch_bootsect(int dev_fd)
394 + uint64_t totalbytes, totalsectors;
395 + struct hd_geometry geo;
396 + struct fat_boot_sector *sbs;
398 + totalbytes = get_size(dev_fd);
399 + get_geometry(dev_fd, totalbytes, &geo);
402 + geo.heads = opt.heads;
404 + geo.sectors = opt.sectors;
406 + /* Patch this into a fake FAT superblock. This isn't because
407 + FAT is a good format in any way, it's because it lets the
408 + early bootstrap share code with the FAT version. */
409 + sbs = (struct fat_boot_sector *)syslinux_bootsect;
411 + totalsectors = totalbytes >> SECTOR_SHIFT;
412 + if (totalsectors >= 65536) {
413 + set_16(&sbs->bsSectors, 0);
415 + set_16(&sbs->bsSectors, totalsectors);
417 + set_32(&sbs->bsHugeSectors, totalsectors);
419 + set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
420 + set_16(&sbs->bsSecPerTrack, geo.sectors);
421 + set_16(&sbs->bsHeads, geo.heads);
422 + set_32(&sbs->bsHiddenSecs, geo.start);