mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	- remove trailing white space, trailing empty lines, C++ comments, etc.
  - split cmd_boot.c (separate cmd_bdinfo.c and cmd_load.c)
* Patches by Kenneth Johansson, 25 Jun 2003:
  - major rework of command structure
    (work done mostly by Michal Cendrowski and Joakim Kristiansen)
		
	
			
		
			
				
	
	
		
			349 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			349 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (C) Copyright 2002
 | 
						|
 * Stäubli Faverges - <www.staubli.com>
 | 
						|
 * Pierre AUBERT  p.aubert@staubli.com
 | 
						|
 *
 | 
						|
 * See file CREDITS for list of people who contributed to this
 | 
						|
 * project.
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU General Public License as
 | 
						|
 * published by the Free Software Foundation; either version 2 of
 | 
						|
 * the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 | 
						|
 * MA 02111-1307 USA
 | 
						|
 */
 | 
						|
 | 
						|
#include <common.h>
 | 
						|
#include <config.h>
 | 
						|
#include <malloc.h>
 | 
						|
 | 
						|
#if (CONFIG_COMMANDS & CFG_CMD_FDOS)
 | 
						|
 | 
						|
#include "dos.h"
 | 
						|
#include "fdos.h"
 | 
						|
 | 
						|
static int cache_sect;
 | 
						|
static unsigned char cache [SZ_STD_SECTOR];
 | 
						|
 | 
						|
 | 
						|
#define min(x,y) ((x)<(y)?(x):(y))
 | 
						|
 | 
						|
