blob: b026eba5ad4cb44b1d0396c3953d65311c5825f2 [file] [log] [blame]
Patrick Williams92b42cb2022-09-03 06:53:57 -05001From acfc8214d3d60b7e251ae66a59b81cdd1ff7a6dc Mon Sep 17 00:00:00 2001
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002From: Robert Yang <liezhi.yang@windriver.com>
3Date: Fri, 2 Jan 2015 12:26:46 +0800
Brad Bishop19323692019-04-05 15:28:33 -04004Subject: [PATCH] libinstaller/syslinuxext: implement syslinux_patch_bootsect()
Patrick Williamsc124f4f2015-09-15 14:41:29 -05005
6Move the related from extlinux/main.c to libinstaller/syslinuxext.c, the
7syslinux_patch_bootsect() are used by both extlinux/main.c and
8linux/syslinux.c.
9
10Upstream-Status: Submitted
11
12Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
13Tested-by: Du Dolpher <dolpher.du@intel.com>
Brad Bishop19323692019-04-05 15:28:33 -040014
15Edited to include sysmacros.h
16
17Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
Patrick Williamsc124f4f2015-09-15 14:41:29 -050018---
19 extlinux/Makefile | 3 +-
Brad Bishop19323692019-04-05 15:28:33 -040020 extlinux/main.c | 167 +-----------------------------------
21 libinstaller/syslinuxext.c | 171 +++++++++++++++++++++++++++++++++++++
22 3 files changed, 176 insertions(+), 165 deletions(-)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050023
24diff --git a/extlinux/Makefile b/extlinux/Makefile
Patrick Williams92b42cb2022-09-03 06:53:57 -050025index 1721ee5..62a4972 100644
Patrick Williamsc124f4f2015-09-15 14:41:29 -050026--- a/extlinux/Makefile
27+++ b/extlinux/Makefile
Brad Bishop19323692019-04-05 15:28:33 -040028@@ -32,7 +32,8 @@ SRCS = main.c \
Patrick Williamsc124f4f2015-09-15 14:41:29 -050029 ../libinstaller/advio.c \
30 ../libinstaller/bootsect_bin.c \
31 ../libinstaller/ldlinuxc32_bin.c \
32- ../libinstaller/ldlinux_bin.c
33+ ../libinstaller/ldlinux_bin.c \
34+ ../libinstaller/syslinuxext.c
35 OBJS = $(patsubst %.c,%.o,$(notdir $(SRCS)))
36
37 .SUFFIXES: .c .o .i .s .S
38diff --git a/extlinux/main.c b/extlinux/main.c
Patrick Williams92b42cb2022-09-03 06:53:57 -050039index ebff7ea..9add50f 100644
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040--- a/extlinux/main.c
41+++ b/extlinux/main.c
Brad Bishop19323692019-04-05 15:28:33 -040042@@ -62,6 +62,7 @@
Patrick Williamsc124f4f2015-09-15 14:41:29 -050043 #include "setadv.h"
44 #include "syslxopt.h" /* unified options */
45 #include "mountinfo.h"
46+#include "syslinuxext.h"
47
48 #ifdef DEBUG
49 # define dprintf printf
Brad Bishop19323692019-04-05 15:28:33 -040050@@ -69,10 +70,6 @@
Patrick Williamsc124f4f2015-09-15 14:41:29 -050051 # define dprintf(...) ((void)0)
52 #endif
53
54-#ifndef EXT2_SUPER_OFFSET
55-#define EXT2_SUPER_OFFSET 1024
56-#endif
57-
58 /* Since we have unused 2048 bytes in the primary AG of an XFS partition,
59 * we will use the first 0~512 bytes starting from 2048 for the Syslinux
60 * boot sector.
Brad Bishop19323692019-04-05 15:28:33 -040061@@ -93,136 +90,6 @@ static char subvol[BTRFS_SUBVOL_MAX];
62 #define BTRFS_ADV_OFFSET (BTRFS_BOOT_AREA_A_OFFSET + BTRFS_BOOT_AREA_A_SIZE \
Patrick Williamsc124f4f2015-09-15 14:41:29 -050063 - 2*ADV_SIZE)
64
Brad Bishop19323692019-04-05 15:28:33 -040065-/*
Patrick Williamsc124f4f2015-09-15 14:41:29 -050066- * Get the size of a block device
67- */
68-static uint64_t get_size(int devfd)
69-{
70- uint64_t bytes;
71- uint32_t sects;
72- struct stat st;
73-
74-#ifdef BLKGETSIZE64
75- if (!ioctl(devfd, BLKGETSIZE64, &bytes))
76- return bytes;
77-#endif
78- if (!ioctl(devfd, BLKGETSIZE, &sects))
79- return (uint64_t) sects << 9;
80- else if (!fstat(devfd, &st) && st.st_size)
81- return st.st_size;
82- else
83- return 0;
84-}
85-
86-/*
87- * Get device geometry and partition offset
88- */
89-struct geometry_table {
90- uint64_t bytes;
91- struct hd_geometry g;
92-};
93-
94-static int sysfs_get_offset(int devfd, unsigned long *start)
95-{
96- struct stat st;
97- char sysfs_name[128];
98- FILE *f;
99- int rv;
100-
101- if (fstat(devfd, &st))
102- return -1;
103-
104- if ((size_t)snprintf(sysfs_name, sizeof sysfs_name,
105- "/sys/dev/block/%u:%u/start",
106- major(st.st_rdev), minor(st.st_rdev))
107- >= sizeof sysfs_name)
108- return -1;
109-
110- f = fopen(sysfs_name, "r");
111- if (!f)
112- return -1;
113-
114- rv = fscanf(f, "%lu", start);
115- fclose(f);
116-
117- return (rv == 1) ? 0 : -1;
118-}
119-
120-/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
121- (x/64/32) is the final fallback. I don't know what LS-240 has
122- as its geometry, since I don't have one and don't know anyone that does,
123- and Google wasn't helpful... */
124-static const struct geometry_table standard_geometries[] = {
125- {360 * 1024, {2, 9, 40, 0}},
126- {720 * 1024, {2, 9, 80, 0}},
127- {1200 * 1024, {2, 15, 80, 0}},
128- {1440 * 1024, {2, 18, 80, 0}},
129- {1680 * 1024, {2, 21, 80, 0}},
130- {1722 * 1024, {2, 21, 80, 0}},
131- {2880 * 1024, {2, 36, 80, 0}},
132- {3840 * 1024, {2, 48, 80, 0}},
133- {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */
134- {0, {0, 0, 0, 0}}
135-};
136-
137-int get_geometry(int devfd, uint64_t totalbytes, struct hd_geometry *geo)
138-{
139- struct floppy_struct fd_str;
140- struct loop_info li;
141- struct loop_info64 li64;
142- const struct geometry_table *gp;
143- int rv = 0;
144-
145- memset(geo, 0, sizeof *geo);
146-
147- if (!ioctl(devfd, HDIO_GETGEO, geo)) {
148- goto ok;
149- } else if (!ioctl(devfd, FDGETPRM, &fd_str)) {
150- geo->heads = fd_str.head;
151- geo->sectors = fd_str.sect;
152- geo->cylinders = fd_str.track;
153- geo->start = 0;
154- goto ok;
155- }
156-
157- /* Didn't work. Let's see if this is one of the standard geometries */
158- for (gp = standard_geometries; gp->bytes; gp++) {
159- if (gp->bytes == totalbytes) {
160- memcpy(geo, &gp->g, sizeof *geo);
161- goto ok;
162- }
163- }
164-
165- /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is
166- what zipdisks use, so this would help if someone has a USB key that
167- they're booting in USB-ZIP mode. */
168-
169- geo->heads = opt.heads ? : 64;
170- geo->sectors = opt.sectors ? : 32;
171- geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT);
172- geo->start = 0;
173-
174- if (!opt.sectors && !opt.heads) {
175- fprintf(stderr,
176- "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n"
177- " (on hard disks, this is usually harmless.)\n",
178- geo->heads, geo->sectors);
179- rv = 1; /* Suboptimal result */
180- }
181-
182-ok:
183- /* If this is a loopback device, try to set the start */
184- if (!ioctl(devfd, LOOP_GET_STATUS64, &li64))
185- geo->start = li64.lo_offset >> SECTOR_SHIFT;
186- else if (!ioctl(devfd, LOOP_GET_STATUS, &li))
187- geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT;
188- else if (!sysfs_get_offset(devfd, &geo->start)) {
189- /* OK */
190- }
191-
192- return rv;
193-}
194-
Brad Bishop19323692019-04-05 15:28:33 -0400195 /*
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500196 * Query the device geometry and put it into the boot sector.
197 * Map the file and put the map in the boot sector and file.
Brad Bishop19323692019-04-05 15:28:33 -0400198@@ -233,11 +100,8 @@ ok:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500199 static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
200 {
201 struct stat dirst, xdst;
202- struct hd_geometry geo;
203 sector_t *sectp;
204- uint64_t totalbytes, totalsectors;
205 int nsect;
206- struct fat_boot_sector *sbs;
207 char *dirpath, *subpath, *xdirpath;
208 int rv;
209
Brad Bishop19323692019-04-05 15:28:33 -0400210@@ -281,33 +145,8 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500211 /* Now subpath should contain the path relative to the fs base */
212 dprintf("subpath = %s\n", subpath);
213
214- totalbytes = get_size(devfd);
215- get_geometry(devfd, totalbytes, &geo);
216-
217- if (opt.heads)
218- geo.heads = opt.heads;
219- if (opt.sectors)
220- geo.sectors = opt.sectors;
221-
222- /* Patch this into a fake FAT superblock. This isn't because
223- FAT is a good format in any way, it's because it lets the
224- early bootstrap share code with the FAT version. */
225- dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
226-
227- sbs = (struct fat_boot_sector *)syslinux_bootsect;
228-
229- totalsectors = totalbytes >> SECTOR_SHIFT;
230- if (totalsectors >= 65536) {
231- set_16(&sbs->bsSectors, 0);
232- } else {
233- set_16(&sbs->bsSectors, totalsectors);
234- }
235- set_32(&sbs->bsHugeSectors, totalsectors);
236-
237- set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
238- set_16(&sbs->bsSecPerTrack, geo.sectors);
239- set_16(&sbs->bsHeads, geo.heads);
240- set_32(&sbs->bsHiddenSecs, geo.start);
241+ /* Patch syslinux_bootsect */
242+ syslinux_patch_bootsect(devfd);
243
244 /* Construct the boot file map */
245
246diff --git a/libinstaller/syslinuxext.c b/libinstaller/syslinuxext.c
Patrick Williams92b42cb2022-09-03 06:53:57 -0500247index bb54cef..9ae8288 100644
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500248--- a/libinstaller/syslinuxext.c
249+++ b/libinstaller/syslinuxext.c
Brad Bishop19323692019-04-05 15:28:33 -0400250@@ -1,7 +1,178 @@
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251 #define _GNU_SOURCE
252
253+#include <sys/stat.h>
254+#include <sys/types.h>
Brad Bishop19323692019-04-05 15:28:33 -0400255+#include <sys/sysmacros.h>
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500256+#include <getopt.h>
257+#include <ext2fs/ext2fs.h>
258+
259+#include "linuxioctl.h"
260+#include "syslinux.h"
261+#include "syslxint.h"
262+#include "syslxopt.h"
263+
264+/*
265+ * Get the size of a block device
266+ */
267+static uint64_t get_size(int dev_fd)
268+{
269+ uint64_t bytes;
270+ uint32_t sects;
271+ struct stat st;
272+
273+#ifdef BLKGETSIZE64
274+ if (!ioctl(dev_fd, BLKGETSIZE64, &bytes))
275+ return bytes;
276+#endif
277+ if (!ioctl(dev_fd, BLKGETSIZE, &sects))
278+ return (uint64_t) sects << 9;
279+ else if (!fstat(dev_fd, &st) && st.st_size)
280+ return st.st_size;
281+ else
282+ return 0;
283+}
284+
285+/*
286+ * Get device geometry and partition offset
287+ */
288+static struct geometry_table {
289+ uint64_t bytes;
290+ struct hd_geometry g;
291+};
292+
293+static int sysfs_get_offset(int dev_fd, unsigned long *start)
294+{
295+ struct stat st;
296+ char sysfs_name[128];
297+ FILE *f;
298+ int rv;
299+
300+ if (fstat(dev_fd, &st))
301+ return -1;
302+
303+ if ((size_t)snprintf(sysfs_name, sizeof sysfs_name,
304+ "/sys/dev/block/%u:%u/start",
305+ major(st.st_rdev), minor(st.st_rdev))
306+ >= sizeof sysfs_name)
307+ return -1;
308+
309+ f = fopen(sysfs_name, "r");
310+ if (!f)
311+ return -1;
312+
313+ rv = fscanf(f, "%lu", start);
314+ fclose(f);
315+
316+ return (rv == 1) ? 0 : -1;
317+}
318+
319+/* Standard floppy disk geometries, plus LS-120. Zipdisk geometry
320+ (x/64/32) is the final fallback. I don't know what LS-240 has
321+ as its geometry, since I don't have one and don't know anyone that does,
322+ and Google wasn't helpful... */
323+static const struct geometry_table standard_geometries[] = {
324+ {360 * 1024, {2, 9, 40, 0}},
325+ {720 * 1024, {2, 9, 80, 0}},
326+ {1200 * 1024, {2, 15, 80, 0}},
327+ {1440 * 1024, {2, 18, 80, 0}},
328+ {1680 * 1024, {2, 21, 80, 0}},
329+ {1722 * 1024, {2, 21, 80, 0}},
330+ {2880 * 1024, {2, 36, 80, 0}},
331+ {3840 * 1024, {2, 48, 80, 0}},
332+ {123264 * 1024, {8, 32, 963, 0}}, /* LS120 */
333+ {0, {0, 0, 0, 0}}
334+};
335+
336+static int get_geometry(int dev_fd, uint64_t totalbytes, struct hd_geometry *geo)
337+{
338+ struct floppy_struct fd_str;
339+ struct loop_info li;
340+ struct loop_info64 li64;
341+ const struct geometry_table *gp;
342+ int rv = 0;
343+
344+ memset(geo, 0, sizeof *geo);
345+
346+ if (!ioctl(dev_fd, HDIO_GETGEO, geo)) {
347+ goto ok;
348+ } else if (!ioctl(dev_fd, FDGETPRM, &fd_str)) {
349+ geo->heads = fd_str.head;
350+ geo->sectors = fd_str.sect;
351+ geo->cylinders = fd_str.track;
352+ geo->start = 0;
353+ goto ok;
354+ }
355+
356+ /* Didn't work. Let's see if this is one of the standard geometries */
357+ for (gp = standard_geometries; gp->bytes; gp++) {
358+ if (gp->bytes == totalbytes) {
359+ memcpy(geo, &gp->g, sizeof *geo);
360+ goto ok;
361+ }
362+ }
363+
364+ /* Didn't work either... assign a geometry of 64 heads, 32 sectors; this is
365+ what zipdisks use, so this would help if someone has a USB key that
366+ they're booting in USB-ZIP mode. */
367+
368+ geo->heads = opt.heads ? : 64;
369+ geo->sectors = opt.sectors ? : 32;
370+ geo->cylinders = totalbytes / (geo->heads * geo->sectors << SECTOR_SHIFT);
371+ geo->start = 0;
372+
373+ if (!opt.sectors && !opt.heads) {
374+ fprintf(stderr,
375+ "Warning: unable to obtain device geometry (defaulting to %d heads, %d sectors)\n"
376+ " (on hard disks, this is usually harmless.)\n",
377+ geo->heads, geo->sectors);
378+ rv = 1; /* Suboptimal result */
379+ }
380+
381+ok:
382+ /* If this is a loopback device, try to set the start */
383+ if (!ioctl(dev_fd, LOOP_GET_STATUS64, &li64))
384+ geo->start = li64.lo_offset >> SECTOR_SHIFT;
385+ else if (!ioctl(dev_fd, LOOP_GET_STATUS, &li))
386+ geo->start = (unsigned int)li.lo_offset >> SECTOR_SHIFT;
387+ else if (!sysfs_get_offset(dev_fd, &geo->start)) {
388+ /* OK */
389+ }
390+
391+ return rv;
392+}
393+
394+
395 /* Patch syslinux_bootsect */
396 void syslinux_patch_bootsect(int dev_fd)
397 {
398+ uint64_t totalbytes, totalsectors;
399+ struct hd_geometry geo;
400+ struct fat_boot_sector *sbs;
401+
402+ totalbytes = get_size(dev_fd);
403+ get_geometry(dev_fd, totalbytes, &geo);
404+
405+ if (opt.heads)
406+ geo.heads = opt.heads;
407+ if (opt.sectors)
408+ geo.sectors = opt.sectors;
409+
410+ /* Patch this into a fake FAT superblock. This isn't because
411+ FAT is a good format in any way, it's because it lets the
412+ early bootstrap share code with the FAT version. */
413+ sbs = (struct fat_boot_sector *)syslinux_bootsect;
414+
415+ totalsectors = totalbytes >> SECTOR_SHIFT;
416+ if (totalsectors >= 65536) {
417+ set_16(&sbs->bsSectors, 0);
418+ } else {
419+ set_16(&sbs->bsSectors, totalsectors);
420+ }
421+ set_32(&sbs->bsHugeSectors, totalsectors);
422+
423+ set_16(&sbs->bsBytesPerSec, SECTOR_SIZE);
424+ set_16(&sbs->bsSecPerTrack, geo.sectors);
425+ set_16(&sbs->bsHeads, geo.heads);
426+ set_32(&sbs->bsHiddenSecs, geo.start);
427 }
428