ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/uboot/fs/tffs/hai_dev.c b/marvell/uboot/fs/tffs/hai_dev.c
new file mode 100644
index 0000000..fe56f6e
--- /dev/null
+++ b/marvell/uboot/fs/tffs/hai_dev.c
@@ -0,0 +1,144 @@
+/*
+ * hai_dev.c
+ *
+ * Hardware Abstraction Interface for TFFS on uboot block device.
+ * Interface definition per TFFS requirement, see hai.h by
+ * knightray@gmail.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <part.h>
+#include "pubstruct.h"
+#include "hai_dev.h"
+
+/* This function is adopted from uboot/fs/fat/fat.c:fat_register_device() */
+#define SECTOR_SIZE 512
+#define DOS_PART_TBL_OFFSET     0x1be
+#define DOS_PART_MAGIC_OFFSET   0x1fe
+#define DOS_FS_TYPE_OFFSET      0x36 /* Marvell fixed: this is wrong */
+#define DOS_FS_SS_OFFSET	0xb /* PBR bytes_per_sector offset */
+#define MBR_BOOTABLE_OFFSET	0x1be
+
+static int find_partition(struct tdev_t *pdev)
+{
+        unsigned char buffer[SECTOR_SIZE];
+        disk_partition_t info;
+	block_dev_desc_t *dev_desc = pdev->dev_desc;
+	int part_no = pdev->part_offset;
+        if (!dev_desc->block_read)
+                return -1;
+
+        /* 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) {
+                /* no signature found */
+                return -1;
+        }
+        /* First we assume, there is a MBR */
+	/* Marvell fixed: PBR has the same magic as MBR:
+		add check for MBR "bootable" field (0 or 0x80 only);
+		add check for PBR bytes_per_sector field */
+	if (!get_partition_info(dev_desc, part_no, &info) && (buffer[MBR_BOOTABLE_OFFSET]&0x7f) == 0) {
+		pdev->part_offset = info.start;
+	} else if ((buffer[DOS_FS_SS_OFFSET] == 0) && (buffer[DOS_FS_SS_OFFSET + 1] == 2)) {
+		/* Sector size 0x200 at offset 0xb: assume PBR */
+		pdev->part_offset = 0;
+        } else {
+                printf ("** Partition %d not valid on device %d **\n",
+                                part_no, dev_desc->dev);
+                return -1;
+        }
+	printf("PART offset = %lx\n", pdev->part_offset);
+	return 0;
+}
+
+tdev_handle_t
+HAI_initdevice(
+	IN	byte * dev,
+	IN	int16 sector_size)
+{
+	struct tdev_t *pdev = (struct tdev_t *)dev;
+
+	pdev->sector_size = sector_size;
+	if (find_partition(pdev))
+		return (tdev_handle_t)NULL;
+	return (tdev_handle_t)dev;
+}
+
+int32
+HAI_readsector(
+	IN	tdev_handle_t hdev,
+	IN	int32 addr,
+	OUT	ubyte * ptr)
+{
+	struct tdev_t *pdev = (struct tdev_t *)hdev;
+
+	if (!ptr || !pdev || !pdev->dev_desc || !pdev->dev_desc->block_read)
+		return ERR_HAI_INVALID_PARAMETER;
+
+	if (pdev->dev_desc->block_read(pdev->dev_desc->dev, addr+pdev->part_offset, 
+		1, (unsigned long *)ptr)<0)
+		return ERR_HAI_READ;
+	return HAI_OK;
+}
+
+int32
+HAI_writesector(
+	IN	tdev_handle_t hdev,
+	IN	int32 addr,
+	IN	ubyte * ptr)
+{
+	struct tdev_t *pdev = (struct tdev_t *)hdev;
+
+	if (!ptr || !pdev || !pdev->dev_desc || !pdev->dev_desc->block_write)
+		return ERR_HAI_INVALID_PARAMETER;
+
+	if (pdev->dev_desc->block_write(pdev->dev_desc->dev, addr+pdev->part_offset, 
+		1, (unsigned long *)ptr)<0)
+		return ERR_HAI_WRITE;
+	return HAI_OK;
+}
+
+/* Marvell fixed */
+int32
+HAI_writesectors(
+	IN	tdev_handle_t hdev,
+	IN	int32 addr,
+	IN	ubyte * ptr,
+	IN	uint32 nsectors)
+{
+	struct tdev_t *pdev = (struct tdev_t *)hdev;
+
+	if (!ptr || !pdev || !pdev->dev_desc || !pdev->dev_desc->block_write)
+		return ERR_HAI_INVALID_PARAMETER;
+
+	if (pdev->dev_desc->block_write(pdev->dev_desc->dev, addr+pdev->part_offset, 
+		nsectors, (unsigned long *)ptr)<0)
+		return ERR_HAI_WRITE;
+	return HAI_OK;
+}
+int32
+HAI_closedevice(
+	IN	tdev_handle_t hdev)
+{
+	return HAI_OK;
+}
+
+int32
+HAI_getdevinfo(
+	IN	tdev_handle_t hdev,
+	OUT	tdev_info_t * devinfo)
+{
+	struct tdev_t *pdev = (struct tdev_t *)hdev;
+
+	if (!devinfo || !pdev)
+		return ERR_HAI_INVALID_PARAMETER;
+
+	devinfo->free_sectors = 1000;
+	return HAI_OK;
+}