Changeset f2b3d3e in mainline for tools/mkfat.py


Ignore:
Timestamp:
2012-05-04T10:57:48Z (12 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
35a35651
Parents:
90924df (diff), d21e935c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tools/mkfat.py

    r90924df rf2b3d3e  
    168168"""
    169169
    170 LFN_ENTRY = """little:
    171         uint8_t pos
    172         uint16_t name1[5]
    173         uint8_t attr
    174         uint8_t type
    175         uint8_t csum
    176         uint16_t name2[6]
    177         uint16_t fc
    178         uint16_t name3[2]
    179 """
    180 
    181 # Global variable to hold the file names in 8.3 format. Needed to
    182 # keep track of "number" when creating a short fname from a LFN.
    183 name83_list = []
    184 
    185 def name83(fname):
    186         "Create a 8.3 name for the given fname"
    187 
    188         # FIXME: filter illegal characters
    189         parts = fname.split('.')
    190        
    191         name = ''
    192         ext = ''
    193         lfn = False
    194 
    195         if len(fname) > 11 :
     170LFN_DIR_ENTRY = """little:
     171        uint8_t seq                /* sequence number */
     172        char name1[10]             /* first part of the name */
     173        uint8_t attr               /* attributes */
     174        uint8_t rec_type           /* LFN record type */
     175        uint8_t checksum           /* LFN checksum */
     176        char name2[12]             /* second part of the name */
     177        uint16_t cluster           /* cluster */
     178        char name3[4]              /* third part of the name */
     179"""
     180
     181lchars = set(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
     182              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
     183              'U', 'V', 'W', 'X', 'Y', 'Z',
     184              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     185              '!', '#', '$', '%', '&', '\'', '(', ')', '-', '@',
     186              '^', '_', '`', '{', '}', '~', '.'])
     187
     188def fat_lchars(name):
     189        "Filter FAT legal characters"
     190       
     191        filtered_name = ''
     192        filtered = False
     193       
     194        for char in name.encode('ascii', 'replace').upper():
     195                if char in lchars:
     196                        filtered_name += char
     197                else:
     198                        filtered_name += b'_'
     199                        filtered = True
     200       
     201        return (filtered_name, filtered)
     202
     203def fat_name83(name, name83_list):
     204        "Create a 8.3 name for the given name"
     205       
     206        ascii_name, lfn = fat_lchars(name)
     207        ascii_parts = ascii_name.split('.')
     208       
     209        short_name = ''
     210        short_ext = ''
     211       
     212        if len(ascii_name) > 11:
    196213                lfn = True
    197 
    198         if len(parts) > 0:
    199                 name = parts[0]
    200                 if len(name) > 8 :
     214       
     215        if len(ascii_parts) > 0:
     216                short_name = ascii_parts[0]
     217                if len(short_name) > 8:
    201218                        lfn = True
    202 
    203         if len(parts) > 1 :
    204                 ext = parts[-1]
    205                 if len(ext) > 3 :
     219       
     220        if len(ascii_parts) > 1:
     221                short_ext = ascii_parts[-1]
     222                if len(short_ext) > 3:
    206223                        lfn = True
    207 
    208         if len(parts) > 2 :
     224       
     225        if len(ascii_parts) > 2:
    209226                lfn = True
    210 
    211         if (lfn == False) :
    212                 return (name.ljust(8)[0:8], ext.ljust(3)[0:3], False)
    213 
     227       
     228        if lfn == False:
     229                name83_list.append(short_name + '.' + short_ext)
     230                return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], False)
     231       
    214232        # For filenames with multiple extensions, we treat the last one
    215233        # as the actual extension. The rest of the filename is stripped
    216234        # of dots and concatenated to form the short name
    217         for _name in parts[1:-1]:
    218                 name = name + _name             
    219 
    220         global name83_list
    221         for number in range(1, 10000) :
    222                 number_str = '~' + str(number)
    223 
    224                 if len(name) + len(number_str) > 8 :
    225                         name = name[0:8 - len(number_str)]
    226 
    227                 name = name + number_str;
    228 
    229                 if (name + ext) not in name83_list :
     235        for part in ascii_parts[1:-1]:
     236                short_name += part
     237       
     238        for number in range(1, 999999):
     239                number_str = ('~' + str(number)).upper()
     240               
     241                if len(short_name) + len(number_str) > 8:
     242                        short_name = short_name[0:8 - len(number_str)]
     243               
     244                short_name += number_str;
     245               
     246                if not (short_name + '.' + short_ext) in name83_list:
    230247                        break
    231                        
    232         name83_list.append(name + ext) 
    233 
    234         return (name.ljust(8)[0:8], ext.ljust(3)[0:3], True)
    235 
    236 def get_utf16(name, l) :
    237         "Create a int array out of a string which we can store in uint16_t arrays"
    238 
    239         bs = [0xFFFF for i in range(l)]
    240 
    241         for i in range(len(name)) :
    242                 bs[i] = ord(name[i])
    243        
    244         if (len(name) < l) :
    245                 bs[len(name)] = 0;
    246        
    247         return bs
    248 
    249 def create_lfn_entry(name_index) :
    250         (name, index) = name_index
    251         entry = xstruct.create(LFN_ENTRY)
    252 
    253         entry.name1 = get_utf16(name[0:5], 5)
    254         entry.name2 = get_utf16(name[5:11], 6)
    255         entry.name3 = get_utf16(name[11:13], 2)
    256         entry.pos = index
    257 
    258         entry.attr = 0xF
    259         entry.fc = 0
    260         entry.type = 0
    261 
    262         return entry
    263 
    264 def create_dirent(name, directory, cluster, size):
     248       
     249        name83_list.append(short_name + '.' + short_ext)
     250        return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], True)
     251
     252def create_lfn_dirent(name, seq, checksum):
     253        "Create LFN directory entry"
     254       
     255        entry = xstruct.create(LFN_DIR_ENTRY)
     256        name_rest = name[26:]
     257       
     258        if len(name_rest) > 0:
     259                entry.seq = seq
     260        else:
     261                entry.seq = seq | 0x40
     262       
     263        entry.name1 = name[0:10]
     264        entry.name2 = name[10:22]
     265        entry.name3 = name[22:26]
     266       
     267        entry.attr = 0x0F
     268        entry.rec_type = 0
     269        entry.checksum = checksum
     270        entry.cluster = 0
     271       
     272        return (entry, name_rest)
     273
     274def lfn_checksum(name):
     275        "Calculate LFN checksum"
     276       
     277        checksum = 0
     278        for i in range(0, 11):
     279                checksum = (((checksum & 1) << 7) + (checksum >> 1) + ord(name[i])) & 0xFF
     280       
     281        return checksum
     282
     283def create_dirent(name, name83_list, directory, cluster, size):
     284        short_name, short_ext, lfn = fat_name83(name, name83_list)
    265285       
    266286        dir_entry = xstruct.create(DIR_ENTRY)
    267287       
    268         dir_entry.name, dir_entry.ext, lfn = name83(name)
    269 
    270         dir_entry.name = dir_entry.name.upper().encode('ascii')
    271         dir_entry.ext = dir_entry.ext.upper().encode('ascii')
    272 
     288        dir_entry.name = short_name
     289        dir_entry.ext = short_ext
     290       
    273291        if (directory):
    274292                dir_entry.attr = 0x30
     
    290308                dir_entry.size = size
    291309       
    292 
    293310        if not lfn:
    294311                return [dir_entry]
    295 
    296         n = (int) (len(name) / 13 + 1)
    297         names = [(name[i * 13: (i + 1) * 13 + 1], i + 1) for i in range(n)]
    298 
    299         entries = sorted(map (create_lfn_entry, names), reverse = True, key = lambda e : e.pos)
    300         entries[0].pos |= 0x40
    301 
    302         fname11 = str(dir_entry.name + dir_entry.ext)
    303 
    304         csum = 0
    305         for i in range(0, 11) :
    306                 csum = ((csum & 1) << 7) + (csum  >> 1) + ord(fname11[i])
    307                 csum = csum & 0xFF
    308        
    309         for e in entries :
    310                 e.csum = csum;
    311        
    312         entries.append(dir_entry)
    313 
     312       
     313        long_name = name.encode('utf_16_le')
     314        entries = [dir_entry]
     315       
     316        seq = 1
     317        checksum = lfn_checksum(dir_entry.name + dir_entry.ext)
     318       
     319        while len(long_name) > 0:
     320                long_entry, long_name = create_lfn_dirent(long_name, seq, checksum)
     321                entries.append(long_entry)
     322                seq += 1
     323       
     324        entries.reverse()
    314325        return entries
    315326
     
    356367       
    357368        directory = []
    358        
    359         if (not head):
     369        name83_list = []
     370       
     371        if not head:
    360372                # Directory cluster preallocation
    361373                empty_cluster = fat.index(0)
    362                 fat[empty_cluster] = 0xffff
     374                fat[empty_cluster] = 0xFFFF
    363375               
    364376                directory.append(create_dot_dirent(empty_cluster))
     
    367379                empty_cluster = 0
    368380       
    369         for item in listdir_items(root):               
     381        for item in listdir_items(root):
    370382                if item.is_file:
    371383                        rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
    372                         directory.extend(create_dirent(item.name, False, rv[0], rv[1]))
     384                        directory.extend(create_dirent(item.name, name83_list, False, rv[0], rv[1]))
    373385                elif item.is_dir:
    374386                        rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
    375                         directory.extend(create_dirent(item.name, True, rv[0], rv[1]))
    376        
    377         if (head):
     387                        directory.extend(create_dirent(item.name, name83_list, True, rv[0], rv[1]))
     388       
     389        if head:
    378390                outf.seek(root_start)
    379391                for dir_entry in directory:
     
    432444        extra_bytes = int(sys.argv[1])
    433445       
    434         path = os.path.abspath(sys.argv[2])
     446        path = os.path.abspath(sys.argv[2].decode())
    435447        if (not os.path.isdir(path)):
    436448                print("<PATH> must be a directory")
     
    530542       
    531543        outf.close()
    532        
     544
    533545if __name__ == '__main__':
    534546        main()
Note: See TracChangeset for help on using the changeset viewer.