Changeset 265 for trunk/kernel/vfs/fatfs.c
- Timestamp:
- Jul 21, 2017, 7:36:08 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/vfs/fatfs.c
r246 r265 46 46 47 47 ////////////////////////////////////////////////////////////////////////////////////////// 48 // FATFS privateand static functions48 // FATFS specific and static functions 49 49 ////////////////////////////////////////////////////////////////////////////////////////// 50 50 … … 74 74 75 75 ////////////////////////////////////////////////////////////////////////////////////////// 76 // This function display the content of the FATFS context. 76 // This function return an integer record value (one, two, or four bytes) 77 // from a memory buffer, taking into account endianness. 78 ////////////////////////////////////////////////////////////////////////////////////////// 79 // @ offset : first byte of record in buffer. 80 // @ size : record length in bytes (1/2/4). 81 // @ buffer : pointer on buffer base. 82 // @ little endian : the most significant byte has the highest address when true. 83 // @ return the integer value in a 32 bits word. 84 ////////////////////////////////////////////////////////////////////////////////////////// 85 static uint32_t fatfs_get_record( uint32_t offset, 86 uint32_t size, 87 uint8_t * buffer, 88 uint32_t little_endian ) 89 { 90 uint32_t n; 91 uint32_t res = 0; 92 93 if ( little_endian) 94 { 95 for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1]; 96 } 97 else 98 { 99 for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n]; 100 } 101 return res; 102 103 } // end fatfs_get_record() 104 105 ////////////////////////////////////////////////////////////////////////////////////////// 106 // This static function retun in the <name> buffer a short name stored in 107 // a SFN FATFS directory entry. 108 /////////////////////////i//////////////////////////////////////////////////////////////// 109 // @ buffer : pointer on buffer containing the directory entry. 110 // @ name : [out] buffer allocated by the caller. 111 ////////////////////////////////////////////////////////////////////////////////////////// 112 static void fatfs_get_name_from_short( uint8_t * buffer, 113 char * name ) 114 { 115 uint32_t i; 116 uint32_t j = 0; 117 118 // get name 119 for ( i = 0; i < 8 && buffer[i] != ' '; i++ ) 120 { 121 name[j] = to_lower( buffer[i] ); 122 j++; 123 } 124 125 // get extension 126 for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ ) 127 { 128 // we entered the loop so there is an extension. add the dot 129 if ( i == 8 ) 130 { 131 name[j] = '.'; 132 j++; 133 } 134 135 name[j] = to_lower( buffer[i] ); 136 j++; 137 } 138 139 name[j] = '\0'; 140 } 141 142 ////////////////////////////////////////////////////////////////////////////////////////// 143 // This static function retun in the <name> buffer a partial name stored in 144 // a LFN FATFS directory entry. 145 /////////////////////////i//////////////////////////////////////////////////////////////// 146 // @ buffer : pointer on buffer containing the directory entry. 147 // @ name : [out] buffer allocated by the caller. 148 ////////////////////////////////////////////////////////////////////////////////////////// 149 static void fatfs_get_name_from_long( uint8_t * buffer, 150 char * name ) 151 { 152 uint32_t name_offset = 0; 153 uint32_t buffer_offset = get_length(LDIR_ORD); 154 uint32_t l_name_1 = get_length(LDIR_NAME_1); 155 uint32_t l_name_2 = get_length(LDIR_NAME_2); 156 uint32_t l_name_3 = get_length(LDIR_NAME_3); 157 uint32_t l_attr = get_length(LDIR_ATTR); 158 uint32_t l_type = get_length(LDIR_TYPE); 159 uint32_t l_chksum = get_length(LDIR_CHKSUM); 160 uint32_t l_rsvd = get_length(LDIR_RSVD); 161 162 uint32_t j = 0; 163 uint32_t eof = 0; 164 165 while ( (buffer_offset != DIR_ENTRY_SIZE) && (!eof) ) 166 { 167 while (j != l_name_1 && !eof ) 168 { 169 if ( (buffer[buffer_offset] == 0x00) || 170 (buffer[buffer_offset] == 0xFF) ) 171 { 172 eof = 1; 173 continue; 174 } 175 name[name_offset] = buffer[buffer_offset]; 176 buffer_offset += 2; 177 j += 2; 178 name_offset++; 179 } 180 181 buffer_offset += (l_attr + l_type + l_chksum); 182 j = 0; 183 184 while (j != l_name_2 && !eof ) 185 { 186 if ( (buffer[buffer_offset] == 0x00) || 187 (buffer[buffer_offset] == 0xFF) ) 188 { 189 eof = 1; 190 continue; 191 } 192 name[name_offset] = buffer[buffer_offset]; 193 buffer_offset += 2; 194 j += 2; 195 name_offset++; 196 } 197 198 buffer_offset += l_rsvd; 199 j = 0; 200 201 while (j != l_name_3 && !eof ) 202 { 203 if ( (buffer[buffer_offset] == 0x00) || 204 (buffer[buffer_offset] == 0xFF) ) 205 { 206 eof = 1; 207 continue; 208 } 209 name[name_offset] = buffer[buffer_offset]; 210 buffer_offset += 2; 211 j += 2; 212 name_offset++; 213 } 214 } 215 name[name_offset] = 0; 216 217 } // end get_name_from_long() 218 219 ////////////////////////////////////////////////////////////////////////////////////////// 220 // This function returns the FATFS cluster index of a page identified by its page 221 // index in the file, using the FAT mapper. It scans the FAT mapper, starting from the 222 // FATFS cluster index allocated to the first page of the file, until it reaches the 223 // searched page. The FAT mapper is automatically updated in case of miss. 224 // This function can be called by any thread running in any cluster, as it uses the 225 // RPC_FATFS_GET_CLUSTER to access the remote FAT mapper if required. 226 // We use a RPC to scan the FAT because the RPC_FIFO will avoid contention 227 // in the cluster containing the FAT mapper, and the RPC latency is not critical 228 // compared to the device access latency. 229 ////////////////////////////////////////////////////////////////////////////////////////// 230 // @ ctx : pointer on local FATFS context. 231 // @ first_cluster : first cluster allocated to a file in FATFS. 232 // @ page_index : index of searched page in file (one page occupies one cluster). 233 // @ cluster_index : [out] pointer on buffer for FATFS cluster index. 234 // @ return 0 if success / return EIO if a FAT cluster miss cannot be solved. 235 ////////////////////////////////////////////////////////////////////////////////////////// 236 static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx, 237 uint32_t first_cluster, 238 uint32_t page_index, 239 uint32_t * cluster_index ) 240 { 241 uint32_t searched_cluster; // searched FATFS cluster index 242 error_t error; 243 244 // get extended pointer on FAT mapper 245 xptr_t fat_mapper_xp = ctx->fat_mapper_xp; 246 247 // get cluster cxy and local pointer on FAT mapper 248 cxy_t fat_mapper_cxy = GET_CXY( fat_mapper_xp ); 249 mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp ); 250 251 if( fat_mapper_cxy == local_cxy ) // FAT mapper is local 252 { 253 error = fatfs_get_cluster( fat_mapper_ptr, 254 first_cluster, 255 page_index, 256 &searched_cluster ); 257 } 258 else // FAT mapper is remote 259 { 260 rpc_fatfs_get_cluster_client( fat_mapper_cxy, 261 fat_mapper_ptr, 262 first_cluster, 263 page_index, 264 &searched_cluster, 265 &error ); 266 } 267 268 if( error ) 269 { 270 printk("\n[ERROR] in %s : cannot access FAT\n", __FUNCTION__ ); 271 return error; 272 } 273 274 // return success 275 *cluster_index = searched_cluster; 276 return 0; 277 278 } // end fatfs_cluster_from_index() 279 280 ////////////////////////////////////////////////////////////////////////////////////////// 281 // FATFS specific but extern functions 282 ////////////////////////////////////////////////////////////////////////////////////////// 283 77 284 ////////////////////////////////////////////////////////////////////////////////////////// 78 285 void fatfs_ctx_display() 79 286 { 80 uint32_t type = FS_TYPE_FATFS;81 287 vfs_ctx_t * vfs_ctx = &fs_context[FS_TYPE_FATFS]; 82 288 fatfs_ctx_t * fatfs_ctx = (fatfs_ctx_t *)vfs_ctx->extend; … … 99 305 } 100 306 101 //////////////////////////////////////////////////////////////////////////////////////////102 // This function return an integer record value (one, two, or four bytes)103 // from a memory buffer, taking into account endianness.104 //////////////////////////////////////////////////////////////////////////////////////////105 // @ offset : first byte of record in buffer.106 // @ size : record length in bytes (1/2/4).107 // @ buffer : pointer on buffer base.108 // @ little endian : the most significant byte has the highest address when true.109 // @ return the integer value in a 32 bits word.110 //////////////////////////////////////////////////////////////////////////////////////////111 static uint32_t fatfs_get_record( uint32_t offset,112 uint32_t size,113 uint8_t * buffer,114 uint32_t little_endian )115 {116 uint32_t n;117 uint32_t res = 0;118 119 if ( little_endian)120 {121 for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1];122 }123 else124 {125 for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n];126 }127 return res;128 129 } // end fatfs_get_record()130 131 //////////////////////////////////////////////////////////////////////////////////////////132 // This static function retun in the <name> buffer a short name stored in133 // a SFN FATFS directory entry.134 /////////////////////////i////////////////////////////////////////////////////////////////135 // @ buffer : pointer on buffer containing the directory entry.136 // @ name : [out] buffer allocated by the caller.137 //////////////////////////////////////////////////////////////////////////////////////////138 static void fatfs_get_name_from_short( uint8_t * buffer,139 char * name )140 {141 uint32_t i;142 uint32_t j = 0;143 144 // get name145 for ( i = 0; i < 8 && buffer[i] != ' '; i++ )146 {147 name[j] = to_lower( buffer[i] );148 j++;149 }150 151 // get extension152 for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ )153 {154 // we entered the loop so there is an extension. add the dot155 if ( i == 8 )156 {157 name[j] = '.';158 j++;159 }160 161 name[j] = to_lower( buffer[i] );162 j++;163 }164 165 name[j] = '\0';166 }167 168 //////////////////////////////////////////////////////////////////////////////////////////169 // This static function retun in the <name> buffer a partial name stored in170 // a LFN FATFS directory entry.171 /////////////////////////i////////////////////////////////////////////////////////////////172 // @ buffer : pointer on buffer containing the directory entry.173 // @ name : [out] buffer allocated by the caller.174 //////////////////////////////////////////////////////////////////////////////////////////175 static void fatfs_get_name_from_long( uint8_t * buffer,176 char * name )177 {178 uint32_t name_offset = 0;179 uint32_t buffer_offset = get_length(LDIR_ORD);180 uint32_t l_name_1 = get_length(LDIR_NAME_1);181 uint32_t l_name_2 = get_length(LDIR_NAME_2);182 uint32_t l_name_3 = get_length(LDIR_NAME_3);183 uint32_t l_attr = get_length(LDIR_ATTR);184 uint32_t l_type = get_length(LDIR_TYPE);185 uint32_t l_chksum = get_length(LDIR_CHKSUM);186 uint32_t l_rsvd = get_length(LDIR_RSVD);187 188 uint32_t j = 0;189 uint32_t eof = 0;190 191 while ( (buffer_offset != DIR_ENTRY_SIZE) && (!eof) )192 {193 while (j != l_name_1 && !eof )194 {195 if ( (buffer[buffer_offset] == 0x00) ||196 (buffer[buffer_offset] == 0xFF) )197 {198 eof = 1;199 continue;200 }201 name[name_offset] = buffer[buffer_offset];202 buffer_offset += 2;203 j += 2;204 name_offset++;205 }206 207 buffer_offset += (l_attr + l_type + l_chksum);208 j = 0;209 210 while (j != l_name_2 && !eof )211 {212 if ( (buffer[buffer_offset] == 0x00) ||213 (buffer[buffer_offset] == 0xFF) )214 {215 eof = 1;216 continue;217 }218 name[name_offset] = buffer[buffer_offset];219 buffer_offset += 2;220 j += 2;221 name_offset++;222 }223 224 buffer_offset += l_rsvd;225 j = 0;226 227 while (j != l_name_3 && !eof )228 {229 if ( (buffer[buffer_offset] == 0x00) ||230 (buffer[buffer_offset] == 0xFF) )231 {232 eof = 1;233 continue;234 }235 name[name_offset] = buffer[buffer_offset];236 buffer_offset += 2;237 j += 2;238 name_offset++;239 }240 }241 name[name_offset] = 0;242 243 } // end get_name_from_long()244 245 //////////////////////////////////////////////////////////////////////////////////////////246 // This function returns the FATFS cluster index of a page identified by its page247 // index in the file, using the FAT mapper. It scans the FAT mapper, starting from the248 // FATFS cluster index allocated to the first page of the file, until it reaches the249 // searched page. The FAT mapper is automatically updated in case of miss.250 // This function can be called by any thread running in any cluster, as it uses the251 // RPC_FATFS_GET_CLUSTER to access the remote FAT mapper if required.252 // We use a RPC to scan the FAT because the RPC_FIFO will avoid contention253 // in the cluster containing the FAT mapper, and the RPC latency is not critical254 // compared to the device access latency.255 //////////////////////////////////////////////////////////////////////////////////////////256 // @ ctx : pointer on local FATFS context.257 // @ first_cluster : first cluster allocated to a file in FATFS.258 // @ page_index : index of searched page in file (one page occupies one cluster).259 // @ cluster_index : [out] pointer on buffer for FATFS cluster index.260 // @ return 0 if success / return EIO if a FAT cluster miss cannot be solved.261 //////////////////////////////////////////////////////////////////////////////////////////262 static error_t fatfs_cluster_from_index( fatfs_ctx_t * ctx,263 uint32_t first_cluster,264 uint32_t page_index,265 uint32_t * cluster_index )266 {267 uint32_t searched_cluster; // searched FATFS cluster index268 error_t error;269 270 // get extended pointer on FAT mapper271 xptr_t fat_mapper_xp = ctx->fat_mapper_xp;272 273 // get cluster cxy and local pointer on FAT mapper274 cxy_t fat_mapper_cxy = GET_CXY( fat_mapper_xp );275 mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp );276 277 if( fat_mapper_cxy == local_cxy ) // FAT mapper is local278 {279 error = fatfs_get_cluster( fat_mapper_ptr,280 first_cluster,281 page_index,282 &searched_cluster );283 }284 else // FAT mapper is remote285 {286 rpc_fatfs_get_cluster_client( fat_mapper_cxy,287 fat_mapper_ptr,288 first_cluster,289 page_index,290 &searched_cluster,291 &error );292 }293 294 if( error )295 {296 printk("\n[ERROR] in %s : cannot access FAT\n", __FUNCTION__ );297 return error;298 }299 300 // return success301 *cluster_index = searched_cluster;302 return 0;303 304 } // end fatfs_cluster_from_index()305 306 //////////////////////////////////////////////////////////////////////////////////////////307 // FATFS specific but extern function (used by RPC_FATFS_GET_CLUSTER)308 //////////////////////////////////////////////////////////////////////////////////////////309 310 307 ///////////////////////////////////////////// 311 308 error_t fatfs_get_cluster( mapper_t * mapper, 312 uint32_t first_cluster ,313 uint32_t searched_page,314 uint32_t * cluster)309 uint32_t first_cluster_id, 310 uint32_t page_index, 311 uint32_t * searched_cluster_id ) 315 312 { 316 313 page_t * current_page_desc; // pointer on current page descriptor … … 319 316 uint32_t current_page_offset; // offset of slot in current page 320 317 uint32_t page_count_in_file; // index of page in file (index in linked list) 321 uint32_t current_cluster; // content of current FAT slot 322 323 fatfs_dmsg("\n[INFO] %s : enters / first_cluster_id = %d / searched_page = %d\n", 324 __FUNCTION__ , first_cluster , searched_page ); 325 326 #if CONFIG_FATFS_DEBUG 318 uint32_t current_cluster_id; // content of current FAT slot 319 320 assert( (page_index > 0) , __FUNCTION__ , "no FAT access required for first page\n"); 321 322 fatfs_dmsg("\n[INFO] %s : enters / mapper = %x / first_cluster_id = %d / page_index = %d\n", 323 __FUNCTION__ , first_cluster_id , page_index ); 324 325 #if (CONFIG_FATFS_DEBUG > 1) 327 326 uint32_t * buf = (uint32_t *)ppm_page2vaddr( mapper_get_page ( mapper , 0 ) ); 328 327 uint32_t line , word; 329 printk("\n*** FAT content for first 128entries ***\n");330 for( line = 0 ; line < 8; line++ )331 { 332 printk("% d : ");328 printk("\n*** FAT mapper content for first 256 entries ***\n"); 329 for( line = 0 ; line < 16 ; line++ ) 330 { 331 printk("%X : ", line ); 333 332 for( word = 0 ; word < 16 ; word++ ) printk("%X ", buf[(line<<4) + word] ); 334 333 printk("\n"); … … 340 339 341 340 // initialize loop variable 342 current_page_index = first_cluster / slots_per_page;343 current_page_offset = first_cluster % slots_per_page;341 current_page_index = first_cluster_id / slots_per_page; 342 current_page_offset = first_cluster_id % slots_per_page; 344 343 page_count_in_file = 0; 345 344 346 345 // scan FAT (i.e. traverse FAT linked list) 347 while( page_count_in_file <= searched_page)346 while( page_count_in_file <= page_index ) 348 347 { 349 348 … … 360 359 361 360 // get FAT slot content 362 current_cluster = current_page_buffer[current_page_offset];361 current_cluster_id = current_page_buffer[current_page_offset]; 363 362 364 363 // update loop variables 365 current_page_index = current_cluster / slots_per_page;366 current_page_offset = current_cluster % slots_per_page;364 current_page_index = current_cluster_id / slots_per_page; 365 current_page_offset = current_cluster_id % slots_per_page; 367 366 page_count_in_file++; 368 367 } 369 368 370 369 fatfs_dmsg("\n[INFO] %s : exit / cluster_id = %d\n", 371 __FUNCTION__ , current_cluster );372 373 * cluster = current_cluster;370 __FUNCTION__ , current_cluster_id ); 371 372 *searched_cluster_id = current_cluster_id; 374 373 return 0; 375 374 … … 550 549 else // it is a normal inode mapper 551 550 { 552 // get first cluster index from inode extension 553 uint32_t first_cluster = (uint32_t)(intptr_t)inode->extend; 554 555 fatfs_dmsg("\n[INFO] %s : for inode %x / first cluster_id = %d\n", 556 __FUNCTION__ , inode , first_cluster ); 557 558 // compute FATFS_cluster index for the accessed page 559 uint32_t cluster = 0; 560 error_t error = fatfs_cluster_from_index( fatfs_ctx, 561 first_cluster, 562 index, 563 &cluster ); 564 if( error ) return EIO; 565 566 // get lba from cluster 567 uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , cluster ); 551 uint32_t searched_cluster_id; 552 553 // get first_cluster_id from inode extension 554 uint32_t first_cluster_id = (uint32_t)(intptr_t)inode->extend; 555 556 fatfs_dmsg("\n[INFO] %s : for inode %x / first_cluster_id = %d\n", 557 __FUNCTION__ , inode , first_cluster_id ); 558 559 // compute cluster_id 560 if( index == 0 ) // no need to access FAT mapper 561 { 562 searched_cluster_id = first_cluster_id; 563 } 564 else // FAT mapper access required 565 { 566 // get cluster and local pointer on FAT mapper 567 xptr_t fat_mapper_xp = fatfs_ctx->fat_mapper_xp; 568 cxy_t fat_mapper_cxy = GET_CXY( fat_mapper_xp ); 569 mapper_t * fat_mapper_ptr = (mapper_t *)GET_PTR( fat_mapper_xp ); 570 571 // access FAT mapper 572 if( fat_mapper_cxy == local_cxy ) // FAT mapper is local 573 { 574 error = fatfs_get_cluster( fat_mapper_ptr, 575 first_cluster_id, 576 index, 577 &searched_cluster_id ); 578 } 579 else // FAT mapper is remote 580 { 581 rpc_fatfs_get_cluster_client( fat_mapper_cxy, 582 fat_mapper_ptr, 583 first_cluster_id, 584 index, 585 &searched_cluster_id, 586 &error ); 587 } 588 589 if( error ) return EIO; 590 } 591 592 // get lba from cluster_id 593 uint32_t lba = fatfs_lba_from_cluster( fatfs_ctx , searched_cluster_id ); 568 594 569 595 fatfs_dmsg("\n[INFO] %s : for inode %x / page = %d / cluster_id = %d / lba = %x\n", 570 __FUNCTION__ , inode , index , cluster, lba );596 __FUNCTION__ , inode , index , searched_cluster_id , lba ); 571 597 572 598 // access device … … 584 610 } // end fatfs_mapper_move_page() 585 611 586 ///////////////////////////////////////////////////// ////////////612 ///////////////////////////////////////////////////// 587 613 error_t fatfs_inode_load( vfs_inode_t * parent_inode, 588 614 char * name, … … 629 655 // get page base 630 656 base = ppm_page2vaddr( page ); 657 658 #if (CONFIG_FATFS_DEBUG > 1) 659 uint32_t * buf = (uint32_t *)base; 660 uint32_t line , word; 661 printk("\n*** DIRECTORY content for first 16 entries ***\n"); 662 for( line = 0 ; line < 16 ; line++ ) 663 { 664 printk("%X : ", line ); 665 for( word = 0 ; word < 8 ; word++ ) printk("%X ", buf[(line<<4) + word] ); 666 printk("\n"); 667 } 668 #endif 669 631 670 632 671 // scan this page until end of directory, end of page, or name found
Note: See TracChangeset
for help on using the changeset viewer.