summaryrefslogtreecommitdiff
path: root/fs/fat/fat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fat/fat.c')
-rw-r--r--fs/fat/fat.c308
1 files changed, 308 insertions, 0 deletions
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 492051b623..4501876789 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1261,3 +1261,311 @@ int fat_read_file(const char *filename, void *buf, int offset, int len)
void fat_close(void)
{
}
+
+/*
+ * Copy string, padding with spaces.
+ */
+static void
+setstr(u_int8_t *dest, const char *src, size_t len)
+{
+ while (len--)
+ *dest++ = *src ? *src++ : ' ';
+}
+
+static int write_pbr(block_dev_desc_t *dev_desc, disk_partition_t *info)
+{
+ struct bs *bs;
+ struct bsbpb *bsbpb;
+ struct bsxbpb *bsxbpb;
+ struct bsx *bsx;
+ __u8 *img;
+ int img_offset = 0;
+ int reserved_cnt= 0;
+ int i;
+ int fat_size = 0;
+
+ img = malloc(sizeof(__u8)*512);
+ if(img == NULL) {
+ printf("Can't make img buffer~~!!\n");
+ return -1;
+ }
+ memset(img, 0x0, sizeof(__u8)*512);
+
+
+ /* Erase Reserved Sector(PBR) */
+ for (i = 0;i < RESERVED_CNT; i++) {
+ if (dev_desc->block_write(dev_desc->dev, info->start + i,
+ 1, (ulong *)img) != 1) {
+ printf ("Can't erase reserved sector~~~!!!\n");
+ return -1;
+ }
+ }
+
+ /* Set bs */
+ bs = (struct bs *)img;
+ img_offset += sizeof(struct bs) - 1;
+
+ mk1(bs->jmp[0], 0xeb);
+ mk1(bs->jmp[1], 0x58);
+ mk1(bs->jmp[2], 0x90); /* Jump Boot Code */
+ setstr(bs->oem, "SAMSUNG", sizeof(bs->oem)); /* OEM Name */
+
+ uint spc;
+ /* Set bsbpb */
+ bsbpb = (struct bsbpb *)(img + img_offset);
+ img_offset += sizeof(struct bsbpb) - 2;
+
+ mk2(bsbpb->bps, 512); /* Byte Per Sector */
+
+ printf("size checking ...\n");
+ /* Sector Per Cluster */
+ if (info->size < 0x10000) { /* partition size >= 32Mb */
+ printf("Can't format less than 32Mb partition!!\n");
+ return -1;
+ }
+ if (info->size <= 0x20000) { /* under 64M -> 512 bytes */
+ printf("Under 64M\n");
+ mk1(bsbpb->spc, 1);
+ spc = 1;
+ }
+ else if (info->size <= 0x40000) { /* under 128M -> 1K */
+ printf("Under 128M\n");
+ mk1(bsbpb->spc, 2);
+ spc = 2;
+ }
+ else if (info->size <= 0x80000) { /* under 256M -> 2K */
+ printf("Under 256M\n");
+ mk1(bsbpb->spc, 4);
+ spc = 4;
+ }
+ else if (info->size <= 0xFA0000) { /* under 8G -> 4K */
+ printf("Under 8G\n");
+ mk1(bsbpb->spc, 8);
+ spc = 8;
+ }
+ else if (info->size <= 0x1F40000) { /* under 16G -> 8K */
+ printf("Under 16G\n");
+ mk1(bsbpb->spc, 16);
+ spc = 16;
+ }
+ else {
+ printf("16G~\n");
+ mk1(bsbpb->spc, 32);
+ spc = 32;
+ }
+
+ printf("write FAT info: %d\n",RESERVED_CNT);
+ mk2(bsbpb->res, RESERVED_CNT); /* Reserved Sector Count */
+ mk1(bsbpb->nft, 2); /* Number of FATs */
+ mk2(bsbpb->rde, 0); /* Root Directory Entry Count : It's no use in FAT32 */
+ mk2(bsbpb->sec, 0); /* Total Sector : It's no use in FAT32 */
+ mk1(bsbpb->mid, 0xF8); /* Media */
+ mk2(bsbpb->spf, 0); /* FAT Size 16 : It's no use in FAT32 */
+ mk2(bsbpb->spt, 0); /* Sector Per Track */
+ mk2(bsbpb->hds, 0); /* Number Of Heads */
+ mk4(bsbpb->hid, 0); /* Hidden Sector */
+ mk4(bsbpb->bsec, info->size); /* Total Sector For FAT32 */
+
+ /* Set bsxbpb */
+ bsxbpb = (struct bsxbpb *)(img + img_offset);
+ img_offset += sizeof(struct bsxbpb);
+
+ mk4(bsxbpb->bspf, (info->size / (spc * 128))); /* FAT Size 32 */
+ fat_size = info->size / (spc * 128);
+ printf("Fat size : 0x%x\n", info->size / (spc * 128));
+ mk2(bsxbpb->xflg, 0); /* Ext Flags */
+ mk2(bsxbpb->vers, 0); /* File System Version */
+ mk4(bsxbpb->rdcl, 2); /* Root Directory Cluster */
+ mk2(bsxbpb->infs, 1); /* File System Information */
+ mk2(bsxbpb->bkbs, 0); /* Boot Record Backup Sector */
+ /* Set bsx */
+ bsx = (struct bsx *)(img + img_offset);
+ mk1(bsx->drv, 0); /* Drive Number */
+ mk1(bsx->sig, 0x29); /* Boot Signature */
+ mk4(bsx->volid, 0x3333); /* Volume ID : 0x3333 means nothing */
+ setstr(bsx->label, "NO NAME ", sizeof(bsx->label)); /* Volume Label */
+ setstr(bsx->type, "FAT32", sizeof(bsx->type)); /* File System Type */
+
+ /* Set Magic Number */
+ mk2(img + BYTE_PER_SEC - 2, 0xaa55); /* Signature */
+
+/*
+ printf("Print Boot Recode\n");
+ for(i = 0;i<512;i++) {
+ if(img[i] == 0)
+ printf("00 ");
+ else
+ printf("%2x ", img[i]);
+ if (!((i+1) % 16))
+ printf("\n");
+ }
+*/
+
+ if (dev_desc->block_write(dev_desc->dev, info->start,
+ 1, (ulong *)img) != 1) {
+ printf ("Can't write PBR~~~!!!\n");
+ return -1;
+ }
+
+ return fat_size;
+}
+
+static int write_reserved(block_dev_desc_t *dev_desc, disk_partition_t *info)
+{
+ /* Set Reserved Region */
+ __u8 *img;
+ int i;
+ img = malloc(sizeof(__u8)*512);
+ if(img == NULL) {
+ printf("Can't make img buffer~~(reserved)!!\n");
+ return -1;
+ }
+
+ memset(img, 0x0, sizeof(__u8)*512);
+
+ mk4(img, 0x41615252); /* Lead Signature */
+ mk4(img + BYTE_PER_SEC - 28, 0x61417272); /* Struct Signature */
+ mk4(img + BYTE_PER_SEC - 24, 0xffffffff); /* Free Cluster Count */
+ mk4(img + BYTE_PER_SEC - 20, 0x3); /* Next Free Cluster */
+ mk2(img + BYTE_PER_SEC - 2, 0xaa55); /* Trail Signature */
+
+ /* Write Reserved region */
+ if (dev_desc->block_write(dev_desc->dev, info->start+1,
+ 1, (ulong *)img) != 1) {
+ printf ("Can't write reserved region~~~!!!\n");
+ return -1;
+ }
+
+ return 1;
+}
+
+static int write_fat(block_dev_desc_t *dev_desc, disk_partition_t *info, int
+fat_size)
+{
+ __u8 *dummy;
+ __u8 *img;
+ int i;
+
+ /* Create buffer for FAT */
+ img = malloc(sizeof(__u8)*512);
+ if(img == NULL) {
+ printf("Can't make img buffer~~!!\n");
+ return -1;
+ }
+ memset(img, 0x0, sizeof(__u8) * 512);
+
+ /* Create buffer for erase */
+ dummy = malloc(sizeof(__u8) * 8192);
+ if(dummy == NULL) {
+ printf("Can't make dummy buffer~~!!\n");
+ return -1;
+ }
+ memset(dummy, 0x0, sizeof(__u8) * 8192);
+
+ /* Erase FAT Region */
+ int erase_block_cnt = (fat_size * 2);
+ int temp = 0;
+ printf("Erase FAT region");
+ for (i = 0;i < erase_block_cnt + 10; i+=16) {
+ if (dev_desc->block_write(dev_desc->dev, info->start +
+ RESERVED_CNT + i, 16, (ulong *)dummy) != 16) {
+ printf ("Can't erase FAT region~~!!!\n");
+ }
+ if((i % 160) == 0)
+ printf(".");
+
+ }
+ printf("\n");
+
+ mk4(img, 0x0ffffff8);
+ mk4(img+4, 0x0fffffff);
+ mk4(img+8, 0x0fffffff); /* Root Directory */
+ /* Write FAT Region */
+ if (dev_desc->block_write(dev_desc->dev, info->start + RESERVED_CNT,
+ 1, (ulong *)img) != 1) {
+ printf ("Can't write FAT~~~!!!\n");
+ return -1;
+ }
+
+ return 1;
+}
+
+/*
+ * Make a volume label.
+ */
+
+static void
+mklabel(u_int8_t *dest, const char *src)
+{
+ int c, i;
+
+ for (i = 0; i < 11; i++) {
+ c = *src ? __toupper(*src++) : ' ';
+ *dest++ = !i && c == '\xe5' ? 5 : c;
+ }
+}
+
+
+/*
+ * * Format device
+ * */
+int
+fat_format_device(block_dev_desc_t *dev_desc, int part_no)
+{
+ unsigned char buffer[SECTOR_SIZE];
+ unsigned long part_offset;
+ int cur_part;
+ disk_partition_t info;
+
+ if (!dev_desc->block_read)
+ return -1;
+ cur_dev = dev_desc;
+ /* check if we have a MBR (on floppies we have only a PBR) */
+ if (dev_desc->block_read (dev_desc->dev, 0,
+ 1, (ulong *) buffer) != 1) {
+ printf ("** Can't read from device %d **\n", dev_desc->dev);
+ return -1;
+ }
+ if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
+ buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
+ printf("** MBR is broken **\n");
+ /* no signature found */
+ return -1;
+ }
+
+#if (defined(CONFIG_CMD_IDE) || \
+ defined(CONFIG_CMD_SCSI) || \
+ defined(CONFIG_CMD_USB) || \
+ defined(CONFIG_MMC) || \
+ defined(CONFIG_SYSTEMACE) )
+ /* First we assume, there is a MBR */
+ if (!get_partition_info (dev_desc, part_no, &info)) {
+ part_offset = info.start;
+ cur_part = part_no;
+ } else if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3)) {
+ /* ok, we assume we are on a PBR only */
+ cur_part = 1;
+ part_offset = 0;
+ } else {
+ printf ("** Partition %d not valid on device %d **\n",
+ part_no, dev_desc->dev);
+ return -1;
+ }
+#endif
+
+ printf("Partition%d: Start Address(0x%x), Size(0x%x)\n",
+ part_no, info.start, info.size);
+
+ int fat_size;
+ fat_size = write_pbr(dev_desc, &info);
+ if(fat_size < 0)
+ return -1;
+ if(write_reserved(dev_desc, &info) < 0)
+ return -1;
+ if(write_fat(dev_desc, &info, fat_size) < 0)
+ return -1;
+ printf("Partition%d format complete.\n", part_no);
+
+ return 0;
+}
+