Added the CILOIO library to abstract platform-specific I/O operations away.
parent
8abff9252f
commit
3982f603d6
@ -0,0 +1,48 @@
|
||||
/* (C) 2008 Philippe Vachon <philippe@cowpig.ca>
|
||||
* Licensed under the GNU General Public License v2
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <ciloio.h>
|
||||
|
||||
/* Platform-specific file I/O operations */
|
||||
#include <platio.h>
|
||||
|
||||
struct file cilo_open(const char *filename)
|
||||
{
|
||||
struct file fp;
|
||||
if (!platio_find_file(filename)) {
|
||||
fp.code = -1;
|
||||
return fp;
|
||||
}
|
||||
|
||||
platio_file_open(&fp, filename);
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
int32_t cilo_read(void *pbuf, uint32_t size, uint32_t nmemb, struct file *fp)
|
||||
{
|
||||
return platio_read(pbuf, size, nmemb, fp);
|
||||
}
|
||||
|
||||
int32_t cilo_seek(struct file *fp, uint32_t offset, uint8_t whence)
|
||||
{
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
if (offset > fp->file_len) fp->file_pos = fp->file_len;
|
||||
else fp->file_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
if (offset + fp->file_pos > fp->file_len) fp->file_pos = fp->file_len;
|
||||
else fp->file_pos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
/* unimplemented */
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
#ifndef _INCLUDE_CILOIO_H
|
||||
#define _INCLUDE_CILOIO_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
struct file {
|
||||
uint8_t dev; /* device ID number */
|
||||
uint32_t file_len; /* length of the file */
|
||||
uint32_t file_pos; /* position in the file */
|
||||
char filename[128];
|
||||
|
||||
int8_t code; /* error code */
|
||||
|
||||
void *private; /* private data for the platform specific flash handler */
|
||||
};
|
||||
|
||||
#define SEEK_SET 9
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
struct file cilo_open(const char *filename);
|
||||
int32_t cilo_read(void *pbuf, uint32_t size, uint32_t nmemb,
|
||||
struct file *fp);
|
||||
int32_t cilo_seek(struct file *fp, uint32_t offset, uint8_t whence);
|
||||
struct fs_ent *find_file(const char *filename, uint32_t base);
|
||||
|
||||
#endif /* _INCLUDE_CILOIO_H */
|
@ -1,8 +1,16 @@
|
||||
#ifndef _INCLUDE_MACH_C3600_PLATFORM_H
|
||||
#define _INCLUDE_MACH_C3600_PLATFORM_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define FLASH_BASE 0x30000000
|
||||
#define KERNEL_ENTRY_POINT 0x80008000
|
||||
#define MEMORY_BASE 0x80000000
|
||||
|
||||
void platform_init();
|
||||
uint32_t check_flash();
|
||||
void flash_directory();
|
||||
uint32_t locate_stage_two();
|
||||
void stage_two(uint32_t kern_off, uint32_t kern_entry, uint32_t kern_size);
|
||||
|
||||
#endif /* _INCLUDE_MACH_C3600_PLATFORM_H */
|
||||
|
@ -0,0 +1,24 @@
|
||||
#ifndef _INCLUDE_MACH_C3600_PLATIO
|
||||
#define _INCLUDE_MACH_C3600_PLATIO
|
||||
|
||||
#include <types.h>
|
||||
#include <ciloio.h>
|
||||
|
||||
/* a flash filesystem entry for the C3600 */
|
||||
struct fs_ent {
|
||||
uint32_t magic;
|
||||
uint32_t length;
|
||||
/* todo: figure out exactly what these two fields contain */
|
||||
uint32_t crc32;
|
||||
uint32_t date;
|
||||
char filename[48];
|
||||
};
|
||||
|
||||
void platio_file_open(struct file *fp, const char *filename);
|
||||
uint32_t platio_read(void *pbuf, uint32_t size, uint32_t nmemb,
|
||||
struct file *fp);
|
||||
uint8_t platio_find_file(const char *filename);
|
||||
|
||||
#define FS_FILE_MAGIC 0xbad00b1e
|
||||
|
||||
#endif /* _INCLUDE_MACH_C3600_PLATIO */
|
@ -1,109 +1,20 @@
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#define NULL 0
|
||||
#include <types.h>
|
||||
|
||||
inline int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0') {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
|
||||
if (*s1 != *s2) return -1;
|
||||
int strncmp(const char *s1, const char *s2, uint32_t n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
char *strcpy(char *dest, const char *src);
|
||||
|
||||
inline int strncmp(const char *s1, const char *s2, uint32_t n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (s1[i] != s2[i]) return -1;
|
||||
if (s1[i] == s2[i] && s1[i] == '\0') break;
|
||||
}
|
||||
char *strncpy(char *dest, const char *src, uint32_t n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
uint32_t strlen(char *s);
|
||||
|
||||
inline char *strcpy(char *dest, const char *src)
|
||||
{
|
||||
if (!dest || !src) {
|
||||
return NULL;
|
||||
}
|
||||
int memcpy(void *dst, const void *src, int n);
|
||||
|
||||
while (*src != '\0') {
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
inline char *strncpy(char *dest, const char *src, uint32_t n)
|
||||
{
|
||||
int i;
|
||||
int t = 0;
|
||||
if (!dest || !src || n == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!t) dest[i] = src[i];
|
||||
else dest[i] = '\0';
|
||||
|
||||
if (dest[i] == '\0') t = 1;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
inline uint32_t strlen(char *s)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (*s != '\0') {
|
||||
i++; s++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy n bytes from src to dst
|
||||
* @param dst destination buffer
|
||||
* @param src source buffer
|
||||
* @param n number of bytes to copy
|
||||
* @return number of bytes copied or value < 0 on error
|
||||
*/
|
||||
inline int memcpy(void *dst, const void *src, int n)
|
||||
{
|
||||
int i = 0;
|
||||
if (!dst || !src) return -1;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
((char *)dst)[i] = ((char *)src)[i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* strchr
|
||||
*/
|
||||
inline const char *strchr(const char *s, int c)
|
||||
{
|
||||
const char *ptr = s;
|
||||
|
||||
if (*ptr == (char)c) return ptr;
|
||||
|
||||
while (*ptr != '\0') {
|
||||
if (*(++ptr) == (char)c) {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
const char *strchr(const char *s, int c);
|
||||
|
||||
#endif /* _STRING_H */
|
||||
|
@ -0,0 +1,68 @@
|
||||
#include <types.h>
|
||||
#include <mach/c3600/platform.h>
|
||||
#include <mach/c3600/platio.h>
|
||||
#include <printf.h>
|
||||
|
||||
/**
|
||||
* perform hardware-specifc initialization for this platform
|
||||
*/
|
||||
void platform_init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a sanity check on flash
|
||||
* @returns 0 if no flash found, number of flash devices found otherwise
|
||||
*/
|
||||
uint32_t check_flash()
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)FLASH_BASE;
|
||||
|
||||
if (*ptr != FS_FILE_MAGIC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* TODO: add support for PCMCIA flash */
|
||||
}
|
||||
|
||||
/**
|
||||
* print a directory listing of the 'main' flash device in the system
|
||||
*/
|
||||
|
||||
void flash_directory()
|
||||
{
|
||||
struct fs_ent *f = (struct fs_ent *)FLASH_BASE;
|
||||
uint32_t offset = 0;
|
||||
|
||||
/* Iterate over the files; f->magic is 0 if an invalid file is found. */
|
||||
while (f->magic == FS_FILE_MAGIC) {
|
||||
printf("%s\n", f->filename);
|
||||
offset += sizeof(struct fs_ent) + f->length;
|
||||
f = (struct fs_ent *)(FLASH_BASE + offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the stage two loader for CiscoLoad for this particular platform
|
||||
* returns 0 if not found, 1 if found
|
||||
*/
|
||||
uint32_t locate_stage_two()
|
||||
{
|
||||
return platio_find_file("ciscoload.two");
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick into the stage two loader.
|
||||
*/
|
||||
void stage_two(uint32_t kern_off, uint32_t kern_entry, uint32_t kern_size)
|
||||
{
|
||||
uint32_t s2addr = ((uint32_t)find_file("ciscoload.two", FLASH_BASE)) +
|
||||
sizeof(struct fs_ent);
|
||||
|
||||
|
||||
((void (*)(uint32_t data_offset, uint32_t data_length, uint32_t entry_pt,
|
||||
uint32_t load_offset)) (s2addr))
|
||||
(kern_off, kern_size, kern_entry, kern_entry);
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/* Platform specific operations for I/O for the cisco 3600 Series
|
||||
* (C) 2008 Philippe Vachon <philippe@cowpig.ca>
|
||||
*
|
||||
* Licensed under the GNU General Public License v2.
|
||||
*/
|
||||
#include <types.h>
|
||||
#include <mach/c3600/platio.h>
|
||||
#include <ciloio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mach/c3600/platform.h>
|
||||
|
||||
/* find file in filesystem starting at base */
|
||||
struct fs_ent *find_file(const char *filename, uint32_t base)
|
||||
{
|
||||
/* Actual file offset */
|
||||
uint32_t offset = 0;
|
||||
|
||||
struct fs_ent *f = (struct fs_ent *)(base + offset);
|
||||
|
||||
/* iterate over files in flash */
|
||||
while (f->magic == FS_FILE_MAGIC) {
|
||||
if (!strncmp(f->filename, filename, 48)) {
|
||||
return f;
|
||||
}
|
||||
|
||||
offset += sizeof(struct fs_ent) + f->length;
|
||||
f = (struct fs_ent *)(base + offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a file within the platform-supported I/O devices
|
||||
* @param filename the file
|
||||
* @returns 0 on failure, device ID number on success
|
||||
*/
|
||||
uint8_t platio_find_file(const char *filename)
|
||||
{
|
||||
if (find_file(filename, FLASH_BASE)) {
|
||||
return 1;
|
||||
}
|
||||
/* todo: add support for PCMCIA devices */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file.
|
||||
* @param fp File structure to hold file information
|
||||
* @param filename name of the file
|
||||
*/
|
||||
void platio_file_open(struct file *fp, const char *filename)
|
||||
{
|
||||
struct fs_ent *ent = find_file(filename, FLASH_BASE);
|
||||
|
||||
if (ent == NULL) {
|
||||
fp->code = 0;
|
||||
fp->private = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
fp->dev = 1; /* TODO: add support for PCMCIA flash */
|
||||
|
||||
fp->private = (void *)ent;
|
||||
|
||||
fp->file_len = ent->length;
|
||||
fp->file_pos = 0;
|
||||
|
||||
/* copy the filename */
|
||||
strncpy(fp->filename, ent->filename, 48);
|
||||
|
||||
fp->code = 1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from a given file
|
||||
* @param pbuf Buffer to read data into
|
||||
* @param size size of entity to be read
|
||||
* @param nmemb number of members to read
|
||||
* @param fp file information structure to read from.
|
||||
* @returns number of bytes read (should = size * nmemb for C3600)
|
||||
*/
|
||||
uint32_t platio_read(void *pbuf, uint32_t size, uint32_t nmemb, struct file *fp)
|
||||
{
|
||||
/* calculate the effective offset of the data we want to read: */
|
||||
char *from = (char *)((uint32_t)(fp->private) + sizeof(struct fs_ent) +
|
||||
fp->file_pos);
|
||||
|
||||
memcpy(pbuf, from, size * nmemb);
|
||||
|
||||
fp->file_pos += size * nmemb;
|
||||
|
||||
return nmemb * size;
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
#include <string.h>
|
||||
#include <types.h>
|
||||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0') {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
if (*s1 != *s2) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, uint32_t n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (s1[i] != s2[i]) return -1;
|
||||
if (s1[i] == s2[i] && s1[i] == '\0') break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *strcpy(char *dest, const char *src)
|
||||
{
|
||||
if (!dest || !src) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*src != '\0') {
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *strncpy(char *dest, const char *src, uint32_t n)
|
||||
{
|
||||
int i;
|
||||
int t = 0;
|
||||
if (!dest || !src || n == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!t) dest[i] = src[i];
|
||||
else dest[i] = '\0';
|
||||
|
||||
if (dest[i] == '\0') t = 1;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
uint32_t strlen(char *s)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (*s != '\0') {
|
||||
i++; s++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy n bytes from src to dst
|
||||
* @param dst destination buffer
|
||||
* @param src source buffer
|
||||
* @param n number of bytes to copy
|
||||
* @return number of bytes copied or value < 0 on error
|
||||
*/
|
||||
int memcpy(void *dst, const void *src, int n)
|
||||
{
|
||||
int i = 0;
|
||||
if (!dst || !src) return -1;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
((char *)dst)[i] = ((char *)src)[i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* strchr
|
||||
*/
|
||||
const char *strchr(const char *s, int c)
|
||||
{
|
||||
const char *ptr = s;
|
||||
|
||||
if (*ptr == (char)c) return ptr;
|
||||
|
||||
while (*ptr != '\0') {
|
||||
if (*(++ptr) == (char)c) {
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue