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"
44 # define dprintf printf
46 # define dprintf(...) ((void)0)
49 #define SECTOR_SHIFT 9
52 * Set and clear file attributes
54 void clear_attributes(int fd
)
58 if (!fstat(fd
, &st
)) {
64 if (!ioctl(fd
, FS_IOC_GETFLAGS
, &flags
)) {
65 flags
&= ~FS_IMMUTABLE_FL
;
66 ioctl(fd
, FS_IOC_SETFLAGS
, &flags
);
72 uint32_t attr
= 0x00; /* Clear all attributes */
73 ioctl(fd
, FAT_IOCTL_SET_ATTRIBUTES
, &attr
);
81 fchmod(fd
, st
.st_mode
| S_IWUSR
);
85 void set_attributes(int fd
)
89 if (!fstat(fd
, &st
)) {
90 fchmod(fd
, st
.st_mode
& (S_IRUSR
| S_IRGRP
| S_IROTH
));
96 if (st
.st_uid
== 0 && !ioctl(fd
, FS_IOC_GETFLAGS
, &flags
)) {
97 flags
|= FS_IMMUTABLE_FL
;
98 ioctl(fd
, FS_IOC_SETFLAGS
, &flags
);
104 uint32_t attr
= 0x07; /* Hidden+System+Readonly */
105 ioctl(fd
, FAT_IOCTL_SET_ATTRIBUTES
, &attr
);
116 /* New FIEMAP based mapping */
117 static int sectmap_fie(int fd
, sector_t
*sectors
, int nsectors
)
120 struct fiemap_extent
*fe
;
121 unsigned int i
, nsec
;
122 sector_t sec
, *secp
, *esec
;
129 fm
= alloca(sizeof(struct fiemap
)
130 + nsectors
* sizeof(struct fiemap_extent
));
132 memset(fm
, 0, sizeof *fm
);
134 maplen
= (uint64_t)nsectors
<< SECTOR_SHIFT
;
135 if (maplen
> (uint64_t)st
.st_size
)
139 fm
->fm_length
= maplen
;
140 fm
->fm_flags
= FIEMAP_FLAG_SYNC
;
141 fm
->fm_extent_count
= nsectors
;
143 if (ioctl(fd
, FS_IOC_FIEMAP
, fm
))
146 memset(sectors
, 0, nsectors
* sizeof *sectors
);
147 esec
= sectors
+ nsectors
;
151 if (fm
->fm_mapped_extents
< 1 ||
152 !(fe
[fm
->fm_mapped_extents
-1].fe_flags
& FIEMAP_EXTENT_LAST
))
155 for (i
= 0; i
< fm
->fm_mapped_extents
; i
++) {
156 if (fe
->fe_flags
& FIEMAP_EXTENT_LAST
) {
157 /* If this is the *final* extent, pad the length */
158 fe
->fe_length
= (fe
->fe_length
+ SECTOR_SIZE
- 1)
159 & ~(SECTOR_SIZE
- 1);
162 if ((fe
->fe_logical
| fe
->fe_physical
| fe
->fe_length
) &
166 if (fe
->fe_flags
& (FIEMAP_EXTENT_UNKNOWN
|
167 FIEMAP_EXTENT_DELALLOC
|
168 FIEMAP_EXTENT_ENCODED
|
169 FIEMAP_EXTENT_DATA_ENCRYPTED
|
170 FIEMAP_EXTENT_UNWRITTEN
))
173 secp
= sectors
+ (fe
->fe_logical
>> SECTOR_SHIFT
);
174 sec
= fe
->fe_physical
>> SECTOR_SHIFT
;
175 nsec
= fe
->fe_length
>> SECTOR_SHIFT
;
189 /* Legacy FIBMAP based mapping */
190 static int sectmap_fib(int fd
, sector_t
*sectors
, int nsectors
)
192 unsigned int blk
, nblk
;
194 unsigned int blksize
;
198 if (ioctl(fd
, FIGETBSZ
, &blksize
))
201 /* Number of sectors per block */
202 blksize
>>= SECTOR_SHIFT
;
207 if (ioctl(fd
, FIBMAP
, &blk
))
210 sec
= (sector_t
)blk
* blksize
;
211 for (i
= 0; i
< blksize
; i
++) {
224 int sectmap(int fd
, sector_t
*sectors
, int nsectors
)
226 if (!sectmap_fie(fd
, sectors
, nsectors
))
229 return sectmap_fib(fd
, sectors
, nsectors
);
233 * SYSLINUX installs the string 'SYSLINUX' at offset 3 in the boot
234 * sector; this is consistent with FAT filesystems. Earlier versions
235 * would install the string "EXTLINUX" instead, handle both.
237 int syslinux_already_installed(int dev_fd
)
241 xpread(dev_fd
, buffer
, 8, 3);
242 return !memcmp(buffer
, "SYSLINUX", 8) || !memcmp(buffer
, "EXTLINUX", 8);