Changeset 97c7682 in mainline for tools/mkfat.py
- Timestamp:
- 2012-07-14T11:18:40Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 804d9b6
- Parents:
- 0747468 (diff), f0348c8 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tools/mkfat.py
r0747468 r97c7682 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 = b'' 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 # Splitting works only on strings, not on bytes 208 ascii_parts = ascii_name.decode('utf8').split('.') 209 210 short_name = '' 211 short_ext = '' 212 213 if len(ascii_name) > 11: 196 214 lfn = True 197 198 if len( parts) > 0:199 name =parts[0]200 if len( name) > 8:215 216 if len(ascii_parts) > 0: 217 short_name = ascii_parts[0] 218 if len(short_name) > 8: 201 219 lfn = True 202 203 if len( parts) > 1:204 ext =parts[-1]205 if len( ext) > 3:220 221 if len(ascii_parts) > 1: 222 short_ext = ascii_parts[-1] 223 if len(short_ext) > 3: 206 224 lfn = True 207 208 if len( parts) > 2:225 226 if len(ascii_parts) > 2: 209 227 lfn = True 210 211 if (lfn == False) : 212 return (name.ljust(8)[0:8], ext.ljust(3)[0:3], False) 213 228 229 if lfn == False: 230 name83_list.append(short_name + '.' + short_ext) 231 return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], False) 232 214 233 # For filenames with multiple extensions, we treat the last one 215 234 # as the actual extension. The rest of the filename is stripped 216 235 # 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 : 236 for part in ascii_parts[1:-1]: 237 short_name += part 238 239 for number in range(1, 999999): 240 number_str = ('~' + str(number)).upper() 241 242 if len(short_name) + len(number_str) > 8: 243 short_name = short_name[0:8 - len(number_str)] 244 245 short_name += number_str; 246 247 if not (short_name + '.' + short_ext) in name83_list: 230 248 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): 249 250 name83_list.append(short_name + '.' + short_ext) 251 return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], True) 252 253 def create_lfn_dirent(name, seq, checksum): 254 "Create LFN directory entry" 255 256 entry = xstruct.create(LFN_DIR_ENTRY) 257 name_rest = name[26:] 258 259 if len(name_rest) > 0: 260 entry.seq = seq 261 else: 262 entry.seq = seq | 0x40 263 264 entry.name1 = name[0:10] 265 entry.name2 = name[10:22] 266 entry.name3 = name[22:26] 267 268 entry.attr = 0x0F 269 entry.rec_type = 0 270 entry.checksum = checksum 271 entry.cluster = 0 272 273 return (entry, name_rest) 274 275 def lfn_checksum(name): 276 "Calculate LFN checksum" 277 278 checksum = 0 279 for i in range(0, 11): 280 checksum = (((checksum & 1) << 7) + (checksum >> 1) + ord(name[i])) & 0xFF 281 282 return checksum 283 284 def create_dirent(name, name83_list, directory, cluster, size): 285 short_name, short_ext, lfn = fat_name83(name, name83_list) 264 286 265 287 dir_entry = xstruct.create(DIR_ENTRY) 266 288 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 289 dir_entry.name = short_name 290 dir_entry.ext = short_ext 291 272 292 if (directory): 273 293 dir_entry.attr = 0x30 … … 289 309 dir_entry.size = size 290 310 291 292 311 if not lfn: 293 312 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 313 314 long_name = name.encode('utf_16_le') 315 entries = [dir_entry] 316 317 seq = 1 318 checksum = lfn_checksum(dir_entry.name + dir_entry.ext) 319 320 while len(long_name) > 0: 321 long_entry, long_name = create_lfn_dirent(long_name, seq, checksum) 322 entries.append(long_entry) 323 seq += 1 324 325 entries.reverse() 313 326 return entries 314 327 … … 355 368 356 369 directory = [] 357 358 if (not head): 370 name83_list = [] 371 372 if not head: 359 373 # Directory cluster preallocation 360 374 empty_cluster = fat.index(0) 361 fat[empty_cluster] = 0x ffff375 fat[empty_cluster] = 0xFFFF 362 376 363 377 directory.append(create_dot_dirent(empty_cluster)) … … 366 380 empty_cluster = 0 367 381 368 for item in listdir_items(root): 382 for item in listdir_items(root): 369 383 if item.is_file: 370 384 rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters) 371 directory.extend(create_dirent(item.name, False, rv[0], rv[1]))385 directory.extend(create_dirent(item.name, name83_list, False, rv[0], rv[1])) 372 386 elif item.is_dir: 373 387 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):388 directory.extend(create_dirent(item.name, name83_list, True, rv[0], rv[1])) 389 390 if head: 377 391 outf.seek(root_start) 378 392 for dir_entry in directory: … … 529 543 530 544 outf.close() 531 545 532 546 if __name__ == '__main__': 533 547 main()
Note:
See TracChangeset
for help on using the changeset viewer.