blob: 3057323b76a31a968f95e679e8f2a0c2bde992c9 [file] [log] [blame]
#include <common.h>
#include <command.h>
#include <ext2fs.h>
#include "hvideo.h"
#include "sys_dep.h"
#include "sam_ide.h"
#include "malloc.h"
extern int do_bootm (cmd_tbl_t *, int, int, char *[]);
#ifdef CONFIG_CMD_SCSI
extern block_dev_desc_t * scsi_get_dev(int);
#else
block_dev_desc_t * scsi_get_dev(int a)
{
return (block_dev_desc_t *)0;
}
#endif
#include <usb.h> // I need usb_stor_get_dev()
#define MAX_USB_UNITNUM USB_MAX_STOR_DEV
//System-dependent support for the A1 first and second level bootloaders.
#define MAX_IDE_UNITNUM CFG_IDE_MAXDEVICE
//#define MAX_SCSI_UNITNUM CFG_SCSI_MAX_DEVICE
#include <fdc.h>
static struct MinList dev_list; //Made out of uboot_scan_handles
static struct MinList old_dev_list; //Made out of old_uboot_scan_handles
static SCAN_HANDLE curr_disk;
struct dev_access_entry * find_dae(const char * s)
{
static struct dev_access_entry devices_access_table[]={
{NULL, NULL, DEV_TYPE_NETBOOT, 1, BUSTYPE_NET},
{NULL, NULL, DEV_TYPE_CDROM, MAX_USB_UNITNUM, BUSTYPE_USB},
{NULL, NULL, DEV_TYPE_HARDDISK, MAX_USB_UNITNUM, BUSTYPE_USB},
{NULL, NULL, DEV_TYPE_HARDDISK, MAX_S_SII_UNITS, BUSTYPE_SIL_SERIAL},
{NULL, NULL, DEV_TYPE_CDROM, MAX_S_SII_UNITS, BUSTYPE_SIL_SERIAL},
{NULL, NULL, DEV_TYPE_HARDDISK, MAX_S_4_SII_UNITS, BUSTYPE_SIL_4_SERIAL},
{NULL, NULL, DEV_TYPE_CDROM, MAX_S_4_SII_UNITS, BUSTYPE_SIL_4_SERIAL},
{NULL, NULL, DEV_TYPE_HARDDISK, MAX_P_SII_UNITS, BUSTYPE_SIL_PARALLEL},
{NULL, NULL, DEV_TYPE_CDROM, MAX_P_SII_UNITS, BUSTYPE_SIL_PARALLEL},
#ifdef CONFIG_SAM460EX
{NULL, NULL, DEV_TYPE_HARDDISK, MAX_SATA2_460_UNITS,BUSTYPE_SATA2_460},
#endif
{NULL, NULL, DEV_TYPE_DUMMY_END, 0, 0}
//{NULL, NULL, DEV_TYPE_CDROM, MAX_SCSI_UNITNUM, BUSTYPE_SCSI},
//{NULL, NULL, DEV_TYPE_HARDDISK, MAX_SCSI_UNITNUM, BUSTYPE_SCSI},
};
devices_access_table[0].dae_identifier = "net";
devices_access_table[1].dae_identifier = "ucdrom";
devices_access_table[2].dae_identifier = "usb";
devices_access_table[3].dae_identifier = "ssii";
devices_access_table[4].dae_identifier = "ssiicdrom";
devices_access_table[5].dae_identifier = "s4sii";
devices_access_table[6].dae_identifier = "s4siicdrom";
devices_access_table[7].dae_identifier = "psii";
devices_access_table[8].dae_identifier = "psiicdrom";
#ifdef CONFIG_SAM460EX
devices_access_table[9].dae_identifier = "sata2-460";
devices_access_table[10].dae_identifier = NULL;
#else
devices_access_table[9].dae_identifier = NULL;
#endif
//devices_access_table[1].dae_identifier = "scdrom";
//devices_access_table[2].dae_identifier = "scsi";
struct dev_access_entry * current;
for(current = devices_access_table;
current->dae_request_type != DEV_TYPE_DUMMY_END;
current++)
{
if(!strcmp(s, current->dae_identifier))
{
/* The get_dev() hooks MUST be assigned at runtime, since uboot is relocated! */
switch(current->dae_bustype)
{
//case BUSTYPE_SCSI:
// current->dae_get_dev = scsi_get_dev;
// break;
case BUSTYPE_USB:
current->dae_get_dev = usb_stor_get_dev;
break;
case BUSTYPE_SIL_SERIAL:
current->dae_get_dev = s_sii_get_dev;
break;
case BUSTYPE_SIL_4_SERIAL:
current->dae_get_dev = s_4_sii_get_dev;
break;
case BUSTYPE_SIL_PARALLEL:
current->dae_get_dev = p_sii_get_dev;
break;
#ifdef CONFIG_SAM460EX
case BUSTYPE_SATA2_460:
current->dae_get_dev = sata2_460_get_dev;
break;
#endif
default:
break;
}
//printf("found hook is %08lx\n", current->dae_get_dev);
return current;
}
}
return NULL;
}
SCAN_HANDLE next_unit_scan(SCAN_HANDLE h, ULONG * const blocksize)
{
SCAN_HANDLE next = (SCAN_HANDLE)h->ush_link.mln_Succ;
h->ush_already_scanned = TRUE; //Mark the past handle as already scanned.
//printf("Entered next_unit_scan\n");
if(next->ush_link.mln_Succ) //more to go ?
{
*blocksize = next->ush_device.blksz;
/*
printf("NUS: returning device with data: interface type %d, devnumber %d, type %u\n",
curr_disk->ush_device.if_type, curr_disk->ush_device.dev, curr_disk->ush_device.type);
*/
return (curr_disk = next);
}
else
{
//printf("NUS: no more units in list\n");
return NULL;
}
}
SCAN_HANDLE start_unit_scan(const void * scan_list, ULONG * const blocksize)
{
const char ** opt_list;
struct dev_access_entry * dae_found;
//printf("entered start_unit_scan\n");
if (!scan_list || !blocksize) return NULL;
//floppy_like_an_hd.block_read = internal_floppy_block_read;
/* This routine builds a list of scan handles from the env-vars passed in scan_list. */
NewList(&dev_list);
for(opt_list = scan_list;*opt_list;opt_list++) //Iterates till empty string.
{
//printf("Now examining boot source '%s'\n", *opt_list);
dae_found = find_dae(*opt_list);
//printf("Done find_dae\n");
if(dae_found)
{
SCAN_HANDLE s_h;
block_dev_desc_t * newdev;
UBYTE curr_unit;
//printf("Found dae matching identifier %s, looping\n", dae_found->dae_identifier);
for(curr_unit = 0; curr_unit < dae_found->dae_max_unitnum; curr_unit++)
{
if(dae_found->dae_bustype == BUSTYPE_NET) //Special case!!
{
//printf("Found special boot type network.\n");
s_h = alloc_mem_for_anythingelse(sizeof (struct uboot_scan_handle));
memset(s_h, 0, sizeof(struct uboot_scan_handle));
s_h->ush_bustype = dae_found->dae_bustype;
s_h->ush_device.blksz = 1500; //Fake value.
s_h->ush_device.type = DEV_TYPE_NETBOOT;
AddTail(&dev_list, &s_h->ush_link);
continue;
}
if((newdev = dae_found->dae_get_dev(curr_unit)))
if((newdev->blksz) && (newdev->type == dae_found->dae_request_type))
//uboot sei sempre una merda.
{
s_h = alloc_mem_for_anythingelse(sizeof (struct uboot_scan_handle));
memset(s_h, 0, sizeof(struct uboot_scan_handle));
s_h->ush_device = *newdev; //Full structure copy.
s_h->ush_bustype = dae_found->dae_bustype;
/*
printf("SUN: found unit; data as follows: interface type %d, devnumber %d, type %u, device points to %08lx\n",
s_h->ush_device.if_type, s_h->ush_device.dev, s_h->ush_device.type, &s_h->ush_device);
*/
AddTail(&dev_list, &s_h->ush_link);
}
}
}
}
curr_disk = (SCAN_HANDLE)dev_list.mlh_Head;
if(curr_disk->ush_device.blksz)
{
*blocksize = curr_disk->ush_device.blksz;
//printf("Blocksize for first device is %lu, type %u\n", *blocksize, curr_disk->ush_bustype);
}
//printf("Exiting start_unit_scan\n");
return curr_disk;
}
BOOL open_specific_unit(const SCAN_HANDLE h)
{
curr_disk = h; //We simply set the current disk to be the one given in.
/*
printf("Opening specific unit; data as follows: interface type %d, devnumber %d, type %u\n",
curr_disk->ush_device.if_type, curr_disk->ush_device.dev, curr_disk->ush_device.type);
*/
return TRUE;
}
BOOL old_open_specific_unit(const OLD_SCAN_HANDLE h)
{
//printf("Old_open_specific unit; real handle to %08lx\n", h->ush_new_reference);
curr_disk = h->ush_device.backpointer; //We simply set the current disk to be the one given in.
/*
printf("Opening specific unit; data as follows: interface type %d, devnumber %d, type %u\n",
curr_disk->ush_device.if_type, curr_disk->ush_device.dev, curr_disk->ush_device.type);
*/
return TRUE;
}
void end_unit_scan(SCAN_HANDLE h)
{
//Nothing: no special resources are opened while scanning
}
void end_global_scan(void)
{
// Just like a1_end_unit_scan()
}
BOOL loadsector(const ULONG sectn, const ULONG sect_size, const ULONG numb_sects, void * const dest_buf)
{
block_dev_desc_t * dev = &curr_disk->ush_device;
//printf("Loadsector: sectornum. %lu, current device %08lx\n", sectn, dev);
if(sect_size) //Sector size check is only performed when passing a non-zero value
{
if(dev->blksz != sect_size)
{
//printf("Loadsector: Bad blocksize: current is %lu, supplied is %lu (base structure at %p)\n", dev->blksz, sect_size, &curr_disk);
return FALSE;
}
}
if(dev->block_read(dev->dev, sectn, numb_sects, dest_buf) != numb_sects)
{
printf("Loadsector: error when reading from block %lu\n", sectn);
return FALSE;
}
else return TRUE;
}
void * uboot_4aligned_malloc(const size_t size)
{
unsigned long temp;
//printf("Allocating %d bytes, jumping to %08lx\n", size, malloc);
temp = (unsigned long)malloc(size + 4);
temp = (temp + 3) & ~3;
// printf("uboot_4aligned_malloc : asked for memsize %d, returned pointer at %08lx\n", size, (ULONG)temp);
return (void *)temp;
}
void * alloc_mem_for_iobuffers(const unsigned long size)
{
return uboot_4aligned_malloc((const size_t)size);
}
void * alloc_mem_for_kickmodule(const unsigned long size)
{
return uboot_4aligned_malloc((const size_t) size);
}
void * alloc_mem_for_execNG(const unsigned long size)
{
return uboot_4aligned_malloc((const size_t) size);
}
void * alloc_mem_for_anythingelse(const unsigned long size)
{
return uboot_4aligned_malloc((const size_t) size);
}
void * alloc_mem_for_bootloader(const unsigned long size)
{
return uboot_4aligned_malloc((const size_t) size);
}
/*
void * alloc_mem_for_bootloader_ABS(const unsigned long size, void * addr)
{
return addr; //Yeah, bulldozing anything that comes in the way!
}
//No longer used, since the absolute bulldozing will be done by the ELF loader & relocator.
*/
/*
static int local_get_part_info(int part, disk_partition_t *info)
//This function will use the file-global curr_disk to get the partition info from uboot
{
return get_partition_info(curr_disk, part, info);
}
*/
void * get_board_info(void)
{
DECLARE_GLOBAL_DATA_PTR;
return (void *)gd->bd;
}
int my_NetLoop(char * fn, void * buff)
{
//printf("Entering %s\n", __PRETTY_FUNCTION__);
copy_filename(BootFile, fn, sizeof(BootFile));
load_addr = (ulong) buff;
//The cast is necessary because someone was so smart to declare an address
//as something else than a pointer.
return NetLoop(TFTP);
}
static void set_load_addr(void * const new_load_addr)
{
load_addr = (ulong)new_load_addr;
}
struct sbl_callback_context * build_callback_context(void * scanopts)
{
static struct sbl_callback_context context;
context.ssc_version = CALLBACK_VERSION;
context.ssc_printf_like = printf;
context.ssc_getc_like = getc;
context.ssc_scan_list = scanopts;
context.ssc_devices_list = &dev_list;
context.ssc_curr_device = curr_disk;
context.ssc_start_unit_scan = start_unit_scan;
context.ssc_next_unit_scan = next_unit_scan;
context.ssc_open_specific_unit = open_specific_unit;
context.ssc_end_unit_scan = end_unit_scan;
context.ssc_end_global_scan = end_global_scan;
context.ssc_loadsector = loadsector;
context.ssc_my_netloop = my_NetLoop;
context.ssc_getenv = getenv;
context.ssc_setenv = setenv;
context.ssc_alloc_mem_for_iobuffers = uboot_4aligned_malloc;
context.ssc_alloc_mem_for_kickmodule =uboot_4aligned_malloc;
context.ssc_alloc_mem_for_execNG = uboot_4aligned_malloc;
context.ssc_alloc_mem_for_anythingelse=uboot_4aligned_malloc;
context.ssc_alloc_mem_for_bootloader =uboot_4aligned_malloc;
context.ssc_free_mem = free;
context.ssc_get_board_info = get_board_info;
#ifdef CONFIG_BZIP2
context.ssc_BZ2_bzBuffToBuffDecompress = BZ2_bzBuffToBuffDecompress;
#endif
context.ssc_video_clear = video_clear;
context.ssc_video_draw_box = video_draw_box;
context.ssc_video_draw_text = video_draw_text;
context.ssc_video_repeat_char = video_repeat_char;
context.ssc_set_partial_scroll_limits = set_partial_scroll_limits;
context.ssc_get_partial_scroll_limits = get_partial_scroll_limits;
context.ssc_video_get_key = video_get_key;
//printf("Allocation functions pointing at %08lx\n", uboot_4aligned_malloc);
context.ssc_do_bootm = do_bootm;
context.ssc_memmove = memmove;
context.ssc_set_load_addr = set_load_addr;
context.ssc_tstc = tstc;
context.ssc_udelay = udelay;
context.ssc_sprintf = sprintf;
context.ssc_ext2fs_set_blk_dev_full=ext2fs_set_blk_dev_full;
context.ssc_ext2fs_open=ext2fs_open;
context.ssc_ext2fs_read=ext2fs_read;
context.ssc_ext2fs_mount=ext2fs_mount;
context.ssc_ext2fs_close=ext2fs_close;
return &context;
}
/*
void degrade_to_old_frigging_interface(struct sbl_callback_context * c)
{
SCAN_HANDLE actual;
NewList(&old_dev_list);
c->ssc_version = 3;
for(actual = (SCAN_HANDLE)c->ssc_devices_list->mlh_Head; actual->ush_link.mln_Succ; actual = (SCAN_HANDLE)actual->ush_link.mln_Succ)
{
OLD_SCAN_HANDLE old_h = alloc_mem_for_anythingelse(sizeof(struct uboot_old_scan_handle));
old_h->ush_bustype = actual->ush_bustype;
old_h->ush_already_scanned = actual->ush_already_scanned;
old_h->ush_device.if_type = actual->ush_device.if_type ;
old_h->ush_device.dev = actual->ush_device.dev;
old_h->ush_device.part_type = actual->ush_device.part_type;
old_h->ush_device.target = actual->ush_device.target;
old_h->ush_device.lun = actual->ush_device.lun;
old_h->ush_device.type = actual->ush_device.type;
old_h->ush_device.lba = (unsigned long)actual->ush_device.lba;
old_h->ush_device.blksz = actual->ush_device.blksz;
memcpy(&old_h->ush_device.vendor, &actual->ush_device,40);
memcpy(&old_h->ush_device.product, &actual->ush_device,20);
memcpy(&old_h->ush_device.revision, &actual->ush_device,4);
old_h->ush_device.removable = actual->ush_device.removable;
old_h->ush_device.block_read = actual->ush_device.block_read;
old_h->ush_device.backpointer = actual; //Backpointer used by old_open_specific_unit()
AddTail(&old_dev_list, &old_h->ush_link);
if(c->ssc_curr_device == actual)
c->ssc_curr_device = (SCAN_HANDLE)old_h;
}
c->ssc_devices_list = &old_dev_list;
c->ssc_open_specific_unit = old_open_specific_unit;
}
*/