1 /* ----------------------------------------------------------------------- * 2 * 3 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved 4 * Copyright 2009-2014 Intel Corporation; author: H. Peter Anvin 5 * Copyright 2011 Paulo Alcantara <pcacjr (at) gmail.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, Inc., 53 Temple Place Ste 330, 10 * Boston MA 02111-1307, USA; either version 2 of the License, or 11 * (at your option) any later version; incorporated herein by reference. 12 * 13 * ----------------------------------------------------------------------- */ 14 15 #ifndef SYSLXINT_H 16 #define SYSLXINT_H 17 18 #include "syslinux.h" 19 20 #if defined(__386__) || defined(__i386__) || defined(__x86_64__) 21 # define X86_MEM 1 /* Littleendian and unaligned safe */ 22 #else 23 # define X86_MEM 0 24 #endif 25 26 #ifdef __GNUC__ 27 # ifdef __MINGW32__ 28 /* gcc 4.7 miscompiles packed structures in MS-bitfield mode */ 29 # define PACKED __attribute__((packed,gcc_struct)) 30 # else 31 # define PACKED __attribute__((packed)) 32 # endif 33 #else 34 # error "Need to define PACKED for this compiler" 35 #endif 36 37 /* 38 * Access functions for littleendian numbers, possibly misaligned. 39 */ 40 static inline uint8_t get_8(const uint8_t * p) 41 { 42 return *p; 43 } 44 45 static inline uint16_t get_16(const uint16_t * p) 46 { 47 #if X86_MEM 48 /* Littleendian and unaligned-capable */ 49 return *p; 50 #else 51 const uint8_t *pp = (const uint8_t *)p; 52 return pp[0] + ((uint16_t)pp[1] << 8); 53 #endif 54 } 55 56 static inline uint32_t get_32(const uint32_t * p) 57 { 58 #if X86_MEM 59 /* Littleendian and unaligned-capable */ 60 return *p; 61 #else 62 const uint16_t *pp = (const uint16_t *)p; 63 return get_16(&pp[0]) + ((uint32_t)get_16(&pp[1]) << 16); 64 #endif 65 } 66 67 static inline uint64_t get_64(const uint64_t * p) 68 { 69 #if X86_MEM 70 /* Littleendian and unaligned-capable */ 71 return *p; 72 #else 73 const uint32_t *pp = (const uint32_t *)p; 74 return get_32(&pp[0]) + ((uint64_t)get_32(&pp[1]) << 32); 75 #endif 76 } 77 78 static inline void set_8(uint8_t *p, uint8_t v) 79 { 80 *p = v; 81 } 82 83 static inline void set_16(uint16_t *p, uint16_t v) 84 { 85 #if X86_MEM 86 /* Littleendian and unaligned-capable */ 87 *p = v; 88 #else 89 uint8_t *pp = (uint8_t *) p; 90 pp[0] = v; 91 pp[1] = v >> 8; 92 #endif 93 } 94 95 static inline void set_32(uint32_t *p, uint32_t v) 96 { 97 #if X86_MEM 98 /* Littleendian and unaligned-capable */ 99 *p = v; 100 #else 101 uint16_t *pp = (uint16_t *) p; 102 set_16(&pp[0], v); 103 set_16(&pp[1], v >> 16); 104 #endif 105 } 106 107 static inline void set_64(uint64_t *p, uint64_t v) 108 { 109 #if X86_MEM 110 /* Littleendian and unaligned-capable */ 111 *p = v; 112 #else 113 uint32_t *pp = (uint32_t *) p; 114 set_32(&pp[0], v); 115 set_32(&pp[1], v >> 32); 116 #endif 117 } 118 119 /* 120 * Special handling for the MS-DOS derivative: syslinux_ldlinux 121 * is a "far" object... 122 */ 123 #ifdef __MSDOS__ 124 125 uint8_t get_8_sl(const uint8_t _slimg * p); 126 uint16_t get_16_sl(const uint16_t _slimg * p); 127 uint32_t get_32_sl(const uint32_t _slimg * p); 128 uint64_t get_64_sl(const uint64_t _slimg * p); 129 void set_8_sl(uint8_t _slimg * p, uint8_t v); 130 void set_16_sl(uint16_t _slimg * p, uint16_t v); 131 void set_32_sl(uint32_t _slimg * p, uint32_t v); 132 void set_64_sl(uint64_t _slimg * p, uint64_t v); 133 void memcpy_to_sl(void _slimg *dst, const void *src, size_t len); 134 void memcpy_from_sl(void *dst, const void _slimg *src, size_t len); 135 void memset_sl(void _slimg *dst, int c, size_t len); 136 137 #else 138 139 /* Sane system ... */ 140 static inline uint8_t get_8_sl(const uint8_t _slimg * p) 141 { 142 return get_8((const uint8_t _force *)p); 143 } 144 static inline uint16_t get_16_sl(const uint16_t _slimg * p) 145 { 146 return get_16((const uint16_t _force *)p); 147 } 148 static inline uint32_t get_32_sl(const uint32_t _slimg * p) 149 { 150 return get_32((const uint32_t _force *)p); 151 } 152 static inline uint64_t get_64_sl(const uint64_t _slimg * p) 153 { 154 return get_64((const uint64_t _force *)p); 155 } 156 static inline void set_8_sl(uint8_t _slimg * p, uint8_t v) 157 { 158 set_8((uint8_t _force *)p, v); 159 } 160 static inline void set_16_sl(uint16_t _slimg * p, uint16_t v) 161 { 162 set_16((uint16_t _force *)p, v); 163 } 164 static inline void set_32_sl(uint32_t _slimg * p, uint32_t v) 165 { 166 set_32((uint32_t _force *)p, v); 167 } 168 static inline void set_64_sl(uint64_t _slimg * p, uint64_t v) 169 { 170 set_64((uint64_t _force *)p, v); 171 } 172 static inline void memcpy_to_sl(void _slimg *dst, const void *src, size_t len) 173 { 174 memcpy((void _force *)dst, src, len); 175 } 176 static inline void memcpy_from_sl(void *dst, const void _slimg *src, size_t len) 177 { 178 memcpy(dst, (const void _force *)src, len); 179 } 180 static inline void memset_sl(void _slimg *dst, int c, size_t len) 181 { 182 memset((void _force *)dst, c, len); 183 } 184 185 #endif 186 187 #define LDLINUX_MAGIC 0x3eb202fe 188 #define BS_MAGIC_VER (0x1b << 9) 189 190 /* Patch area for disk-based installers */ 191 struct patch_area { 192 uint32_t magic; /* LDLINUX_MAGIC */ 193 uint32_t instance; /* Per-version value */ 194 uint16_t data_sectors; 195 uint16_t adv_sectors; 196 uint32_t dwords; 197 uint32_t checksum; 198 uint16_t maxtransfer; 199 uint16_t epaoffset; /* Pointer to the extended patch area */ 200 }; 201 202 struct ext_patch_area { 203 uint16_t advptroffset; /* ADV pointers */ 204 uint16_t diroffset; /* Current directory field */ 205 uint16_t dirlen; /* Length of current directory field */ 206 uint16_t subvoloffset; /* Subvolume field */ 207 uint16_t subvollen; /* Length of subvolume field */ 208 uint16_t secptroffset; /* Sector extent pointers */ 209 uint16_t secptrcnt; /* Number of sector extent pointers */ 210 211 uint16_t sect1ptr0; /* Boot sector offset of sector 1 ptr LSW */ 212 uint16_t sect1ptr1; /* Boot sector offset of sector 1 ptr MSW */ 213 uint16_t raidpatch; /* Boot sector RAID mode patch pointer */ 214 }; 215 216 /* Sector extent */ 217 struct syslinux_extent { 218 uint64_t lba; 219 uint16_t len; 220 } PACKED; 221 222 /* FAT bootsector format, also used by other disk-based derivatives */ 223 struct fat_boot_sector { 224 uint8_t bsJump[3]; 225 char bsOemName[8]; 226 uint16_t bsBytesPerSec; 227 uint8_t bsSecPerClust; 228 uint16_t bsResSectors; 229 uint8_t bsFATs; 230 uint16_t bsRootDirEnts; 231 uint16_t bsSectors; 232 uint8_t bsMedia; 233 uint16_t bsFATsecs; 234 uint16_t bsSecPerTrack; 235 uint16_t bsHeads; 236 uint32_t bsHiddenSecs; 237 uint32_t bsHugeSectors; 238 239 union { 240 struct { 241 uint8_t DriveNumber; 242 uint8_t Reserved1; 243 uint8_t BootSignature; 244 uint32_t VolumeID; 245 char VolumeLabel[11]; 246 char FileSysType[8]; 247 uint8_t Code[442]; 248 } PACKED bs16; 249 struct { 250 uint32_t FATSz32; 251 uint16_t ExtFlags; 252 uint16_t FSVer; 253 uint32_t RootClus; 254 uint16_t FSInfo; 255 uint16_t BkBootSec; 256 uint8_t Reserved0[12]; 257 uint8_t DriveNumber; 258 uint8_t Reserved1; 259 uint8_t BootSignature; 260 uint32_t VolumeID; 261 char VolumeLabel[11]; 262 char FileSysType[8]; 263 uint8_t Code[414]; 264 } PACKED bs32; 265 } PACKED; 266 267 uint32_t bsMagic; 268 uint16_t bsForwardPtr; 269 uint16_t bsSignature; 270 } PACKED; 271 272 /* NTFS bootsector format */ 273 struct ntfs_boot_sector { 274 uint8_t bsJump[3]; 275 char bsOemName[8]; 276 uint16_t bsBytesPerSec; 277 uint8_t bsSecPerClust; 278 uint16_t bsResSectors; 279 uint8_t bsZeroed_0[3]; 280 uint16_t bsZeroed_1; 281 uint8_t bsMedia; 282 uint16_t bsZeroed_2; 283 uint16_t bsUnused_0; 284 uint16_t bsUnused_1; 285 uint32_t bsUnused_2; 286 uint32_t bsZeroed_3; 287 uint32_t bsUnused_3; 288 uint64_t bsTotalSectors; 289 uint64_t bsMFTLogicalClustNr; 290 uint64_t bsMFTMirrLogicalClustNr; 291 uint8_t bsClustPerMFTrecord; 292 uint8_t bsUnused_4[3]; 293 uint8_t bsClustPerIdxBuf; 294 uint8_t bsUnused_5[3]; 295 uint64_t bsVolSerialNr; 296 uint32_t bsUnused_6; 297 298 uint8_t Code[420]; 299 300 uint32_t bsMagic; 301 uint16_t bsForwardPtr; 302 uint16_t bsSignature; 303 } PACKED; 304 305 #define FAT_bsHead bsJump 306 #define FAT_bsHeadLen offsetof(struct fat_boot_sector, bsBytesPerSec) 307 #define FAT_bsCode bs32.Code /* The common safe choice */ 308 #define FAT_bsCodeLen (offsetof(struct fat_boot_sector, bsSignature) - \ 309 offsetof(struct fat_boot_sector, FAT_bsCode)) 310 311 #define NTFS_bsHead bsJump 312 #define NTFS_bsHeadLen offsetof(struct ntfs_boot_sector, bsOemName) 313 #define NTFS_bsCode Code 314 #define NTFS_bsCodeLen (offsetof(struct ntfs_boot_sector, bsSignature) - \ 315 offsetof(struct ntfs_boot_sector, NTFS_bsCode)) 316 317 /* Check if there are specific zero fields in an NTFS boot sector */ 318 static inline int ntfs_check_zero_fields(const struct ntfs_boot_sector *sb) 319 { 320 return !sb->bsResSectors && (!sb->bsZeroed_0[0] && !sb->bsZeroed_0[1] && 321 !sb->bsZeroed_0[2]) && !sb->bsZeroed_1 && !sb->bsZeroed_2 && 322 !sb->bsZeroed_3; 323 } 324 325 static inline int ntfs_check_sb_fields(const struct ntfs_boot_sector *sb) 326 { 327 return ntfs_check_zero_fields(sb) && 328 (!memcmp(sb->bsOemName, "NTFS ", 8) || 329 !memcmp(sb->bsOemName, "MSWIN4.0", 8) || 330 !memcmp(sb->bsOemName, "MSWIN4.1", 8)); 331 } 332 333 static inline int fat_check_sb_fields(const struct fat_boot_sector *sb) 334 { 335 return sb->bsResSectors && sb->bsFATs && 336 (!memcmp(sb->bs16.FileSysType, "FAT12 ", 8) || 337 !memcmp(sb->bs16.FileSysType, "FAT16 ", 8) || 338 !memcmp(sb->bs16.FileSysType, "FAT ", 8) || 339 !memcmp(sb->bs32.FileSysType, "FAT32 ", 8)); 340 } 341 342 #endif /* SYSLXINT_H */ 343