📄 l1rom.c
字号:
/*
* copyright (c) 1995,2000 TriMedia Technologies Inc.
*
* +-----------------------------------------------------------------+
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such |
* | a license and with the inclusion of the this copy right notice. |
* | this software or any other copies of this software may not be |
* | provided or otherwise made available to any other person. The |
* | ownership and title of this software is not transferred. |
* +-----------------------------------------------------------------+
*
* Module name:
* l1rom.c
*
* Description:
* Generates an EEPROM image (binary file)
*
* Input:
* f.mi - generated using -mi option of tmld
*
* Output:
* f.eeprom
* f.eeprom contains 47 header bytes as required by
* TM1 autoboot protocol, followed by the program bytes
* (bytes are swapped as required by boot)
*
* Assumption:
* 1. f.mi contains less than 2001 bytes, divisible by four
* (as required by the boot protocol).
* 2. short is 2 bytes.
*
* Update History:
* May 23, 1998 Modify to accept SDRAM_BASE and SDRAM_LIMIT
* macros values from the Makefile.
*/
#if defined(__sun) || defined(__hpux)
#include <unistd.h>
#endif
#if defined(__hpux)
#define _INCLUDE_POSIX_SOURCE
#endif
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#if !defined(SDRAM_BASE) || !defined(SDRAM_LIMIT)
#error "Macros SDRAM_BASE and SDRAM_LIMIT have to be defined for this file to build"
#endif
#define MAX_FILE_SIZE 2000
#define MAX_EPROM_SIZE (1024 * 2)
#define BUF_SIZE MAX_EPROM_SIZE
#define NUM_HEADER_BYTES 47
#define MSB_1ST(n) (unsigned char)(((n) >> 24) & 0xff)
#define MSB_2ND(n) (unsigned char)(((n) >> 16) & 0xff)
#define MSB_3RD(n) (unsigned char)(((n) >> 8) & 0xff)
#define MSB_4TH(n) (unsigned char)((n) & 0xff)
static void
basename(char *fname, char *bname)
{
char *ptr, *ptr2;
int i;
if ((ptr = strrchr(fname, '.')) == NULL) {
strcpy(bname, fname);
}
else {
for (ptr2 = fname, i = 0; ptr2 != ptr; ptr2++, i++) {
bname[i] = *ptr2;
}
bname[i] = '\0';
}
}
int
read_file(unsigned char *buffer, char *filename)
{
FILE *L1fp;
int L1fd, n, nbytes;
struct stat file_stat;
if ((L1fd = open(filename, O_RDONLY)) == -1) {
fprintf(stderr, "Unable to open file: %s\n", filename);
fprintf(stderr, "File doesn't exist or not readable\n");
exit(1);
}
if (fstat(L1fd, &file_stat)) {
fprintf(stderr, "Unable to fstat file: %s\n", filename);
exit(1);
}
nbytes = (unsigned long)file_stat.st_size;
close(L1fd);
if ((L1fp = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "Unable to open file: %s\n", filename);
fprintf(stderr, "File doesn't exist or not readable\n");
exit(1);
}
if (nbytes > MAX_FILE_SIZE) {
fprintf(stderr, "File has %5d bytes. must be less than %5d bytes\n",
nbytes, MAX_FILE_SIZE);
exit(1);
}
n = fread(buffer, 1, nbytes, L1fp);
if (n != nbytes) {
fprintf(stderr, "Unable to read %5d bytes, error no: %5d\n",
nbytes, errno);
exit(1);
}
fprintf(stderr, " Program Size: %5d bytes\n", nbytes);
return nbytes;
}
/*
* Header bytes are hard-coded. Read the TM-1 boot block paper
* to see what needs to go in here for AUTO boot.
*/
int
output_eeprom_header(int nbytes, unsigned char obuffer[])
{
int i = 0;
/* Output eeprom header bytes 0 thru 46, as per
* Chapter 12 of TM 1000 Data Book (April 1997 edition).
* These go into output array index 0 onwards
*/
/* 0xc8 for 50 and 40 MHz TRI_CLKIN. 0xcc for 33 MHz */
obuffer[i++] = 0xc8; /* 0 */
/* Sub-system Id */
obuffer[i++] = 0x00; /* 1 */
obuffer[i++] = 0x03; /* 2 */
/* Sub-system Vendor Id */
obuffer[i++] = 0x11; /* 3 */
obuffer[i++] = 0x31; /* 4 */
/* Bytes 5 6 7: MM Config register */
/*
* Byte 6 and 4 bits of byte 7 determine refresh rate.
* The refresh rate is 4c4 for 80MHz sdram clock, 384 for 60 Mhz.
* Use Table 11-10 Refresh Intervals of TM 1000 Preliminary Data
* for other SDRAM clock speeds and interpolate for speeds not
* mentioned in that table
*/
obuffer[i++] = 0x00; /* 5 */
obuffer[i++] = 0x4c; /* 6 */
obuffer[i++] = 0x44; /* 7 */
/* Byte 8: PLL Ratios */
obuffer[i++] = 0x00; /* 8 */
/*
* Byte 9: Most significant bit is 1 for stand-alone boot
* Least 3 bits of byte 9 and 8 bits of byte 10 determine
* L1 boot program code size. 11 bits == 2K bytes at most
*/
obuffer[i++] = (0x80 | ((nbytes >> 8) & 0x7));
obuffer[i++] = (nbytes & 0xfc);
/* MMIO base register address, MSB first */
obuffer[i++] = 0xef; /* 11 */
obuffer[i++] = 0xf0; /* 12 */
obuffer[i++] = 0x04; /* 13 */
obuffer[i++] = 0x00; /* 14 */
/* MMIO base register value, MSB first */
obuffer[i++] = 0xef; /* 15 */
obuffer[i++] = 0xe0; /* 16 */
obuffer[i++] = 0x00; /* 17 */
obuffer[i++] = 0x00; /* 18 */
/* DRAM base register address, MSB first */
obuffer[i++] = 0xef; /* 19 */
obuffer[i++] = 0xf0; /* 20 */
obuffer[i++] = 0x00; /* 21 */
obuffer[i++] = 0x00; /* 22 */
/* DRAM base register value, MSB first */
obuffer[i++] = MSB_1ST(SDRAM_BASE); /* 23 */
obuffer[i++] = MSB_2ND(SDRAM_BASE); /* 24 */
obuffer[i++] = MSB_3RD(SDRAM_BASE); /* 25 */
obuffer[i++] = MSB_4TH(SDRAM_BASE); /* 26 */
/* DRAM limit register address, MSB first */
obuffer[i++] = 0xef; /* 27 */
obuffer[i++] = 0xf0; /* 28 */
obuffer[i++] = 0x00; /* 29 */
obuffer[i++] = 0x04; /* 30 */
/* DRAM limit register value, MSB first */
obuffer[i++] = MSB_1ST(SDRAM_LIMIT); /* 31 */
obuffer[i++] = MSB_2ND(SDRAM_LIMIT); /* 32 */
obuffer[i++] = MSB_3RD(SDRAM_LIMIT); /* 33 */
obuffer[i++] = MSB_4TH(SDRAM_LIMIT); /* 34 */
/* DRAM cacheable limit reg address, MSB first */
obuffer[i++] = 0xef; /* 35 */
obuffer[i++] = 0xf0; /* 36 */
obuffer[i++] = 0x00; /* 37 */
obuffer[i++] = 0x08; /* 38 */
/* DRAM cacheable limit reg value, MSB first */
obuffer[i++] = MSB_1ST(SDRAM_LIMIT); /* 39 */ /* assumes to be the same as SDRAM_LIMIT */
obuffer[i++] = MSB_2ND(SDRAM_LIMIT); /* 40 */
obuffer[i++] = MSB_3RD(SDRAM_LIMIT); /* 41 */
obuffer[i++] = MSB_4TH(SDRAM_LIMIT); /* 42 */
/* DRAM base reg value, MSB first */
obuffer[i++] = MSB_1ST(SDRAM_BASE); /* 43 */
obuffer[i++] = MSB_2ND(SDRAM_BASE); /* 44 */
obuffer[i++] = MSB_3RD(SDRAM_BASE); /* 45 */
obuffer[i++] = MSB_4TH(SDRAM_BASE); /* 46 */
if (i != NUM_HEADER_BYTES) {
fprintf(stderr, "Error: header bytes count = %5d, shd be %5d\n",
i, NUM_HEADER_BYTES );
exit(1);
}
fprintf(stderr, "EEPROM Header Size: %5d bytes\n", NUM_HEADER_BYTES);
return i;
}
int
main(int argc, char **argv)
{
int i, j, file_size;
int header_bytes;
FILE *fp;
char *o_file_name, *cp;
unsigned char ibuffer[BUF_SIZE] = {0};
unsigned char obuffer[BUF_SIZE] = {0};
if (argc < 2) {
fprintf(stderr, "Usage: l1prom file.mi \n");
exit(1);
}
/* find output file name */
i = strlen(argv[1]);
/* .eeprom extension needs 7+1 chars */
o_file_name = (char *)malloc(i+8);
if (o_file_name == NULL) {
fprintf(stderr, "unable to malloc\n");
exit(1);
}
/* skip all directory names */
if ((cp = strrchr(argv[1], '/')) == NULL) {
cp = argv[1];
}
basename(cp, o_file_name);
i = strlen(o_file_name);
o_file_name[i++] = '.';
o_file_name[i++] = 'e';
o_file_name[i++] = 'e';
o_file_name[i++] = 'p';
o_file_name[i++] = 'r';
o_file_name[i++] = 'o';
o_file_name[i++] = 'm';
o_file_name[i++] = '\0';
if ((fp = fopen(o_file_name, "wb")) == NULL) {
fprintf(stderr, "Could not open (binary) file %s for write\n",
o_file_name);
exit(1);
}
file_size = read_file(ibuffer, argv[1]);
header_bytes = output_eeprom_header(file_size, obuffer);
/*
* Output 4 bytes at a time.
* Swap the byte ordering since boot block expects
* words in eeprom to have MSB first and LSB last.
*/
for (i = header_bytes; i < file_size + header_bytes; i += 4) {
obuffer[i] = ibuffer[i+3-header_bytes];
obuffer[i+1] = ibuffer[i+2-header_bytes];
obuffer[i+2] = ibuffer[i+1-header_bytes];
obuffer[i+3] = ibuffer[i-header_bytes];
}
j = fwrite(obuffer, sizeof(char), file_size + header_bytes, fp);
if (j != file_size + header_bytes) {
fprintf(stderr, "Unable to write %5d bytes. Wrote %5d \n",
file_size + header_bytes);
exit(1);
}
close(fp);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -