1 /* ----------------------------------------------------------------------- *
3 * Copyright 2010 Intel Corp. - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 * Boston MA 02111-1307, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
16 * common functions for extlinux & syslinux installer
30 #include <sys/types.h>
31 #include <sys/mount.h>
34 #include "linuxioctl.h"
43 # define dprintf printf
45 # define dprintf(...) ((void)0)
48 #define SECTOR_SHIFT 9
50 static void die(const char *msg)
57 * read/write wrapper functions
59 ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
61 char *bufp = (char *)buf;
66 rv = pread(fd, bufp, count, offset);
69 } else if (rv == -1) {
86 ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
88 const char *bufp = (const char *)buf;
93 rv = pwrite(fd, bufp, count, offset);
96 } else if (rv == -1) {
100 die(strerror(errno));
114 * Set and clear file attributes
116 void clear_attributes(int fd)
120 if (!fstat(fd, &st)) {
126 if (!ioctl(fd, FS_IOC_GETFLAGS, &flags)) {
127 flags &= ~FS_IMMUTABLE_FL;
128 ioctl(fd, FS_IOC_SETFLAGS, &flags);
134 uint32_t attr = 0x00; /* Clear all attributes */
135 ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
143 fchmod(fd, st.st_mode | S_IWUSR);
147 void set_attributes(int fd)
151 if (!fstat(fd, &st)) {
152 fchmod(fd, st.st_mode & (S_IRUSR | S_IRGRP | S_IROTH));
158 if (st.st_uid == 0 && !ioctl(fd, FS_IOC_GETFLAGS, &flags)) {
159 flags |= FS_IMMUTABLE_FL;
160 ioctl(fd, FS_IOC_SETFLAGS, &flags);
166 uint32_t attr = 0x07; /* Hidden+System+Readonly */
167 ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
178 /* New FIEMAP based mapping */
179 static int sectmap_fie(int fd, sector_t *sectors, int nsectors)
182 struct fiemap_extent *fe;
183 unsigned int i, nsec;
184 sector_t sec, *secp, *esec;
191 fm = alloca(sizeof(struct fiemap)
192 + nsectors * sizeof(struct fiemap_extent));
194 memset(fm, 0, sizeof *fm);
196 maplen = (uint64_t)nsectors << SECTOR_SHIFT;
197 if (maplen > (uint64_t)st.st_size)
201 fm->fm_length = maplen;
202 fm->fm_flags = FIEMAP_FLAG_SYNC;
203 fm->fm_extent_count = nsectors;
205 if (ioctl(fd, FS_IOC_FIEMAP, fm))
208 memset(sectors, 0, nsectors * sizeof *sectors);
209 esec = sectors + nsectors;
213 if (fm->fm_mapped_extents < 1 ||
214 !(fe[fm->fm_mapped_extents-1].fe_flags & FIEMAP_EXTENT_LAST))
217 for (i = 0; i < fm->fm_mapped_extents; i++) {
218 if (fe->fe_flags & FIEMAP_EXTENT_LAST) {
219 /* If this is the *final* extent, pad the length */
220 fe->fe_length = (fe->fe_length + SECTOR_SIZE - 1)
221 & ~(SECTOR_SIZE - 1);
224 if ((fe->fe_logical | fe->fe_physical| fe->fe_length) &
228 if (fe->fe_flags & (FIEMAP_EXTENT_UNKNOWN|
229 FIEMAP_EXTENT_DELALLOC|
230 FIEMAP_EXTENT_ENCODED|
231 FIEMAP_EXTENT_DATA_ENCRYPTED|
232 FIEMAP_EXTENT_UNWRITTEN))
235 secp = sectors + (fe->fe_logical >> SECTOR_SHIFT);
236 sec = fe->fe_physical >> SECTOR_SHIFT;
237 nsec = fe->fe_length >> SECTOR_SHIFT;
251 /* Legacy FIBMAP based mapping */
252 static int sectmap_fib(int fd, sector_t *sectors, int nsectors)
254 unsigned int blk, nblk;
256 unsigned int blksize;
260 if (ioctl(fd, FIGETBSZ, &blksize))
263 /* Number of sectors per block */
264 blksize >>= SECTOR_SHIFT;
269 if (ioctl(fd, FIBMAP, &blk))
272 sec = (sector_t)blk * blksize;
273 for (i = 0; i < blksize; i++) {
286 int sectmap(int fd, sector_t *sectors, int nsectors)
288 if (!sectmap_fie(fd, sectors, nsectors))
291 return sectmap_fib(fd, sectors, nsectors);
295 * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
296 * sector; this is consistent with FAT filesystems. Earlier versions
297 * would install the string "EXTLINUX" instead, handle both.
299 int syslinux_already_installed(int dev_fd)
303 xpread(dev_fd, buffer, 8, 3);
304 return !memcmp(buffer, "SYSLINUX", 8) || !memcmp(buffer, "EXTLINUX", 8);