mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Added conversion to/from little-endian on disk
Required to support big-endian processors, with the most notable being the PowerPC architecture. On little-endian architectures, these conversions can be optimized out and have no code impact. Initial patch provided by gmouchard
This commit is contained in:
		
							
								
								
									
										76
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -323,6 +323,48 @@ static void lfs_alloc_ack(lfs_t *lfs) { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /// Endian swapping functions /// | ||||||
|  | static void lfs_dir_fromle32(struct lfs_disk_dir *d) { | ||||||
|  |     d->rev     = lfs_fromle32(d->rev); | ||||||
|  |     d->size    = lfs_fromle32(d->size); | ||||||
|  |     d->tail[0] = lfs_fromle32(d->tail[0]); | ||||||
|  |     d->tail[1] = lfs_fromle32(d->tail[1]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lfs_dir_tole32(struct lfs_disk_dir *d) { | ||||||
|  |     d->rev     = lfs_tole32(d->rev); | ||||||
|  |     d->size    = lfs_tole32(d->size); | ||||||
|  |     d->tail[0] = lfs_tole32(d->tail[0]); | ||||||
|  |     d->tail[1] = lfs_tole32(d->tail[1]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lfs_entry_fromle32(struct lfs_disk_entry *d) { | ||||||
|  |     d->u.dir[0] = lfs_fromle32(d->u.dir[0]); | ||||||
|  |     d->u.dir[1] = lfs_fromle32(d->u.dir[1]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lfs_entry_tole32(struct lfs_disk_entry *d) { | ||||||
|  |     d->u.dir[0] = lfs_tole32(d->u.dir[0]); | ||||||
|  |     d->u.dir[1] = lfs_tole32(d->u.dir[1]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lfs_superblock_fromle32(struct lfs_disk_superblock *d) { | ||||||
|  |     d->root[0]     = lfs_fromle32(d->root[0]); | ||||||
|  |     d->root[1]     = lfs_fromle32(d->root[1]); | ||||||
|  |     d->block_size  = lfs_fromle32(d->block_size); | ||||||
|  |     d->block_count = lfs_fromle32(d->block_count); | ||||||
|  |     d->version     = lfs_fromle32(d->version); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void lfs_superblock_tole32(struct lfs_disk_superblock *d) { | ||||||
|  |     d->root[0]     = lfs_tole32(d->root[0]); | ||||||
|  |     d->root[1]     = lfs_tole32(d->root[1]); | ||||||
|  |     d->block_size  = lfs_tole32(d->block_size); | ||||||
|  |     d->block_count = lfs_tole32(d->block_count); | ||||||
|  |     d->version     = lfs_tole32(d->version); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Metadata pair and directory operations /// | /// Metadata pair and directory operations /// | ||||||
| static inline void lfs_pairswap(lfs_block_t pair[2]) { | static inline void lfs_pairswap(lfs_block_t pair[2]) { | ||||||
|     lfs_block_t t = pair[0]; |     lfs_block_t t = pair[0]; | ||||||
| @@ -364,6 +406,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) { | |||||||
|     // rather than clobbering one of the blocks we just pretend |     // rather than clobbering one of the blocks we just pretend | ||||||
|     // the revision may be valid |     // the revision may be valid | ||||||
|     int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->d.rev, 4); |     int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->d.rev, 4); | ||||||
|  |     dir->d.rev = lfs_fromle32(dir->d.rev); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -389,6 +432,7 @@ static int lfs_dir_fetch(lfs_t *lfs, | |||||||
|     for (int i = 0; i < 2; i++) { |     for (int i = 0; i < 2; i++) { | ||||||
|         struct lfs_disk_dir test; |         struct lfs_disk_dir test; | ||||||
|         int err = lfs_bd_read(lfs, tpair[i], 0, &test, sizeof(test)); |         int err = lfs_bd_read(lfs, tpair[i], 0, &test, sizeof(test)); | ||||||
|  |         lfs_dir_fromle32(&test); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -403,7 +447,9 @@ static int lfs_dir_fetch(lfs_t *lfs, | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         uint32_t crc = 0xffffffff; |         uint32_t crc = 0xffffffff; | ||||||
|  |         lfs_dir_tole32(&test); | ||||||
|         lfs_crc(&crc, &test, sizeof(test)); |         lfs_crc(&crc, &test, sizeof(test)); | ||||||
|  |         lfs_dir_fromle32(&test); | ||||||
|         err = lfs_bd_crc(lfs, tpair[i], sizeof(test), |         err = lfs_bd_crc(lfs, tpair[i], sizeof(test), | ||||||
|                 (0x7fffffff & test.size) - sizeof(test), &crc); |                 (0x7fffffff & test.size) - sizeof(test), &crc); | ||||||
|         if (err) { |         if (err) { | ||||||
| @@ -463,8 +509,10 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             uint32_t crc = 0xffffffff; |             uint32_t crc = 0xffffffff; | ||||||
|  |             lfs_dir_tole32(&dir->d); | ||||||
|             lfs_crc(&crc, &dir->d, sizeof(dir->d)); |             lfs_crc(&crc, &dir->d, sizeof(dir->d)); | ||||||
|             err = lfs_bd_prog(lfs, dir->pair[0], 0, &dir->d, sizeof(dir->d)); |             err = lfs_bd_prog(lfs, dir->pair[0], 0, &dir->d, sizeof(dir->d)); | ||||||
|  |             lfs_dir_fromle32(&dir->d); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 if (err == LFS_ERR_CORRUPT) { |                 if (err == LFS_ERR_CORRUPT) { | ||||||
|                     goto relocate; |                     goto relocate; | ||||||
| @@ -511,7 +559,9 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             crc = lfs_tole32(crc); | ||||||
|             err = lfs_bd_prog(lfs, dir->pair[0], newoff, &crc, 4); |             err = lfs_bd_prog(lfs, dir->pair[0], newoff, &crc, 4); | ||||||
|  |             crc = lfs_fromle32(crc); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 if (err == LFS_ERR_CORRUPT) { |                 if (err == LFS_ERR_CORRUPT) { | ||||||
|                     goto relocate; |                     goto relocate; | ||||||
| @@ -584,11 +634,14 @@ relocate: | |||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         const lfs_entry_t *entry, const void *data) { |         lfs_entry_t *entry, const void *data) { | ||||||
|     return lfs_dir_commit(lfs, dir, (struct lfs_region[]){ |     lfs_entry_tole32(&entry->d); | ||||||
|  |     int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||||
|             {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, |             {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, | ||||||
|             {entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen} |             {entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen} | ||||||
|         }, data ? 2 : 1); |         }, data ? 2 : 1); | ||||||
|  |     lfs_entry_fromle32(&entry->d); | ||||||
|  |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | ||||||
| @@ -597,10 +650,14 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     while (true) { |     while (true) { | ||||||
|         if (dir->d.size + lfs_entry_size(entry) <= lfs->cfg->block_size) { |         if (dir->d.size + lfs_entry_size(entry) <= lfs->cfg->block_size) { | ||||||
|             entry->off = dir->d.size - 4; |             entry->off = dir->d.size - 4; | ||||||
|             return lfs_dir_commit(lfs, dir, (struct lfs_region[]){ |  | ||||||
|  |             lfs_entry_tole32(&entry->d); | ||||||
|  |             int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||||
|                     {entry->off, 0, &entry->d, sizeof(entry->d)}, |                     {entry->off, 0, &entry->d, sizeof(entry->d)}, | ||||||
|                     {entry->off, 0, data, entry->d.nlen} |                     {entry->off, 0, data, entry->d.nlen} | ||||||
|                 }, 2); |                 }, 2); | ||||||
|  |             lfs_entry_fromle32(&entry->d); | ||||||
|  |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // we need to allocate a new dir block |         // we need to allocate a new dir block | ||||||
| @@ -614,10 +671,12 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             newdir.d.tail[0] = dir->d.tail[0]; |             newdir.d.tail[0] = dir->d.tail[0]; | ||||||
|             newdir.d.tail[1] = dir->d.tail[1]; |             newdir.d.tail[1] = dir->d.tail[1]; | ||||||
|             entry->off = newdir.d.size - 4; |             entry->off = newdir.d.size - 4; | ||||||
|  |             lfs_entry_tole32(&entry->d); | ||||||
|             err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){ |             err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){ | ||||||
|                     {entry->off, 0, &entry->d, sizeof(entry->d)}, |                     {entry->off, 0, &entry->d, sizeof(entry->d)}, | ||||||
|                     {entry->off, 0, data, entry->d.nlen} |                     {entry->off, 0, data, entry->d.nlen} | ||||||
|                 }, 2); |                 }, 2); | ||||||
|  |             lfs_entry_fromle32(&entry->d); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -703,6 +762,7 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|  |  | ||||||
|     int err = lfs_bd_read(lfs, dir->pair[0], dir->off, |     int err = lfs_bd_read(lfs, dir->pair[0], dir->off, | ||||||
|             &entry->d, sizeof(entry->d)); |             &entry->d, sizeof(entry->d)); | ||||||
|  |     lfs_entry_fromle32(&entry->d); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1065,6 +1125,7 @@ static int lfs_ctz_find(lfs_t *lfs, | |||||||
|                 lfs_ctz(current)); |                 lfs_ctz(current)); | ||||||
|  |  | ||||||
|         int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4); |         int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4); | ||||||
|  |         head = lfs_fromle32(head); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -1140,8 +1201,10 @@ static int lfs_ctz_extend(lfs_t *lfs, | |||||||
|             lfs_size_t skips = lfs_ctz(index) + 1; |             lfs_size_t skips = lfs_ctz(index) + 1; | ||||||
|  |  | ||||||
|             for (lfs_off_t i = 0; i < skips; i++) { |             for (lfs_off_t i = 0; i < skips; i++) { | ||||||
|  |                 head = lfs_tole32(head); | ||||||
|                 err = lfs_cache_prog(lfs, pcache, rcache, |                 err = lfs_cache_prog(lfs, pcache, rcache, | ||||||
|                         nblock, 4*i, &head, 4); |                         nblock, 4*i, &head, 4); | ||||||
|  |                 head = lfs_fromle32(head); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     if (err == LFS_ERR_CORRUPT) { |                     if (err == LFS_ERR_CORRUPT) { | ||||||
|                         goto relocate; |                         goto relocate; | ||||||
| @@ -1152,6 +1215,7 @@ static int lfs_ctz_extend(lfs_t *lfs, | |||||||
|                 if (i != skips-1) { |                 if (i != skips-1) { | ||||||
|                     err = lfs_cache_read(lfs, rcache, NULL, |                     err = lfs_cache_read(lfs, rcache, NULL, | ||||||
|                             head, 4*i, &head, 4); |                             head, 4*i, &head, 4); | ||||||
|  |                     head = lfs_fromle32(head); | ||||||
|                     if (err) { |                     if (err) { | ||||||
|                         return err; |                         return err; | ||||||
|                     } |                     } | ||||||
| @@ -1196,6 +1260,8 @@ static int lfs_ctz_traverse(lfs_t *lfs, | |||||||
|         lfs_block_t heads[2]; |         lfs_block_t heads[2]; | ||||||
|         int count = 2 - (index & 1); |         int count = 2 - (index & 1); | ||||||
|         err = lfs_cache_read(lfs, rcache, pcache, head, 0, &heads, count*4); |         err = lfs_cache_read(lfs, rcache, pcache, head, 0, &heads, count*4); | ||||||
|  |         heads[0] = lfs_fromle32(heads[0]); | ||||||
|  |         heads[1] = lfs_fromle32(heads[1]); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -1456,6 +1522,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|         lfs_entry_t entry = {.off = file->poff}; |         lfs_entry_t entry = {.off = file->poff}; | ||||||
|         err = lfs_bd_read(lfs, cwd.pair[0], entry.off, |         err = lfs_bd_read(lfs, cwd.pair[0], entry.off, | ||||||
|                 &entry.d, sizeof(entry.d)); |                 &entry.d, sizeof(entry.d)); | ||||||
|  |         lfs_entry_fromle32(&entry.d); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2075,6 +2142,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4; |     superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4; | ||||||
|  |  | ||||||
|     // write both pairs to be safe |     // write both pairs to be safe | ||||||
|  |     lfs_superblock_tole32(&superblock.d); | ||||||
|     bool valid = false; |     bool valid = false; | ||||||
|     for (int i = 0; i < 2; i++) { |     for (int i = 0; i < 2; i++) { | ||||||
|         err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){ |         err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){ | ||||||
| @@ -2125,6 +2193,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     if (!err) { |     if (!err) { | ||||||
|         err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d), |         err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d), | ||||||
|                 &superblock.d, sizeof(superblock.d)); |                 &superblock.d, sizeof(superblock.d)); | ||||||
|  |         lfs_superblock_fromle32(&superblock.d); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2182,6 +2251,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { | |||||||
|         while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { |         while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { | ||||||
|             err = lfs_bd_read(lfs, dir.pair[0], dir.off, |             err = lfs_bd_read(lfs, dir.pair[0], dir.off, | ||||||
|                     &entry.d, sizeof(entry.d)); |                     &entry.d, sizeof(entry.d)); | ||||||
|  |             lfs_entry_fromle32(&entry.d); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								lfs_util.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								lfs_util.h
									
									
									
									
									
								
							| @@ -70,6 +70,29 @@ static inline int lfs_scmp(uint32_t a, uint32_t b) { | |||||||
|     return (int)(unsigned)(a - b); |     return (int)(unsigned)(a - b); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static inline uint32_t lfs_fromle32(uint32_t a) { | ||||||
|  | #if ( \ | ||||||
|  |     (defined(  BYTE_ORDER  ) &&   BYTE_ORDER   ==   ORDER_LITTLE_ENDIAN  ) || \ | ||||||
|  |     (defined(__BYTE_ORDER  ) && __BYTE_ORDER   == __ORDER_LITTLE_ENDIAN  ) || \ | ||||||
|  |     (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) | ||||||
|  |     return a; | ||||||
|  | #elif ( \ | ||||||
|  |     (defined(  BYTE_ORDER  ) &&   BYTE_ORDER   ==   ORDER_BIG_ENDIAN  ) || \ | ||||||
|  |     (defined(__BYTE_ORDER  ) && __BYTE_ORDER   == __ORDER_BIG_ENDIAN  ) || \ | ||||||
|  |     (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) | ||||||
|  |     return __builtin_bswap32(a); | ||||||
|  | #else | ||||||
|  |     return (((uint8_t*)&a)[0] <<  0) | | ||||||
|  |            (((uint8_t*)&a)[1] <<  8) | | ||||||
|  |            (((uint8_t*)&a)[2] << 16) | | ||||||
|  |            (((uint8_t*)&a)[3] << 24); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline uint32_t lfs_tole32(uint32_t a) { | ||||||
|  |     return lfs_fromle32(a); | ||||||
|  | } | ||||||
|  |  | ||||||
| // CRC-32 with polynomial = 0x04c11db7 | // CRC-32 with polynomial = 0x04c11db7 | ||||||
| void lfs_crc(uint32_t *crc, const void *buffer, size_t size); | void lfs_crc(uint32_t *crc, const void *buffer, size_t size); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user