ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/uboot/fs/fdos/vfat.c b/marvell/uboot/fs/fdos/vfat.c
new file mode 100644
index 0000000..2b87d0f
--- /dev/null
+++ b/marvell/uboot/fs/fdos/vfat.c
@@ -0,0 +1,336 @@
+/*
+ * (C) Copyright 2002
+ * Stäubli Faverges - <www.staubli.com>
+ * Pierre AUBERT  p.aubert@staubli.com
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <config.h>
+#include <linux/ctype.h>
+
+#include "dos.h"
+#include "fdos.h"
+
+static int dir_read (Fs_t *fs,
+		     Slot_t *dir,
+		     Directory_t *dirent,
+		     int num,
+		     struct vfat_state *v);
+
+static int unicode_read (char *in, char *out, int num);
+static int match (const char *s, const char *p);
+static unsigned char sum_shortname (char *name);
+static int check_vfat (struct vfat_state *v, Directory_t *dir);
+static char *conv_name (char *name, char *ext, char Case, char *ans);
+
+
+/*-----------------------------------------------------------------------------
+ * clear_vfat --
+ *-----------------------------------------------------------------------------
+ */
+static void clear_vfat (struct vfat_state *v)
+{
+    v -> subentries = 0;
+    v -> status = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * vfat_lookup --
+ *-----------------------------------------------------------------------------
+ */
+int vfat_lookup (Slot_t *dir,
+		 Fs_t *fs,
+		 Directory_t *dirent,
+		 int *entry,
+		 int *vfat_start,
+		 char *filename,
+		 int flags,
+		 char *outname,
+		 Slot_t *file)
+{
+    int found;
+    struct vfat_state vfat;
+    char newfile [VSE_NAMELEN];
+    int vfat_present = 0;
+
+    if (*entry == -1) {
+	return -1;
+    }
+
+    found = 0;
+    clear_vfat (&vfat);
+    while (1) {
+	if (dir_read (fs, dir, dirent, *entry, &vfat) < 0) {
+	    if (vfat_start) {
+		*vfat_start = *entry;
+	    }
+	    break;
+	}
+	(*entry)++;
+
+	/* Empty slot                                                        */
+	if (dirent -> name[0] == '\0'){
+	    if (vfat_start == 0) {
+		break;
+	    }
+	    continue;
+	}
+
+	if (dirent -> attr == ATTR_VSE) {
+	    /* VSE entry, continue                                           */
+	    continue;
+	}
+	if ( (dirent -> name [0] == DELMARK) ||
+	     ((dirent -> attr & ATTR_DIRECTORY) != 0 &&
+	      (flags & ACCEPT_DIR) == 0) ||
+	     ((dirent -> attr & ATTR_VOLUME) != 0 &&
+	      (flags & ACCEPT_LABEL) == 0) ||
+	     (((dirent -> attr & (ATTR_DIRECTORY | ATTR_VOLUME)) == 0) &&
+	      (flags & ACCEPT_PLAIN) == 0)) {
+	    clear_vfat (&vfat);
+	    continue;
+	}
+
+	vfat_present = check_vfat (&vfat, dirent);
+	if (vfat_start) {
+	    *vfat_start = *entry - 1;
+	    if (vfat_present) {
+		*vfat_start -= vfat.subentries;
+	    }
+	}
+
+	if (dirent -> attr & ATTR_VOLUME) {
+	    strncpy (newfile, dirent -> name, 8);
+	    newfile [8] = '\0';
+	    strncat (newfile, dirent -> ext, 3);
+	    newfile [11] = '\0';
+	}
+	else {
+	    conv_name (dirent -> name, dirent -> ext, dirent -> Case, newfile);
+	}
+
+	if (flags & MATCH_ANY) {
+	    found = 1;
+	    break;
+	}
+
+	if ((vfat_present && match (vfat.name, filename)) ||
+	    (match (newfile, filename))) {
+	    found = 1;
+	    break;
+	}
+	clear_vfat (&vfat);
+    }
+
+    if (found) {
+	if ((flags & DO_OPEN) && file) {
+	    if (open_file (file, dirent) < 0) {
+		return (-1);
+	    }
+	}
+	if (outname) {
+	    if (vfat_present) {
+		strcpy (outname, vfat.name);
+	    }
+	    else {
+		strcpy (outname, newfile);
+	    }
+	}
+	return (0);                    /* File found                         */
+    } else {
+	*entry = -1;
+	return -1;                      /* File not found                    */
+    }
+}
+
+/*-----------------------------------------------------------------------------
+ * dir_read -- Read one directory entry
+ *-----------------------------------------------------------------------------
+ */
+static int dir_read (Fs_t *fs,
+	      Slot_t *dir,
+	      Directory_t *dirent,
+	      int num,
+	      struct vfat_state *v)
+{
+
+    /* read the directory entry                                              */
+    if (read_file (fs,
+		   dir,
+		   (char *)dirent,
+		   num * MDIR_SIZE,
+		   MDIR_SIZE) != MDIR_SIZE) {
+	return (-1);
+    }
+
+    if (v && (dirent -> attr == ATTR_VSE)) {
+	struct vfat_subentry *vse;
+	unsigned char id, last_flag;
+	char *c;
+
+	vse = (struct vfat_subentry *) dirent;
+	id = vse -> id & VSE_MASK;
+	last_flag = (vse -> id & VSE_LAST);
+	if (id > MAX_VFAT_SUBENTRIES) {
+	    /* Invalid VSE entry                                             */
+	    return (-1);
+	}
+
+
+	/* Decode VSE                                                        */
+	if(v -> sum != vse -> sum) {
+	    clear_vfat (v);
+	    v -> sum = vse -> sum;
+	}
+
+
+	v -> status |= 1 << (id - 1);
+	if (last_flag) {
+	    v -> subentries = id;
+	}
+
+	c = &(v -> name [VSE_NAMELEN * (id - 1)]);
+	c += unicode_read (vse->text1, c, VSE1SIZE);
+	c += unicode_read (vse->text2, c, VSE2SIZE);
+	c += unicode_read (vse->text3, c, VSE3SIZE);
+
+	if (last_flag) {
+	    *c = '\0';	        /* Null terminate long name                  */
+	}
+
+    }
+    return (0);
+}
+
+/*-----------------------------------------------------------------------------
+ * unicode_read --
+ *-----------------------------------------------------------------------------
+ */
+static int unicode_read (char *in, char *out, int num)
+{
+    int j;
+
+    for (j = 0; j < num; ++j) {
+	if (in [1])
+	    *out = '_';
+	else
+	    *out = in [0];
+	out ++;
+	in += 2;
+    }
+    return num;
+}
+
+/*-----------------------------------------------------------------------------
+ * match --
+ *-----------------------------------------------------------------------------
+ */
+static int match (const char *s, const char *p)
+{
+
+    for (; *p != '\0'; ) {
+	if (toupper (*s) != toupper (*p)) {
+	    return (0);
+	}
+	p++;
+	s++;
+    }
+
+    if (*s != '\0') {
+	return (0);
+    }
+    else {
+	return (1);
+    }
+}
+/*-----------------------------------------------------------------------------
+ * sum_shortname --
+ *-----------------------------------------------------------------------------
+ */
+static unsigned char sum_shortname (char *name)
+{
+    unsigned char sum;
+    int j;
+
+    for (j = sum = 0; j < 11; ++j) {
+	sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) +
+	    (name [j] ? name [j] : ' ');
+    }
+    return (sum);
+}
+/*-----------------------------------------------------------------------------
+ * check_vfat --
+ * Return 1 if long name is valid, 0 else
+ *-----------------------------------------------------------------------------
+ */
+static int check_vfat (struct vfat_state *v, Directory_t *dir)
+{
+    char name[12];
+
+    if (v -> subentries == 0) {
+	return 0;
+    }
+
+    strncpy (name, dir -> name, 8);
+    strncpy (name + 8, dir -> ext, 3);
+    name [11] = '\0';
+
+    if (v -> sum != sum_shortname (name)) {
+	return 0;
+    }
+
+    if( (v -> status & ((1 << v -> subentries) - 1)) !=
+	(1 << v -> subentries) - 1) {
+	return 0;
+    }
+    v->name [VSE_NAMELEN * v -> subentries] = 0;
+
+    return 1;
+}
+/*-----------------------------------------------------------------------------
+ * conv_name --
+ *-----------------------------------------------------------------------------
+ */
+static char *conv_name (char *name, char *ext, char Case, char *ans)
+{
+    char tname [9], text [4];
+    int i;
+
+    i = 0;
+    while (i < 8 && name [i] != ' ' && name [i] != '\0') {
+	tname [i] = name [i];
+	i++;
+    }
+    tname [i] = '\0';
+
+    if (Case & BASECASE) {
+	for (i = 0; i < 8 && tname [i]; i++) {
+	    tname [i] = tolower (tname [i]);
+	}
+    }
+
+    i = 0;
+    while (i < 3 && ext [i] != ' ' && ext [i] != '\0') {
+	text [i] = ext [i];
+	i++;
+    }
+    text [i] = '\0';
+
+    if (Case & EXTCASE){
+	for (i = 0; i < 3 && text [i]; i++) {
+	    text [i] = tolower (text [i]);
+	}
+    }
+
+    if (*text) {
+	strcpy (ans, tname);
+	strcat (ans, ".");
+	strcat (ans, text);
+    }
+    else {
+	strcpy(ans, tname);
+    }
+    return (ans);
+}