ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/uboot/fs/tffs/initfs.c b/marvell/uboot/fs/tffs/initfs.c
new file mode 100755
index 0000000..3d178df
--- /dev/null
+++ b/marvell/uboot/fs/tffs/initfs.c
@@ -0,0 +1,260 @@
+/*
+ * initfs.c
+ *
+ * TFFS_mount TFFS_mkfs implementation.
+ * implementation file.
+ *
+ * Copyright (C) knightray@gmail.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include "initfs.h"
+#include "debug.h"
+#include "tffs.h"
+#include "hai.h"
+#include "fat.h"
+#include "dir.h"
+
+#ifndef DBG_INITFS
+#undef DBG
+#define DBG nulldbg
+#endif
+
+int32
+TFFS_mount(
+    IN  byte * dev,
+    OUT tffs_handle_t * phtffs)
+{
+	int32 ret;
+	tffs_t * tffs;
+	boot_sector_t * pbs = NULL;
+	tdev_handle_t hdev;
+	tdir_t * proot_dir = NULL;
+	tdir_t * pcur_dir = NULL;
+	uint32 rootdir_clus;
+	tfat_t * pfat = NULL;
+	tcache_t * pcache = NULL;
+	
+	if (!dev || !phtffs)
+		return ERR_TFFS_INVALID_PARAM;
+
+	ret = TFFS_OK;
+	tffs = (tffs_t *)Malloc(sizeof(tffs_t));
+	Memset(tffs, 0, sizeof(tffs_t));
+	pbs = (boot_sector_t *)Malloc(sizeof(boot_sector_t));
+	Memset(pbs, 0, sizeof(boot_sector_t));
+
+	/* Marvell fixed: sizeof(boot_sector_t) is actualy 514 but only
+		due to sub-struct size alignment to 32-bit.
+		This only affects bs_sig offset, and it is unused 
+	ASSERT(sizeof(boot_sector_t) == 512);
+	*/
+	
+	hdev = HAI_initdevice(dev, 512);
+	if (hdev == NULL) {
+		ret = ERR_TFFS_DEVICE_FAIL;
+		goto _release;
+	}
+	tffs->hdev = hdev;
+
+	if (HAI_readsector(hdev, 0, (ubyte *)pbs) != HAI_OK) {
+		ret = ERR_TFFS_DEVICE_FAIL;
+		goto _release;
+	}
+
+	if (!_validate_bs(pbs)) {
+		ret = ERR_TFFS_BAD_BOOTSECTOR;
+		goto _release;
+	}
+
+	tffs->pbs = pbs;
+	
+	_parse_boot_sector(pbs, tffs);
+	DBG("tffs->fat_type:%d\n", tffs->fat_type);
+	DBG("tffs->sec_fat:%d\n", tffs->sec_fat);
+	DBG("tffs->sec_root_dir:%d\n", tffs->sec_root_dir);
+	DBG("tffs->sec_first_data:%d\n", tffs->sec_first_data);
+
+	/* Marvell fixed */
+#ifdef TFFS_FAT_CACHE
+	if ((pcache = cache_init(hdev, TFFS_FAT_CACHE, tffs->pbs->byts_per_sec)) == NULL) {
+		WARN("TFFS: cache is disable.\n");
+		pcache = cache_init(hdev, 0, tffs->pbs->byts_per_sec);
+	}
+	tffs->pfatcache = pcache;
+#endif
+	if ((pfat = fat_init(tffs)) == NULL) {
+		ret = ERR_TFFS_BAD_FAT;
+		goto _release;
+	}
+	tffs->pfat = pfat;
+
+	/* Marvell fixed: TFFS_FILE_CACHE instead of 32 hard-coded */
+	if ((pcache = cache_init(hdev, TFFS_FILE_CACHE, tffs->pbs->byts_per_sec)) == NULL) {
+		WARN("TFFS: cache is disable.\n");
+		pcache = cache_init(hdev, 0, tffs->pbs->byts_per_sec);
+	}
+	tffs->pcache = pcache;
+
+	rootdir_clus = tffs->fat_type == FT_FAT32 ? tffs->pbs->bh32.root_clus : ROOT_DIR_CLUS_FAT16;
+
+	if (dir_init_by_clus(tffs, rootdir_clus, &proot_dir) != DIR_OK ||
+		dir_init_by_clus(tffs, rootdir_clus, &pcur_dir) != DIR_OK) {
+		ret = ERR_TFFS_DEVICE_FAIL;
+		goto _release;
+	}
+
+	tffs->root_dir = proot_dir;
+	tffs->cur_dir = pcur_dir;
+
+	*phtffs = (tffs_handle_t)tffs;
+	INFO("tiny fat file system mount OK.\n");
+
+	return ret;
+
+_release:
+	if (pfat)
+		fat_destroy(pfat);
+	if (proot_dir)
+		dir_destroy(proot_dir);
+	if (pcur_dir)
+		dir_destroy(pcur_dir);
+	if (HAI_closedevice(tffs->hdev) != HAI_OK)
+		ret = ERR_TFFS_DEVICE_FAIL;
+	Free(pbs);
+	Free(tffs);
+
+	return ret;
+}
+
+int32
+TFFS_fs_flush(
+	IN	tffs_handle_t  htffs)
+{
+	tffs_t * ptffs;
+	int32 ret;
+
+	if (!htffs)
+		return ERR_TFFS_INVALID_PARAM;
+
+	ptffs = (tffs_t *)htffs;
+	ret = TFFS_OK;
+
+	if (ptffs->pfat)
+		fat_flush(ptffs->pfat);
+	if (ptffs->pcache)
+		ret = cache_flush(ptffs->pcache);
+#ifdef TFFS_FAT_CACHE
+	if (ptffs->pfatcache)
+		ret = cache_flush(ptffs->pfatcache);
+#endif
+	return ret;
+}
+
+int32
+TFFS_umount(
+	IN	tffs_handle_t  htffs)
+{
+	tffs_t * ptffs;
+	int32 ret;
+
+	if (!htffs)
+		return ERR_TFFS_INVALID_PARAM;
+	
+	ptffs = (tffs_t *)htffs;
+	ret = TFFS_OK;
+
+	if (ptffs->pbs)
+		Free(ptffs->pbs);
+
+	if (ptffs->pfat)
+		fat_destroy(ptffs->pfat);
+
+	if (ptffs->root_dir)
+		dir_destroy(ptffs->root_dir);
+	
+	if (ptffs->cur_dir)
+		dir_destroy(ptffs->cur_dir);
+	
+	if (ptffs->pcache)
+		ret = cache_destroy(ptffs->pcache);
+	/* Marvell fixed */
+#ifdef TFFS_FAT_CACHE
+	if (ptffs->pfatcache)
+		ret = cache_destroy(ptffs->pfatcache);
+#endif
+	if (ret > 0 && (HAI_closedevice(ptffs->hdev) != HAI_OK))
+		ret = ERR_TFFS_DEVICE_FAIL;
+
+	Free(ptffs);
+
+	return ret;
+}
+
+int32
+_validate_bs(
+	IN	boot_sector_t * pbs)
+{
+	INFO("=================Boot sector====================\n");
+	INFO("oem_name: %s\n", pbs->oem_name);
+	INFO("byts_per_sec: %d\n", pbs->byts_per_sec);
+	INFO("resvd_sec_cnt: %d\n", pbs->resvd_sec_cnt);
+	INFO("sec_per_clus: %d\n", pbs->sec_per_clus);
+	INFO("num_fats: %d\n", pbs->num_fats);
+	INFO("================================================\n");
+	/* Marvell fixed: check basic parameters are sane */
+	if ((pbs->byts_per_sec == 0) || (pbs->sec_per_clus == 0) ||
+		(pbs->num_fats < 1) || (pbs->num_fats > 2))
+		return FALSE;
+	return TRUE;
+}
+
+void
+_parse_boot_sector(
+	IN	boot_sector_t * pbs,
+	OUT	tffs_t * tffs)
+{
+	uint32 totsec;
+	uint32 count_of_clusters;
+	uint32 datasec;
+	
+	tffs->root_dir_sectors = ((pbs->root_ent_cnt * 32) + (pbs->byts_per_sec - 1)) /  pbs->byts_per_sec;
+
+	if (pbs->fatsz16 != 0) {
+		tffs->fatsz = pbs->fatsz16;
+	}
+	else {
+		tffs->fatsz = pbs->bh32.fatsz32;
+	}
+
+	if (pbs->tot_sec16 != 0) {
+		totsec = pbs->tot_sec16;
+	}
+	else {
+		totsec = pbs->tot_sec32;
+	}
+
+	datasec = totsec - (pbs->resvd_sec_cnt + (pbs->num_fats * tffs->fatsz) + tffs->root_dir_sectors);
+	count_of_clusters = datasec / pbs->sec_per_clus;
+	tffs->total_clusters = count_of_clusters;
+	
+	DBG("count_of_clusters = %d\n", count_of_clusters);
+
+	//FIXME. I should find another to determine the fat type.
+	if (count_of_clusters < 4085) {
+		tffs->fat_type = FT_FAT12;
+	}
+	else if (count_of_clusters < 65525 && pbs->fatsz16 != 0){
+		tffs->fat_type = FT_FAT16;
+	}
+	else {
+		tffs->fat_type = FT_FAT32;
+	}
+
+	tffs->sec_fat = pbs->resvd_sec_cnt;
+	tffs->sec_root_dir = tffs->sec_fat + pbs->num_fats * tffs->fatsz;
+	tffs->sec_first_data = tffs->sec_root_dir + tffs->root_dir_sectors;
+	/* Marvell fixed */
+	tffs->num_fats = pbs->num_fats;
+}
+