Changes in tools/mkfat.py [a9a6d8d:87608a5] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tools/mkfat.py
ra9a6d8d r87608a5 168 168 """ 169 169 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 : 170 LFN_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 181 lchars = 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 188 def 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 203 def 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: 196 213 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: 201 218 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: 206 223 lfn = True 207 208 if len( parts) > 2:224 225 if len(ascii_parts) > 2: 209 226 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 214 232 # For filenames with multiple extensions, we treat the last one 215 233 # as the actual extension. The rest of the filename is stripped 216 234 # 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: 230 247 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 entry = xstruct.create(LFN_ENTRY) 251 252 entry.name1 = get_utf16(name[0:5], 5) 253 entry.name2 = get_utf16(name[5:11], 6) 254 entry.name3 = get_utf16(name[11:13], 2) 255 entry.pos = index 256 257 entry.attr = 0xF 258 entry.fc = 0 259 entry.type = 0 260 261 return entry 262 263 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 252 def 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 274 def 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 283 def create_dirent(name, name83_list, directory, cluster, size): 284 short_name, short_ext, lfn = fat_name83(name, name83_list) 264 285 265 286 dir_entry = xstruct.create(DIR_ENTRY) 266 287 267 dir_entry.name, dir_entry.ext, lfn = name83(name) 268 269 dir_entry.name = dir_entry.name.upper().encode('ascii') 270 dir_entry.ext = dir_entry.ext.upper().encode('ascii') 271 288 dir_entry.name = short_name 289 dir_entry.ext = short_ext 290 272 291 if (directory): 273 292 dir_entry.attr = 0x30 … … 289 308 dir_entry.size = size 290 309 291 292 310 if not lfn: 293 311 return [dir_entry] 294 295 n = len(name) / 13 + 1 296 names = [(name[i * 13: (i + 1) * 13 + 1], i + 1) for i in range(n)] 297 298 entries = sorted(map (create_lfn_entry, names), reverse = True, key = lambda e : e.pos) 299 entries[0].pos |= 0x40 300 301 fname11 = dir_entry.name + dir_entry.ext 302 303 csum = 0 304 for i in range(0, 11) : 305 csum = ((csum & 1) << 7) + (csum >> 1) + ord(fname11[i]) 306 csum = csum & 0xFF 307 308 for e in entries : 309 e.csum = csum; 310 311 entries.append(dir_entry) 312 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() 313 325 return entries 314 326 … … 355 367 356 368 directory = [] 357 358 if (not head): 369 name83_list = [] 370 371 if not head: 359 372 # Directory cluster preallocation 360 373 empty_cluster = fat.index(0) 361 fat[empty_cluster] = 0x ffff374 fat[empty_cluster] = 0xFFFF 362 375 363 376 directory.append(create_dot_dirent(empty_cluster)) … … 366 379 empty_cluster = 0 367 380 368 for item in listdir_items(root): 381 for item in listdir_items(root): 369 382 if item.is_file: 370 383 rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters) 371 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])) 372 385 elif item.is_dir: 373 386 rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster) 374 directory.extend(create_dirent(item.name, True, rv[0], rv[1]))375 376 if (head):387 directory.extend(create_dirent(item.name, name83_list, True, rv[0], rv[1])) 388 389 if head: 377 390 outf.seek(root_start) 378 391 for dir_entry in directory: … … 431 444 extra_bytes = int(sys.argv[1]) 432 445 433 path = os.path.abspath(sys.argv[2] )446 path = os.path.abspath(sys.argv[2].decode()) 434 447 if (not os.path.isdir(path)): 435 448 print("<PATH> must be a directory") … … 529 542 530 543 outf.close() 531 544 532 545 if __name__ == '__main__': 533 546 main()
Note:
See TracChangeset
for help on using the changeset viewer.