static int descend (Slot_t *parent,
 | 
						|
	     Fs_t *fs,
 | 
						|
		    char *path);
 | 
						|
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * init_subdir --
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
void init_subdir (void)
 | 
						|
{
 | 
						|
    cache_sect = -1;
 | 
						|
}
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * basename --
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
char *basename (char *name)
 | 
						|
{
 | 
						|
    register char *cptr;
 | 
						|
 | 
						|
    if (!name || !*name) {
 | 
						|
	return ("");
 | 
						|
    }
 | 
						|
 | 
						|
    for (cptr= name; *cptr++; );
 | 
						|
    while (--cptr >= name) {
 | 
						|
	if (*cptr == '/')    {
 | 
						|
	    return (cptr + 1);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return(name);
 | 
						|
}
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * root_map --
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
static int root_map (Fs_t *fs, Slot_t *file, int where, int *len)
 | 
						|
{
 | 
						|
    *len = min (*len, fs -> dir_len * SZ_STD_SECTOR - where);
 | 
						|
    if (*len < 0 ) {
 | 
						|
	*len = 0;
 | 
						|
	return (-1);
 | 
						|
    }
 | 
						|
    return fs -> dir_start * SZ_STD_SECTOR + where;
 | 
						|
}
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * normal_map --
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
static int normal_map (Fs_t *fs, Slot_t *file, int where, int *len)
 | 
						|
{
 | 
						|
    int offset;
 | 
						|
    int NrClu;
 | 
						|
    unsigned short RelCluNr;
 | 
						|
    unsigned short CurCluNr;
 | 
						|
    unsigned short NewCluNr;
 | 
						|
    unsigned short AbsCluNr;
 | 
						|
    int clus_size;
 | 
						|
 | 
						|
    clus_size = fs -> cluster_size * SZ_STD_SECTOR;
 | 
						|
    offset = where % clus_size;
 | 
						|
 | 
						|
    *len = min (*len, file -> FileSize - where);
 | 
						|
 | 
						|
    if (*len < 0 ) {
 | 
						|
	*len = 0;
 | 
						|
	return (0);
 | 
						|
    }
 | 
						|
 | 
						|
    if (file -> FirstAbsCluNr < 2){
 | 
						|
	*len = 0;
 | 
						|
	return (0);
 | 
						|
    }
 | 
						|
 | 
						|
    RelCluNr = where / clus_size;
 | 
						|
 | 
						|
    if (RelCluNr >= file -> PreviousRelCluNr){
 | 
						|
	CurCluNr = file -> PreviousRelCluNr;
 | 
						|
	AbsCluNr = file -> PreviousAbsCluNr;
 | 
						|
    } else {
 | 
						|
	CurCluNr = 0;
 | 
						|
	AbsCluNr = file -> FirstAbsCluNr;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    NrClu = (offset + *len - 1) / clus_size;
 | 
						|
    while (CurCluNr <= RelCluNr + NrClu) {
 | 
						|
	if (CurCluNr == RelCluNr){
 | 
						|
	    /* we have reached the beginning of our zone. Save
 | 
						|
	     * coordinates */
 | 
						|
	    file -> PreviousRelCluNr = RelCluNr;
 | 
						|
	    file -> PreviousAbsCluNr = AbsCluNr;
 | 
						|
	}
 | 
						|
	NewCluNr = fat_decode (fs, AbsCluNr);
 | 
						|
	if (NewCluNr == 1 || NewCluNr == 0) {
 | 
						|
	    PRINTF("Fat problem while decoding %d %x\n",
 | 
						|
		    AbsCluNr, NewCluNr);
 | 
						|
	    return (-1);
 | 
						|
	}
 | 
						|
	if (CurCluNr == RelCluNr + NrClu) {
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CurCluNr < RelCluNr && NewCluNr == FAT12_END) {
 | 
						|
	    *len = 0;
 | 
						|
	    return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	if (CurCluNr >= RelCluNr && NewCluNr != AbsCluNr + 1)
 | 
						|
	    break;
 | 
						|
	CurCluNr++;
 | 
						|
	AbsCluNr = NewCluNr;
 | 
						|
    }
 | 
						|
 | 
						|
    *len = min (*len, (1 + CurCluNr - RelCluNr) * clus_size - offset);
 | 
						|
 | 
						|
    return (((file -> PreviousAbsCluNr - 2) * fs -> cluster_size +
 | 
						|
	     fs -> dir_start + fs -> dir_len) *
 | 
						|
	    SZ_STD_SECTOR + offset);
 | 
						|
}
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * open_subdir -- open the subdir containing the file
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
int open_subdir (File_t *desc)
 | 
						|
{
 | 
						|
    char *pathname;
 | 
						|
    char *tmp, *s, *path;
 | 
						|
    char terminator;
 | 
						|
 | 
						|
    if ((pathname = (char *)malloc (MAX_PATH)) == NULL) {
 | 
						|
	return (-1);
 | 
						|
    }
 | 
						|
 | 
						|
    strcpy (pathname, desc -> name);
 | 
						|
 | 
						|
    /* Suppress file name                                                    */
 | 
						|
    tmp = basename (pathname);
 | 
						|
    *tmp = '\0';
 | 
						|
 | 
						|
    /* root directory  init                                                  */
 | 
						|
    desc -> subdir.FirstAbsCluNr = 0;
 | 
						|
    desc -> subdir.FileSize = -1;
 | 
						|
    desc -> subdir.map = root_map;
 | 
						|
    desc -> subdir.dir.attr = ATTR_DIRECTORY;
 | 
						|
 | 
						|
    tmp = pathname;
 | 
						|
    for (s = tmp; ; ++s) {
 | 
						|
	if (*s == '/' || *s == '\0') {
 | 
						|
	    path = tmp;
 | 
						|
	    terminator = *s;
 | 
						|
	    *s = '\0';
 | 
						|
	    if (s != tmp && strcmp (path,".")) {
 | 
						|
		if (descend (&desc -> subdir, desc -> fs, path) < 0) {
 | 
						|
		    free (pathname);
 | 
						|
		    return (-1);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    if (terminator == 0) {
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    tmp = s + 1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    free (pathname);
 | 
						|
    return (0);
 | 
						|
}
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * descend --
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
static int descend (Slot_t *parent,
 | 
						|
	     Fs_t *fs,
 | 
						|
	     char *path)
 | 
						|
{
 | 
						|
    int entry;
 | 
						|
    Slot_t SubDir;
 | 
						|
 | 
						|
    if(path[0] == '\0' || strcmp (path, ".") == 0) {
 | 
						|
	return (0);
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    entry = 0;
 | 
						|
    if (vfat_lookup (parent,
 | 
						|
		     fs,
 | 
						|
		     &(SubDir.dir),
 | 
						|
		     &entry,
 | 
						|
		     0,
 | 
						|
		     path,
 | 
						|
		     ACCEPT_DIR | SINGLE | DO_OPEN,
 | 
						|
		     0,
 | 
						|
		     &SubDir) == 0) {
 | 
						|
	*parent = SubDir;
 | 
						|
	return (0);
 | 
						|
    }
 | 
						|
 | 
						|
    if (strcmp(path, "..") == 0) {
 | 
						|
	parent -> FileSize = -1;
 | 
						|
	parent -> FirstAbsCluNr = 0;
 | 
						|
	parent -> map = root_map;
 | 
						|
	return (0);
 | 
						|
    }
 | 
						|
    return (-1);
 | 
						|
}
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * open_file --
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
int open_file (Slot_t *file, Directory_t *dir)
 | 
						|
{
 | 
						|
    int first;
 | 
						|
    unsigned long size;
 | 
						|
 | 
						|
    first = __le16_to_cpu (dir -> start);
 | 
						|
 | 
						|
    if(first == 0 &&
 | 
						|
       (dir -> attr & ATTR_DIRECTORY) != 0) {
 | 
						|
	file -> FirstAbsCluNr = 0;
 | 
						|
	file -> FileSize = -1;
 | 
						|
	file -> map = root_map;
 | 
						|
	return (0);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((dir -> attr & ATTR_DIRECTORY) != 0) {
 | 
						|
	size = (1UL << 31) - 1;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
	size = __le32_to_cpu (dir -> size);
 | 
						|
    }
 | 
						|
 | 
						|
    file -> map = normal_map;
 | 
						|
    file -> FirstAbsCluNr = first;
 | 
						|
    file -> PreviousRelCluNr = 0xffff;
 | 
						|
    file -> FileSize = size;
 | 
						|
    return (0);
 | 
						|
}
 | 
						|
/*-----------------------------------------------------------------------------
 | 
						|
 * read_file --
 | 
						|
 *-----------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
int read_file (Fs_t *fs,
 | 
						|
	       Slot_t *file,
 | 
						|
	       char *buf,
 | 
						|
	       int where,
 | 
						|
	       int len)
 | 
						|
{
 | 
						|
    int pos;
 | 
						|
    int read, nb, sect, offset;
 | 
						|
 | 
						|
    pos = file -> map (fs, file, where, &len);
 | 
						|
    if  (pos < 0) {
 | 
						|
	return -1;
 | 
						|
    }
 | 
						|
    if (len == 0) {
 | 
						|
	return (0);
 | 
						|
    }
 | 
						|
 | 
						|
    /* Compute sector number                                                 */
 | 
						|
    sect = pos / SZ_STD_SECTOR;
 | 
						|
    offset = pos % SZ_STD_SECTOR;
 | 
						|
    read = 0;
 | 
						|
 | 
						|
    if (offset) {
 | 
						|
	/* Read doesn't start at the sector beginning. We need to use our    */
 | 
						|
	/* cache                                                             */
 | 
						|
	if (sect != cache_sect) {
 | 
						|
	    if (dev_read (cache, sect, 1) < 0) {
 | 
						|
		return (-1);
 | 
						|
	    }
 | 
						|
	    cache_sect = sect;
 | 
						|
	}
 | 
						|
	nb = min (len, SZ_STD_SECTOR - offset);
 | 
						|
 | 
						|
	memcpy (buf, cache + offset, nb);
 | 
						|
	read += nb;
 | 
						|
	len -= nb;
 | 
						|
	sect += 1;
 | 
						|
    }
 | 
						|
 | 
						|
    if (len > SZ_STD_SECTOR) {
 | 
						|
	nb = (len - 1) / SZ_STD_SECTOR;
 | 
						|
	if (dev_read (buf + read, sect, nb) < 0) {
 | 
						|
	    return ((read) ? read : -1);
 | 
						|
	}
 | 
						|
	/* update sector position                                            */
 | 
						|
	sect += nb;
 | 
						|
 | 
						|
	/* Update byte position                                              */
 | 
						|
	nb *= SZ_STD_SECTOR;
 | 
						|
	read += nb;
 | 
						|
	len -= nb;
 | 
						|
    }
 | 
						|
 | 
						|
    if (len) {
 | 
						|
	if (sect != cache_sect) {
 | 
						|
	    if (dev_read (cache, sect, 1) < 0) {
 | 
						|
		return ((read) ? read : -1);
 | 
						|
		cache_sect = -1;
 | 
						|
	    }
 | 
						|
	    cache_sect = sect;
 | 
						|
	}
 | 
						|
 | 
						|
	memcpy (buf + read, cache, len);
 | 
						|
	read += len;
 | 
						|
    }
 | 
						|
    return (read);
 | 
						|
}
 | 
						|
#endif
 |