Corrections and debug channel in the Incomplete Mass Storage class bootloader.
[pub/USBasp.git] / Bootloaders / Incomplete / MassStorage / Lib / VirtualFAT.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2013.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 #include "VirtualFAT.h"
32
33 #define FAT_TIME(h, m, s) ((h << 11) | (m << 5) | (s >> 1))
34 #define FAT_DATE(d, m, y) (((y - 1980) << 9) | (m << 5) | (d << 0))
35
36 #define SECTOR_SIZE_BYTES VIRTUAL_MEMORY_BLOCK_SIZE
37 #define SECTOR_PER_CLUSTER 4
38 #define CLUSTER_SIZE_BYTES (SECTOR_PER_CLUSTER * SECTOR_SIZE_BYTES)
39
40 #define FILE_CLUSTERS(size) (size / CLUSTER_SIZE_BYTES)
41
42 static const FATBootBlock_t BootBlock =
43 {
44 .Bootstrap = {0xEB, 0x3C, 0x90},
45 .Description = "mkdosfs",
46 .SectorSize = SECTOR_SIZE_BYTES,
47 .SectorsPerCluster = SECTOR_PER_CLUSTER,
48 .ReservedSectors = 1,
49 .FATCopies = 2,
50 .RootDirectoryEntries = SECTOR_SIZE_BYTES / sizeof(FATDirectoryEntry_t),
51 .TotalSectors16 = LUN_MEDIA_BLOCKS,
52 .MediaDescriptor = 0xF8,
53 .SectorsPerFAT = 1,
54 .SectorsPerTrack = 32,
55 .Heads = 64,
56 .HiddenSectors = 0,
57 .TotalSectors32 = 0,
58 .PhysicalDriveNum = 0,
59 .ExtendedBootRecordSig = 0x29,
60 .VolumeSerialNumber = 0x12345678,
61 .VolumeLabel = "LUFA BOOT ",
62 .FilesystemIdentifier = "FAT16 ",
63 .BootstrapProgram = {0},
64 .MagicSignature = 0xAA55,
65 };
66
67 static FATDirectoryEntry_t FirmwareFileEntry =
68 {
69 .Filename = "FIRMWARE",
70 .Extension = "BIN",
71 .Attributes = 0,
72 .Reserved = {0},
73 .CreationTime = FAT_TIME(1, 1, 0),
74 .CreationDate = FAT_DATE(14, 2, 1989),
75 .StartingCluster = 2,
76 .FileSizeBytes = 2049,
77 };
78
79 static void WriteBlock(uint16_t BlockNumber)
80 {
81 uint8_t BlockBuffer[512];
82
83 /* Wait until endpoint is ready before continuing */
84 if (Endpoint_WaitUntilReady())
85 return;
86
87 Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
88 Endpoint_ClearOUT();
89
90 printf("WRITE %d\r\n", BlockNumber);
91 // TODO: Write to FLASH
92 }
93
94 static void ReadBlock(uint16_t BlockNumber)
95 {
96 uint8_t BlockBuffer[512];
97 memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
98
99 printf("READ %d", BlockNumber);
100
101 switch (BlockNumber)
102 {
103 case 0:
104 memcpy(BlockBuffer, &BootBlock, sizeof(FATBootBlock_t));
105 printf(" <B>\r\n");
106 break;
107
108 case 1:
109 case 2:
110 printf(" <F>\r\n");
111
112 /* Cluster 0: Media type/Reserved */
113 ((uint16_t*)&BlockBuffer)[0] = 0xFF00 | BootBlock.MediaDescriptor;
114
115 /* Cluster 1: Reserved */
116 ((uint16_t*)&BlockBuffer)[1] = 0xFFFF;
117
118 /* Cluster 2 onwards: Cluster chain of FIRMWARE.BIN */
119 for (uint16_t i = 0; i < FILE_CLUSTERS(2049); i++)
120 {
121 ((uint16_t*)&BlockBuffer)[i + 2] = i + 3;
122 }
123
124 /* Mark last cluster as end of file */
125 ((uint16_t*)&BlockBuffer)[FILE_CLUSTERS(2049) + 3] = 0xFFFF;
126 break;
127
128 case 3:
129 printf("<R>\r\n");
130 memcpy(BlockBuffer, &FirmwareFileEntry, sizeof(FATDirectoryEntry_t));
131 break;
132
133 default:
134 if ((BlockNumber >= 4) && (BlockNumber < (4 + FILE_CLUSTERS(FIRMWARE_FILE_SIZE))))
135 {
136 printf("<D>\r\n");
137
138 for (uint16_t i = 0; i < 512; i++)
139 BlockBuffer[i] = '0' + BlockNumber; //A' + (i % 26);
140 }
141
142 break;
143 }
144
145 /* Wait until endpoint is ready before continuing */
146 if (Endpoint_WaitUntilReady())
147 return;
148
149 Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
150 Endpoint_ClearIN();
151 }
152
153 void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
154 const uint32_t BlockAddress,
155 uint16_t TotalBlocks)
156 {
157 uint16_t CurrentBlock = (uint16_t)BlockAddress;
158
159 while (TotalBlocks--)
160 WriteBlock(CurrentBlock++);
161 }
162
163 void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
164 const uint32_t BlockAddress,
165 uint16_t TotalBlocks)
166 {
167 uint16_t CurrentBlock = (uint16_t)BlockAddress;
168
169 while (TotalBlocks--)
170 ReadBlock(CurrentBlock++);
171 }
172