]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/blob
f1d01fa43cc0b16bf69008ab1d33eca6979a7eac
[thirdparty/openembedded/openembedded-core-contrib.git] /
1 From efce87e5ab98664c57e5f4e3955a2f3747df5737 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] libinstaller/syslinuxext: implement syslinux_patch_bootsect()
5
6 Move the related from extlinux/main.c to libinstaller/syslinuxext.c, the
7 syslinux_patch_bootsect() are used by both extlinux/main.c and
8 linux/syslinux.c.
9
10 Upstream-Status: Submitted
11
12 Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
13 Tested-by: Du Dolpher <dolpher.du@intel.com>
14
15 Edited to include sysmacros.h
16
17 Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
18 ---
19 extlinux/Makefile | 3 +-
20 extlinux/main.c | 167 +-----------------------------------
21 libinstaller/syslinuxext.c | 171 +++++++++++++++++++++++++++++++++++++
22 3 files changed, 176 insertions(+), 165 deletions(-)
23
24 diff --git a/extlinux/Makefile b/extlinux/Makefile
25 index 1721ee54..62a49728 100644
26 --- a/extlinux/Makefile
27 +++ b/extlinux/Makefile
28 @@ -32,7 +32,8 @@ SRCS = main.c \
29 ../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
38 diff --git a/extlinux/main.c b/extlinux/main.c
39 index ebff7eae..9add50fb 100644
40 --- a/extlinux/main.c
41 +++ b/extlinux/main.c
42 @@ -62,6 +62,7 @@
43 #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
50 @@ -69,10 +70,6 @@
51 # 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.
61 @@ -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 \
63 - 2*ADV_SIZE)
64
65 -/*
66 - * 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 -
195 /*
196 * 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.
198 @@ -233,11 +100,8 @@ ok:
199 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
210 @@ -281,33 +145,8 @@ static int patch_file_and_bootblock(int fd, const char *dir, int devfd)
211 /* 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
246 diff --git a/libinstaller/syslinuxext.c b/libinstaller/syslinuxext.c
247 index bb54cefc..9ae82884 100644
248 --- a/libinstaller/syslinuxext.c
249 +++ b/libinstaller/syslinuxext.c
250 @@ -1,7 +1,178 @@
251 #define _GNU_SOURCE
252
253 +#include <sys/stat.h>
254 +#include <sys/types.h>
255 +#include <sys/sysmacros.h>
256 +#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
429 --
430 2.17.1
431