Home | History | Annotate | Download | only in libinstaller
      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