Contiki-Inga 3.x
fat_mkfs.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Institute of Operating Systems and Computer Networks (TU Brunswick).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * Author: Christoph Peltz <peltz@ibr.cs.tu-bs.de>
30  */
31 
32 /**
33  * \addtogroup Drivers
34  * @{
35  *
36  * \addtogroup fat_driver
37  * @{
38  */
39 
40 /**
41  * \file
42  * FAT driver mkfs implementation
43  * \author
44  * Christoph Peltz <peltz@ibr.cs.tu-bs.de>
45  * Enrico Joerns <joerns.ibr.cs.tu-bs.de>
46  */
47 
48 #include "cfs-fat.h"
49 
50 #define DEBUG 0
51 #if DEBUG
52 #include <stdio.h>
53 #define PRINTF(...) printf(__VA_ARGS__)
54 #else
55 #define PRINTF(...)
56 #endif
57 
58 /* specifies divisor of fat size to erase during mkfs, because erasing the whole FAT
59  * may take some time.
60  * e.g. FAT_ERASE_DIV set to 4 means 1/4 of the fat will be erased.
61  */
62 #define FAT_ERASE_DIV 2
63 
64 
65 static int mkfs_write_boot_sector(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi);
66 static void mkfs_write_fats(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi);
67 static void mkfs_write_fsinfo(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi);
68 static void mkfs_write_root_directory(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi);
69 static uint8_t mkfs_calc_cluster_size(uint16_t sec_size, uint16_t bytes);
70 static uint16_t mkfs_determine_fat_type_and_SPC(uint32_t total_sec_count, uint16_t bytes_per_sec);
71 static uint32_t mkfs_compute_fat_size(struct FAT_Info *fi);
72 /*----------------------------------------------------------------------------*/
73 int
75 {
76  uint8_t buffer[512];
77  struct FAT_Info fi;
78  int ret = 0;
79 
80  PRINTF("\nWriting boot sector ... ");
81 
82  memset(buffer, 0, 512);
83  ret = mkfs_write_boot_sector(buffer, dev, &fi);
84 
85  if (ret != 0) {
86  PRINTF("Error(%d).", ret);
87  return 1;
88  } else {
89  PRINTF("done.");
90  }
91 
92  PRINTF("\nWriting FATs ... ");
93  mkfs_write_fats(buffer, dev, &fi);
94 
95  if (fi.type == FAT32) {
96  PRINTF("done.\nWriting FSINFO ... ");
97  mkfs_write_fsinfo(buffer, dev, &fi);
98  }
99  PRINTF("done.\n");
100 
101  PRINTF("Writing root directory ... ");
102  mkfs_write_root_directory(buffer, dev, &fi);
103  PRINTF("done.");
104 
105  return 0;
106 }
107 /*----------------------------------------------------------------------------*/
108 /**
109  * Determines the number of sectors per cluster.
110  *
111  * \param sec_size The size of one sector in bytes.
112  * \param bytes number of bytes one cluster should be big
113  * \return 1,2,4,8,16,32,64,128 depending on the number of sectors per cluster
114  */
115 static uint8_t
116 mkfs_calc_cluster_size(uint16_t sec_size, uint16_t bytes)
117 {
118  uint8_t SecPerCluster = 0;
119 
120  SecPerCluster = (uint8_t) (bytes / sec_size);
121 
122  if (SecPerCluster == 0) {
123  return 1;
124  }
125 
126  if (is_a_power_of_2(SecPerCluster) != 0) {
127  SecPerCluster = (uint8_t) round_down_to_power_of_2(SecPerCluster);
128  }
129 
130  if (SecPerCluster > 128 || SecPerCluster * sec_size > 32 * ((uint32_t) 1024)) {
131  return 1;
132  }
133 
134  return SecPerCluster;
135 }
136 /*----------------------------------------------------------------------------*/
137 /**
138  * Determines for mkfs which FAT-Type and cluster-size should be used.
139  *
140  * This is based upon the FAT specification, which states that the table only works for 512
141  * Bytes sized sectors. For that the function SPC is used to compute this right. but
142  * it probalby only works for powers of 2 in the bytes_per_sec field. It tries to use FAT16
143  * if at all possible, FAT32 only when there is no other choice.
144  * \param total_sec_count the total number of sectors of the filesystem
145  * \param bytes_per_sec how many bytes are there in one sector
146  * \return in the upper two bits is the fat type, either FAT12, FAT16, FAT32 or FAT_INVALID. In the lower 8 bits is the number of sectors per cluster.
147  */
148 static uint16_t
149 mkfs_determine_fat_type_and_SPC(uint32_t total_sec_count, uint16_t bytes_per_sec)
150 {
151  uint64_t vol_size = (total_sec_count * bytes_per_sec) / 512;
152 
153  if (vol_size < ((uint32_t) 8400)) {
154  return (FAT16 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 512);
155  } else if (vol_size < 32680) {
156  return (FAT16 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 1024);
157  } else if (vol_size < 262144) {
158  return (FAT16 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 2048);
159  } else if (vol_size < 524288) {
160  return (FAT16 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 4096);
161  } else if (vol_size < 1048576) {
162  return (FAT16 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 8192);
163  } else if (vol_size < 2097152) {
164  return (FAT16 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 16384);
165  } else if (vol_size < 4194304L) {
166  return (FAT32 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 2048);
167  }
168 
169  if (vol_size < 16777216) {
170  return (FAT32 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 4096);
171  } else if (vol_size < 33554432) {
172  return (FAT32 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 8192);
173  } else if (vol_size < 67108864) {
174  return (FAT32 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 16384);
175  } else if (vol_size < 0xFFFFFFFF) {
176  return (FAT32 << 8) +mkfs_calc_cluster_size(bytes_per_sec, 32768);
177  } else {
178  return (FAT_INVALID << 8) + 0;
179  }
180 }
181 /*----------------------------------------------------------------------------*/
182 /**
183  * Computes the required size of one FAT according to standard formula.
184  *
185  * \param fi FAT_Info structure that must contain BPB_RootEntCnt, BPB_BytesPerSec, BPB_TotSec, BPB_RsvdSecCnt, BPB_NumFATs and type.
186  * \return the required size of one FAT [sectors] for this FS.
187  */
188 static uint32_t
189 mkfs_compute_fat_size(struct FAT_Info *fi)
190 {
191  uint32_t FATSz = 0;
192  uint16_t RootDirSectors = ((fi->BPB_RootEntCnt * 32) + (fi->BPB_BytesPerSec - 1)) / fi->BPB_BytesPerSec;
193  uint32_t TmpVal1 = fi->BPB_TotSec - (fi->BPB_RsvdSecCnt + RootDirSectors);
194  uint32_t TmpVal2 = (256UL * fi->BPB_SecPerClus) + fi->BPB_NumFATs;
195 
196  if (fi->type == FAT32) {
197  TmpVal2 /= 2;
198  }
199 
200  FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
201 
202  PRINTF("\nFat size: %ld", FATSz);
203  return FATSz;
204 }
205 /*----------------------------------------------------------------------------*/
206 static int
207 mkfs_write_boot_sector(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi)
208 {
209  // Test if we can make FAT16 or FAT32
210  uint16_t type_SPC = mkfs_determine_fat_type_and_SPC(dev->num_sectors, dev->sector_size);
211  uint8_t sectors_per_cluster = (uint8_t) type_SPC;
212 
213  fi->BPB_FATSz = 0;
214  fi->type = (uint8_t) (type_SPC >> 8);
215 
216  PRINTF("\nA: SPC = %u; type = %u; dev->num_sectors = %lu", sectors_per_cluster, fi->type, dev->num_sectors);
217  if (fi->type == FAT12 || fi->type == FAT_INVALID) {
218  return -1;
219  }
220 
221  // BS_jmpBoot
222  buffer[0x000] = 0x00;
223  buffer[0x001] = 0x00;
224  buffer[0x002] = 0x00;
225 
226  // BS_OEMName
227  memcpy(&(buffer[0x03]), "cfs-mkfs", 8);
228 
229  // BPB_BytesPerSec
230  buffer[0x00B] = (uint8_t) dev->sector_size;
231  buffer[0x00C] = (uint8_t) (dev->sector_size >> 8);
232  fi->BPB_BytesPerSec = dev->sector_size;
233 
234  // BPB_SecPerClus
235  buffer[0x00D] = sectors_per_cluster;
236  fi->BPB_SecPerClus = sectors_per_cluster;
237 
238  //BPB_RsvdSecCnt
239  if (fi->type == FAT16) {
240  buffer[0x00E] = 1;
241  buffer[0x00F] = 0;
242  fi->BPB_RsvdSecCnt = 1;
243  } else if (fi->type == FAT32) {
244  buffer[0x00E] = 32;
245  buffer[0x00F] = 0;
246  fi->BPB_RsvdSecCnt = 32;
247  }
248 
249  // BPB_NumFATs
250  buffer[0x010] = 2;
251  fi->BPB_NumFATs = 2;
252 
253  // BPB_RootEntCnt
254  if (fi->type == FAT16) {
255  buffer[0x011] = (uint8_t) 512;
256  buffer[0x012] = (uint8_t) (512 >> 8);
257  fi->BPB_RootEntCnt = 512;
258  } else if (fi->type == FAT32) {
259  buffer[0x011] = 0;
260  buffer[0x012] = 0;
261  fi->BPB_RootEntCnt = 0;
262  }
263 
264  // BPB_TotSec16
265  if (dev->num_sectors < 0x10000) {
266  buffer[0x013] = (uint8_t) dev->num_sectors;
267  buffer[0x014] = (uint8_t) (dev->num_sectors >> 8);
268  } else {
269  buffer[0x013] = 0;
270  buffer[0x014] = 0;
271  }
272  fi->BPB_TotSec = dev->num_sectors;
273 
274  // BPB_Media
275  buffer[0x015] = 0xF8;
276  fi->BPB_Media = 0xF8;
277 
278  // BPB_FATSz16
279  fi->BPB_FATSz = mkfs_compute_fat_size(fi);
280 
281  if (fi->type == FAT16 && fi->BPB_FATSz < 0x10000) {
282  buffer[0x016] = (uint8_t) fi->BPB_FATSz;
283  buffer[0x017] = (uint8_t) (fi->BPB_FATSz >> 8);
284  } else if (fi->type == FAT16) {
285  PRINTF("B: FATSz = %lu", fi->BPB_FATSz);
286  return -1;
287  } else {
288  // unused in FAT32 -> see offset 24h
289  buffer[0x016] = 0;
290  buffer[0x017] = 0;
291  }
292 
293  // BPB_SecPerTrk
294  buffer[0x018] = 0;
295  buffer[0x019] = 0;
296 
297  // BPB_NumHeads
298  buffer[0x01A] = 0;
299  buffer[0x01B] = 0;
300 
301  // BPB_HiddSec
302  buffer[0x01C] = 0;
303  buffer[0x01D] = 0;
304  buffer[0x01E] = 0;
305  buffer[0x01F] = 0;
306 
307  // BPB_TotSec32
308  if (dev->num_sectors < 0x10000) {
309  buffer[0x020] = 0;
310  buffer[0x021] = 0;
311  buffer[0x022] = 0;
312  buffer[0x023] = 0;
313  } else {
314  buffer[0x020] = (uint8_t) fi->BPB_TotSec;
315  buffer[0x021] = (uint8_t) (fi->BPB_TotSec >> 8);
316  buffer[0x022] = (uint8_t) (fi->BPB_TotSec >> 16);
317  buffer[0x023] = (uint8_t) (fi->BPB_TotSec >> 24);
318  }
319 
320  if (fi->type == FAT16) {
321  // BS_DrvNum
322  buffer[0x024] = 0x80;
323 
324  // BS_Reserved1
325  buffer[0x025] = 0;
326 
327  // BS_BootSig
328  buffer[0x026] = 0x29;
329 
330  // BS_VolID
331  buffer[0x027] = 0;
332  buffer[0x028] = 0;
333  buffer[0x029] = 0;
334  buffer[0x02A] = 0;
335 
336  // BS_VolLab
337  memcpy(&(buffer[0x02B]), "NO NAME ", 11);
338 
339  // BS_FilSysType
340  memcpy(&(buffer[0x036]), "FAT16 ", 8);
341  } else if (fi->type == FAT32) {
342  // BPB_FATSz32
343  buffer[0x024] = (uint8_t) fi->BPB_FATSz;
344  buffer[0x025] = (uint8_t) (fi->BPB_FATSz >> 8);
345  buffer[0x026] = (uint8_t) (fi->BPB_FATSz >> 16);
346  buffer[0x027] = (uint8_t) (fi->BPB_FATSz >> 24);
347 
348  // BPB_ExtFlags
349  buffer[0x028] = 0;
350  buffer[0x029] = 0; // Mirror enabled, TODO:...
351 
352  // BPB_FSVer
353  buffer[0x02A] = 0;
354  buffer[0x02B] = 0;
355 
356  // BPB_RootClus, cluster number of root cluster (typically 2)
357  buffer[0x02C] = 2;
358  buffer[0x02D] = 0;
359  buffer[0x02E] = 0;
360  buffer[0x02F] = 0;
361 
362  // BPB_FSInfo
363  buffer[0x030] = 1;
364  buffer[0x031] = 0;
365 
366  // BPB_BkBootSec, set to 0 as we do not create a boot sectors copy yet
367  // TODO: maybe we should create it, as it does not require to much effort?
368  buffer[0x032] = 0x00;
369  buffer[0x033] = 0x00;
370 
371  // BPB_Reserved
372  memset(&(buffer[0x034]), 0, 12);
373 
374  // BS_DrvNum
375  buffer[0x040] = 0x80;
376 
377  // BS_Reserved1
378  buffer[0x041] = 0;
379 
380  // BS_BootSig
381  buffer[0x042] = 0x29;
382 
383  // BS_VolID
384  buffer[0x043] = 0;
385  buffer[0x044] = 0;
386  buffer[0x045] = 0;
387  buffer[0x046] = 0;
388 
389  // BS_VolLab
390  memcpy(&(buffer[0x047]), "NO NAME ", 11);
391 
392  // BS_FilSysType
393  memcpy(&(buffer[0x052]), "FAT32 ", 8);
394  }
395 
396  // Specification demands this values at this precise positions
397  buffer[0x1FE] = 0x55;
398  buffer[0x1FF] = 0xAA;
399 
400  diskio_write_block(dev, 0, buffer);
401 
402  return 0;
403 }
404 /*----------------------------------------------------------------------------*/
405 /**
406  * Writes the FAT-Portions of the FS.
407  *
408  * \param buffer Buffer / 2 and buffer / 4 should be integers.
409  * \param dev the Device where the FATs are written to
410  */
411 static void
412 mkfs_write_fats(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi)
413 {
414  uint32_t *fat32_buf = (uint32_t *) buffer;
415  uint16_t *fat16_buf = (uint16_t *) buffer;
416  uint32_t i = 0;
417 #if FAT_SYNC
418  uint32_t j = 0;
419 #endif
420 
421  memset(buffer, 0x00, 512);
422  if (fi->type == FAT32) {
423  // BPB_Media Copy
424  fat32_buf[0] = 0x0FFFFF00 + fi->BPB_Media;
425  // End of Clusterchain marker
426  fat32_buf[1] = 0x0FFFFFFF;
427  // End of Clusterchain marker for root directory at cluster 2
428  fat32_buf[2] = 0x0FFFFFF8;
429  } else {
430  // BPB_Media Copy
431  fat16_buf[0] = 0xFF00 + fi->BPB_Media;
432  // End of Clusterchain marker
433  fat16_buf[1] = 0xFFF8;
434  }
435 
436  // Write first sector of the FATs
437  diskio_write_block(dev, fi->BPB_RsvdSecCnt, buffer);
438 #if FAT_SYNC
439  // Write first sector of the secondary FAT(s)
440  for (j = 1; j < fi->BPB_NumFATs; ++j) {
441  diskio_write_block(dev, fi->BPB_RsvdSecCnt + fi->BPB_FATSz * j, buffer);
442  }
443 #endif
444 
445  // Reset previously written first 96 bits = 12 Bytes of the buffer
446  memset(buffer, 0x00, 12);
447 
448  // Write additional Sectors of the FATs
449  diskio_write_blocks_start(dev, fi->BPB_RsvdSecCnt + 1, fi->BPB_FATSz / 2);
450  for (i = 1; i < fi->BPB_FATSz / FAT_ERASE_DIV; ++i) {
452  diskio_write_blocks_next(dev, buffer);
453  //diskio_write_block(dev, fi->BPB_RsvdSecCnt + i, buffer);
454  }
456 
457 #if FAT_SYNC
458  // Write additional Sectors of the secondary FAT(s)
459  for (j = 1; j < fi->BPB_NumFATs; ++j) {
460  for (i = 1; i < fi->BPB_FATSz; ++i) {
461  diskio_write_block(dev, fi->BPB_RsvdSecCnt + i + fi->BPB_FATSz * j, buffer);
462  }
463  }
464 #endif
465 }
466 /*----------------------------------------------------------------------------*/
467 static void
468 mkfs_write_fsinfo(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi)
469 {
470  uint32_t fsi_free_count = 0;
471  uint32_t fsi_nxt_free = 0;
472 
473  memset(buffer, 0, 512);
474  // FSI_LeadSig
475  buffer[0] = 0x52;
476  buffer[1] = 0x52;
477  buffer[2] = 0x61;
478  buffer[3] = 0x41;
479 
480  // FSI_Reserved1
481 
482  // FSI_StrucSig
483  buffer[484] = 0x72;
484  buffer[485] = 0x72;
485  buffer[486] = 0x41;
486  buffer[487] = 0x61;
487 
488  // FSI_Free_Count
489  fsi_free_count = (fi->BPB_TotSec - ((fi->BPB_FATSz * fi->BPB_NumFATs) + fi->BPB_RsvdSecCnt)) / fi->BPB_SecPerClus;
490  buffer[488] = (uint8_t) fsi_free_count;
491  buffer[489] = (uint8_t) (fsi_free_count >> 8);
492  buffer[490] = (uint8_t) (fsi_free_count >> 16);
493  buffer[491] = (uint8_t) (fsi_free_count >> 24);
494 
495  // FSI_Nxt_Free
496  fsi_nxt_free = (fi->BPB_RsvdSecCnt + (fi->BPB_NumFATs * fi->BPB_FATSz));
497  if (fsi_nxt_free % fi->BPB_SecPerClus) {
498  fsi_nxt_free = (fsi_nxt_free / fi->BPB_SecPerClus) + 1;
499  } else {
500  fsi_nxt_free = (fsi_nxt_free / fi->BPB_SecPerClus);
501  }
502  buffer[492] = (uint8_t) fsi_nxt_free;
503  buffer[493] = (uint8_t) (fsi_nxt_free >> 8);
504  buffer[494] = (uint8_t) (fsi_nxt_free >> 16);
505  buffer[495] = (uint8_t) (fsi_nxt_free >> 24);
506 
507  // FSI_Reserved2
508 
509  // FSI_TrailSig
510  buffer[508] = 0x00;
511  buffer[509] = 0x00;
512  buffer[510] = 0x55;
513  buffer[511] = 0xAA;
514 
515  diskio_write_block(dev, 1, buffer);
516 }
517 /*----------------------------------------------------------------------------*/
518 static void
519 mkfs_write_root_directory(uint8_t *buffer, struct diskio_device_info *dev, struct FAT_Info *fi)
520 {
521  // TODO: respect root cluster entry in boot sector
522  uint16_t i;
523  uint32_t firstDataSector = fi->BPB_RsvdSecCnt + (fi->BPB_NumFATs * fi->BPB_FATSz);// TODO: + RootDirSectors
524  memset(buffer, 0x00, 512);
525 
526  // clear first root cluster
527  for (i = 0; i < fi->BPB_SecPerClus; i++) {
528  diskio_write_block(dev, firstDataSector + i, buffer);
529  }
530 }
531 /*----------------------------------------------------------------------------*/