Mcucpp

Форк
0
514 строк · 11.0 Кб
1
#include <filesystem/fat.h>
2
#include <memory_stream.h>
3
#include <filesystem/file.h>
4
#include <template_utils.h>
5
#include <utf8.h>
6
#include <data_buffer.h>
7
#include <new>
8

9
namespace Mcucpp
10
{
11
namespace Fat
12
{
13
	using namespace Mcucpp::Fs;
14

15
	size_t DecodeShortName(const uint8_t* shortName, uint8_t *name)
16
	{
17
		size_t nameLen = 0;
18
		for(int i = 0; i < 11; i++)
19
		{
20
			if(i == 8)
21
			{
22
				*name++ = '.';
23
				nameLen++;
24
			}
25
			if(*shortName == 0x20)
26
			{
27
				shortName++;
28
				continue;
29
			}
30
			*name++ = *shortName++;
31
			nameLen++;
32
		}
33
		if(name[-1] == '.')
34
		{
35
			name--;
36
			nameLen--;
37
		}
38
		*name = 0;
39
		return nameLen;
40
	}
41

42
	uint8_t ShortNameCheckSum(const uint8_t* dirEntryName)
43
	{
44
		uint8_t result = 0;
45
		for (int i = 0; i < 11; i++)
46
		{
47
			result = ((result & 1) ? 0x80 : 0) + (result >> 1) + dirEntryName[i];
48
		}
49
		return result;
50
	}
51

52
	uint32_t FatFs::ClusterToSector(uint32_t cluster)
53
	{
54
		return (cluster - 2) * _fat.sectorPerCluster + _fat.firstDataSector;
55
	}
56

57
	uint32_t FatFs::SectorToClaster(uint32_t sector)
58
	{
59
		return (sector - _fat.firstDataSector) / _fat.sectorPerCluster + 2;
60
	}
61

62
	FatFs::FatFs(IBlockDevice &device)
63
		:_device(device),
64
		_lastError(ErrOK),
65
		_cachedSector(0xffffffff),
66
		_sectorBuffer(nullptr)
67
	{
68

69
	}
70

71
	MemoryStream FatFs::ReadSector(uint32_t sector)
72
	{
73
		if(_cachedSector != sector)
74
		{
75
			if(!_device.ReadPage(sector, _sectorBuffer, _fat.bytesPerSector, 0))
76
			{
77
				_lastError = ErrIoFailed;
78
			}
79
			_cachedSector = sector;
80
		}
81
		return MemoryStream(_sectorBuffer, _fat.bytesPerSector);
82
	}
83

84
	ErrorCode FatFs::GetError()
85
	{
86
		return _lastError;
87
	}
88

89
	bool FatFs::EndOfFile(Fs::FsNode node)
90
	{
91
		return node >= _fat.eocMarker;
92
	}
93

94
	FsNode FatFs::RootDirectory()
95
	{
96
		return FsNode(_fat.rootSector);
97
	}
98

99
	bool FatFs::ListDirectory(FsNode dir, DirectoryLister &directoryLister)
100
	{
101
		BinaryStream<Fs::File> drectory(*this, dir, -1);
102

103
		int lfnChecksum = -1;
104
		DataBuffer lfnBuffer;
105

106
		for(TFileSize dirEntryIndex = 0; !drectory.EndOfFile(); dirEntryIndex += DIR_ENTRY_SIZE)
107
		{
108
			drectory.Seek(dirEntryIndex);
109
			uint8_t marker = drectory.Read();
110
			if(marker == DELETED)
111
			{
112
				continue;
113
			}
114
			if(marker == EMPTY)
115
			{
116
				_lastError = ErrOK;
117
				return true;
118
			}
119

120
			drectory.Seek(dirEntryIndex + 11);
121
			uint8_t attr = drectory.Read();
122
			if(attr == 0xff)
123
			{
124
				continue;
125
			}
126
			drectory.Seek(dirEntryIndex);
127
			FileSystemEntry entry;
128

129
			if(attr == ATTR_LONG_NAME) // long name entry
130
			{
131
				lfnChecksum = ReadLfnEntry(drectory, lfnBuffer);
132
				continue;
133
			}
134
			else
135
			{
136
				if(!ReadDirEntry(drectory, entry, lfnChecksum, lfnBuffer))
137
				{
138
					return false;
139
				}
140
				lfnChecksum = -1;
141
			}
142
			lfnBuffer.Clear();
143
			bool stop = !directoryLister.DirectoryEntry(entry);
144

145
			if(stop)
146
			{
147
				_lastError = ErrOK;
148
				return true;
149
			}
150
		}
151
		_lastError = ErrOK;
152
		return true;
153
	}
154

155
	int FatFs::ReadLfnEntry(BinaryStream<Fs::File> &reader, DataBuffer &lfnBuffer)
156
	{
157
		uint8_t lfnSequence = reader.Read();
158
		if ((lfnSequence & 0x1F) == 0)
159
		{
160
			return -1;
161
		}
162
		if((lfnSequence & 0x40) != 0) // last LFN entry for item
163
		{
164
			lfnBuffer.Clear();
165
			lfnSequence &= 0x1F;
166
			lfnBuffer.InsertFront(lfnSequence * LfnNameChunkBytes);
167
		}
168

169
		lfnBuffer.Seek((lfnSequence - 1) * LfnNameChunkBytes);
170

171
		for(int i = 0; i < 5; i++)
172
		{
173
			lfnBuffer.WriteU16Le( reader.ReadU16Le());
174
		}
175

176
		reader.Read(); // attributes
177
		uint8_t type = reader.Read();
178
		if(type != 0) // not type LFN entry
179
		{
180
			return -1;
181
		}
182
		int lfnChecksum = reader.Read();
183

184
		for(int i = 0; i < 6; i++)
185
		{
186
			lfnBuffer.WriteU16Le(reader.ReadU16Le());
187
		}
188

189
		/*uint16_t fstClusLO = */reader.ReadU16Le(); // always 0
190
		for(int i = 0; i < 2; i++)
191
		{
192
			lfnBuffer.WriteU16Le(reader.ReadU16Le());
193
		}
194
		return lfnChecksum;
195
	}
196

197
	bool FatFs::ReadDirEntry(BinaryStream<Fs::File> &reader, FileSystemEntry &entry, int lfnChecksum, DataBuffer &lfnBuffer)
198
	{
199
		uint8_t shortName[12];
200
		reader.Read(shortName, 11);
201
		shortName[11] = 0;
202
		if(shortName[0] == 0x05)
203
		{
204
			shortName[0] = 0xE5;
205
		}
206
		uint8_t entryNameCecksum = ShortNameCheckSum(shortName);
207
		if(lfnChecksum >= 0 && entryNameCecksum == lfnChecksum)
208
		{
209
			size_t lfnSize = lfnBuffer.Size() / 2;
210
			lfnBuffer.Seek(0);
211
			size_t utf8Size = 0;
212
			for (size_t i = 0; i < lfnSize; i++)
213
			{
214
				uint16_t c = lfnBuffer.ReadU16Le();
215
				if (!c)
216
				{
217
					break;
218
				}
219
				utf8Size += Utf8Encoding<uint16_t>::EncodedLen(c);
220
			}
221

222
			lfnBuffer.Seek(0);
223
			uint8_t *utf8Buffer = new (std::nothrow) uint8_t[utf8Size + 1];
224
			uint8_t *utf8ptr = utf8Buffer;
225
			for (size_t i = 0; i < lfnSize; i++)
226
			{
227
				uint16_t c = lfnBuffer.ReadU16Le();
228
				if (!c)
229
				{
230
					break;
231
				}
232
				Utf8Encoding<uint16_t>::Encode(utf8ptr,c);
233
			}
234
			utf8Buffer[utf8Size] = 0;
235
			entry.SetName(utf8Buffer, utf8Size, false);
236
		}else
237
		{
238
			uint8_t decodedName[12];
239
			size_t nameLen = DecodeShortName(shortName, decodedName);
240
			entry.SetName(decodedName, nameLen);
241
		}
242

243
		uint8_t attr = reader.Read();
244
		uint8_t NTRes = reader.Read();
245
		uint8_t crtTimeTenth = reader.Read();
246
		uint16_t crtTime = reader.ReadU16Le();
247
		uint16_t crtDate = reader.ReadU16Le();
248
		uint16_t lstAccDate = reader.ReadU16Le();
249
		uint16_t fstClusHI = reader.ReadU16Le();
250
		uint16_t wrtTime = reader.ReadU16Le();
251
		uint16_t wrtDate = reader.ReadU16Le();
252
		uint16_t fstClusLO  = reader.ReadU16Le();
253
		uint32_t size = reader.ReadU32Le();
254

255
		entry.SetSize(size);
256
		entry.SetAttributes((Fs::FileAttributes)attr);
257
		entry.SetNode(ClusterToSector(fstClusLO | (((uint32_t)fstClusHI) << 16)));
258
		return true;
259
	}
260

261
	uint32_t FatFs::ReadFat(uint32_t sector, unsigned fatNum)
262
	{
263
		if(sector == _fat.eocMarker)
264
			return _fat.eocMarker;
265

266
		uint32_t cluster = SectorToClaster(sector);
267
		uint32_t fatEntryOffset;
268
		if(_fat.type == Fat12)
269
		{
270
			fatEntryOffset = cluster + cluster / 2;
271
		} else if(_fat.type == Fat16)
272
		{
273
			fatEntryOffset = cluster * 2;
274
		}else
275
		{
276
			fatEntryOffset = cluster * 4;
277
		}
278

279
		uint32_t fatEntrySector = _fat.reservedSectorCount +
280
			(fatEntryOffset / _fat.bytesPerSector) +
281
			fatNum * _fat.FATsize;
282
		uint32_t fatEntryOffsetInSector = fatEntryOffset % _fat.bytesPerSector;
283

284
		MemoryStream reader = ReadSector(fatEntrySector);
285
		if(GetError() != ErrOK)
286
		{
287
			return _fat.eocMarker;
288
		}
289
		reader.Seek(fatEntryOffsetInSector);
290
		uint32_t result = _fat.eocMarker;
291

292
		if(_fat.type == Fat12)
293
		{
294
			if(fatEntryOffsetInSector == uint32_t(_fat.bytesPerSector - 1))
295
			{
296
				result = reader.Read();
297
				MemoryStream reader = ReadSector(fatEntrySector + 1);
298
				result |= uint16_t(reader.Read()) << 8;
299
			}else{
300
				result = reader.ReadU16Le();
301
			}
302

303
			if((cluster & 1) != 0)
304
			{
305
				result >>= 4;
306
			}
307
			result &= 0X0fff;
308
		} else if(_fat.type == Fat16)
309
		{
310
			result = reader.ReadU16Le();
311
		}else
312
		{
313
			result = reader.ReadU32Le() & 0x0fffffff;
314
		}
315
		result = ClusterToSector(result);
316
		return result;
317
	}
318

319
	bool WriteFat(uint32_t cluster, uint32_t nextCluster)
320
	{
321
		return false;
322
	}
323

324
	uint32_t FatFs::GetParameter(FsParams param)
325
	{
326
		switch(param)
327
		{
328
			case BlockSize: return _fat.bytesPerSector;
329
			case ChunkSize: return _fat.bytesPerSector * _fat.sectorPerCluster;
330
			case BlocksInChunk: return _fat.sectorPerCluster;
331
			case TotalBlocks:
332
			case UsedBlocks:
333
			default: return 0;
334
		}
335
	}
336

337
	uint32_t FatFs::GetBlocksPerNode(Fs::FsNode node)
338
	{
339
		bool fat12_16_rootDir = _fat.rootDirSectors > 0 && node == RootDirectory();
340
		if(fat12_16_rootDir)
341
		{
342
			return  _fat.rootDirSectors;
343
		}
344
		return _fat.sectorPerCluster;
345
	}
346

347
	FsNode FatFs::GetNextChunk(FsNode node)
348
	{
349
		return ReadFat((uint32_t)node, 0);
350
	}
351

352
	FsNode FatFs::AllocNextChunk(FsNode parentNode)
353
	{
354
		return FsNode(0);
355
	}
356

357
	FsNode FatFs::CreateNode(FsNode parentDir, Fs::FileAttributes attributes, uint8_t *nodeName)
358
	{
359
		return FsNode(0);
360
	}
361

362
	bool FatFs::ReadBlock(FsNode node, uint8_t *buffer)
363
	{
364
		if(!_device.ReadPage((uint32_t)node, buffer, _fat.bytesPerSector, 0))
365
		{
366
			_lastError = ErrIoFailed;
367
			return false;
368
		}
369
		_lastError = ErrOK;
370
		return true;
371
	}
372

373
	bool FatFs::WriteBlock(FsNode node, const uint8_t *buffer)
374
	{
375
		if(!_device.WritePage((uint32_t)node, buffer, _fat.bytesPerSector, 0))
376
		{
377
			_lastError = ErrIoFailed;
378
			return false;
379
		}
380
		_lastError = ErrOK;
381
		return true;
382
	}
383

384
	void FatFs::Unmount()
385
	{
386
		if(_sectorBuffer)
387
		{
388
			delete [] _sectorBuffer;
389
		}
390
		_sectorBuffer = nullptr;
391
		_fat = FatInfo();
392
	}
393

394
	bool FatFs::Mount()
395
	{
396
		_fat = FatInfo();
397
		if(!_device.Enable())
398
		{
399
			_lastError = ErrDeviceNotReady;
400
			return false;
401
		}
402

403
		if(_sectorBuffer)
404
		{
405
			delete [] _sectorBuffer;
406
		}
407

408
		_fat.firstSector = 0;
409
		_fat.bytesPerSector = SectorSize;
410
		_sectorBuffer = new (std::nothrow) uint8_t[_fat.bytesPerSector];
411

412
		// read boot sector
413
		MemoryStream reader = ReadSector(_fat.firstSector);
414
		if(GetError() != ErrOK)
415
		{
416
			return false;
417
		}
418
		reader.Seek(0);
419
		uint8_t c = reader.Read();
420
		if(c != 0xE9 && c != 0xEB) // first setor is MBR
421
		{
422
			reader.Seek(446 + 8);
423
			_fat.firstSector = reader.ReadU32Le();
424
			reader.Seek(510);
425
			uint16_t sig = reader.ReadU16Le();
426

427
			if(sig != BootSignatureVal)
428
			{
429
				_lastError = ErrInvalidFs;
430
				return false;
431
			}
432

433
			reader = ReadSector(_fat.firstSector);
434
			if(GetError() != ErrOK)
435
			{
436
				return false;
437
			}
438
			uint8_t c = reader.Read();
439
			if(c != 0xE9 && c != 0xEB)
440
			{
441
				_lastError = ErrInvalidFs;
442
				return false;
443
			}
444
		}
445
		reader.Seek(11);
446
		_fat.bytesPerSector = reader.ReadU16Le();
447
		_fat.sectorPerCluster = reader.Read();
448
		_fat.reservedSectorCount = reader.ReadU16Le();
449
		_fat.numberofFATs = reader.Read();
450
		_fat.rootEntCnt = reader.ReadU16Le();
451
		_fat.totalSectors = reader.ReadU16Le();
452
		/*uint8_t  mediaType = */reader.Read();
453
		_fat.FATsize = reader.ReadU16Le();
454
		/*uint16_t sectorsPerTrack = */reader.ReadU16Le();
455
		/*uint16_t numberofHeads = */reader.ReadU16Le();
456
		_fat.hiddenSectors = reader.ReadU32Le();
457
		uint32_t totalSectors_F32 = reader.ReadU32Le();
458

459
		if(_fat.bytesPerSector > SectorSize)
460
		{
461
			delete [] _sectorBuffer;
462
			_sectorBuffer = new (std::nothrow) uint8_t[_fat.bytesPerSector];
463
		}
464

465
		if(_fat.totalSectors == 0)
466
			_fat.totalSectors = totalSectors_F32;
467

468
		uint32_t fat32RootCluster = 0;
469
		if(_fat.FATsize == 0)
470
		{
471
			_fat.FATsize = reader.ReadU32Le();
472
			/*uint16_t extFlags = */reader.ReadU16Le();
473
			/*uint16_t FSversion = */reader.ReadU16Le();
474
			fat32RootCluster = reader.ReadU32Le();
475
		}
476
		reader.Seek(510);
477
		uint16_t sig = reader.ReadU16Le();
478
		if(sig != 0xaa55)
479
		{
480
			_lastError = ErrInvalidFs;
481
			return false;
482
		}
483

484
		_fat.rootDirSectors = (_fat.rootEntCnt * 32 + _fat.bytesPerSector - 1) / _fat.bytesPerSector;
485
		_fat.firstDataSector = _fat.rootDirSectors + _fat.reservedSectorCount + _fat.FATsize * _fat.numberofFATs;
486
		uint32_t dataSec = _fat.totalSectors - (_fat.reservedSectorCount + _fat.FATsize * _fat.numberofFATs + _fat.rootDirSectors);
487
		_fat.countofClusters = dataSec / _fat.sectorPerCluster;
488
		if(fat32RootCluster == 0)
489
		{
490
			_fat.rootSector = (_fat.reservedSectorCount + _fat.FATsize * _fat.numberofFATs);
491
		}else
492
		{
493
			_fat.rootSector = ClusterToSector(fat32RootCluster);
494
		}
495

496
		if(_fat.countofClusters < 4085)
497
		{
498
			_fat.type = Fat12;
499
			_fat.eocMarker = 0x0FF8;
500
		} else if(_fat.countofClusters < 65525)
501
		{
502
			_fat.type = Fat16;
503
			_fat.eocMarker = 0xFFF8;
504
		} else
505
		{
506
			_fat.type = Fat32;
507
			_fat.eocMarker = 0x0FFFFFF8;
508
		}
509

510
		return true;
511
	}
512

513
}
514
}
515

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.