forked from Imagelibrary/rtems
PC386 BSP enhancements from Aleksey Romanov (Quality Quorum
<qqi@world.std.com>). Unfortunately after merging these, the pc386 will not boot using grub for for. It still does not work using netboot for me. Here is his summary of changes: rtems/c/src/lib/libbsp/i386/pc386/Makefile.in Added support for new sub-directory rtems/c/src/lib/libbsp/i386/pc386/bsp_specs Made possible to build COFF image rtems/c/src/lib/libbsp/i386/pc386/console/console.c Added support for serial consoles, selectable by patching binary image, added __assert(), use _IBMPC_inch_sleep() instaed of _IMBPC_inch() rtems/c/src/lib/libbsp/i386/pc386/console/inch.c Added _IMBPC_inch_sleep() rtems/c/src/lib/libbsp/i386/pc386/console/outch.c Oops - just formatting rtems/c/src/lib/libbsp/i386/pc386/include/Makefile.in Added support for new files rtems/c/src/lib/libbsp/i386/pc386/include/bsp.h Added support for new features rtems/c/src/lib/libbsp/i386/pc386/include/pc386uart.h New file: definitions for serial ports rtems/c/src/lib/libbsp/i386/pc386/include/pcibios.h New file: definitions for PCI BIOS rtems/c/src/lib/libbsp/i386/pc386/pc386dev/Makefile.in New file: makefile in new directory rtems/c/src/lib/libbsp/i386/pc386/pc386dev/i386-stub-glue.c New file: i386-stub interface rtems/c/src/lib/libbsp/i386/pc386/pc386dev/i386-stub.c New file: i386-stub itself rtems/c/src/lib/libbsp/i386/pc386/pc386dev/pc386uart.c New file: serial ports rtems/c/src/lib/libbsp/i386/pc386/pc386dev/pcibios.c New file: PCI BIOS support rtems/c/src/lib/libbsp/i386/pc386/start/start.s Commented out DEBUG_EARLY stuff, everything is working fine rtems/c/src/lib/libbsp/i386/pc386/start/start16.s Cleaned up rtems/c/src/lib/libbsp/i386/pc386/startup/bspstart.c Added call to console_resereve_resources rtems/c/src/lib/libbsp/i386/pc386/startup/exit.c Added support for serial console rtems/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s Fixed typo in comments rtems/c/src/lib/libbsp/i386/pc386/tools/Makefile.in Changed to reflect cnages in code rtems/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c Trivialized, problem - I do not know how to make patch remove obsolete files - there are a lot of them there rtems/c/src/lib/libbsp/i386/pc386/tools/binpatch.c New file: utility to do binary patches rtems/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in Added support for new directory rtems/make/custom/pc386.cfg Add COFF image building
This commit is contained in:
@@ -13,4 +13,4 @@ include $(RTEMS_ROOT)/make/directory.cfg
|
|||||||
|
|
||||||
# wrapup is the one that actually builds and installs the library
|
# wrapup is the one that actually builds and installs the library
|
||||||
# from the individual .rel files built in other directories
|
# from the individual .rel files built in other directories
|
||||||
SUB_DIRS=include tools start startup clock console timer wrapup
|
SUB_DIRS=include tools start startup clock console timer pc386dev wrapup
|
||||||
|
|||||||
@@ -19,5 +19,5 @@
|
|||||||
%{qrtems_debug: start_g.o%s}}
|
%{qrtems_debug: start_g.o%s}}
|
||||||
|
|
||||||
*link:
|
*link:
|
||||||
%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N -e start --oformat=elf32-i386}
|
%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N -e start}
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,17 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <bsp.h>
|
#include <bsp.h>
|
||||||
#include <irq.h>
|
#include <irq.h>
|
||||||
#include <rtems/libio.h>
|
#include <rtems/libio.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <pc386uart.h>
|
||||||
|
|
||||||
|
int PC386ConsolePort = PC386_CONSOLE_PORT_CONSOLE;
|
||||||
|
|
||||||
|
static int conSetAttr(int minor, const struct termios *);
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
/*-------------------------------------------------------------------------+
|
||||||
| Constants
|
| Constants
|
||||||
@@ -51,74 +58,25 @@ extern rtems_isr _IBMPC_keyboard_isr(rtems_vector_number);
|
|||||||
/* keyboard (IRQ 0x01) Interrupt Service Routine (defined in 'inch.c') */
|
/* keyboard (IRQ 0x01) Interrupt Service Routine (defined in 'inch.c') */
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
void console_reserve_resources(rtems_configuration_table *conf)
|
||||||
| Functions
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Function: console_cleanup
|
|
||||||
| Description: This routine is called at exit to clean up the console
|
|
||||||
| hardware.
|
|
||||||
| Global Variables: None.
|
|
||||||
| Arguments: None.
|
|
||||||
| Returns: Nothing.
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
void
|
|
||||||
console_cleanup(void)
|
|
||||||
{
|
{
|
||||||
/* nothing */
|
if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
|
||||||
} /* console_cleanup */
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Function: is_character_ready
|
|
||||||
| Description: Check if a character is available for input, and if so
|
|
||||||
| return it.
|
|
||||||
| Global Variables: None.
|
|
||||||
| Arguments: c - character read if available, otherwise unchanged.
|
|
||||||
| Returns: TRUE if there was a character available for input,
|
|
||||||
| FALSE otherwise.
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
rtems_boolean
|
|
||||||
is_character_ready(char *c)
|
|
||||||
{
|
{
|
||||||
return (_IBMPC_chrdy(c) ? TRUE : FALSE);
|
rtems_termios_reserve_resources(conf, 1);
|
||||||
} /* is_character_ready */
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __assert(const char *file, int line, const char *msg)
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Function: inbyte
|
|
||||||
| Description: Read a character from the console (keyboard).
|
|
||||||
| Global Variables: None.
|
|
||||||
| Arguments: None.
|
|
||||||
| Returns: Caracter read from the console.
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
unsigned char
|
|
||||||
inbyte(void)
|
|
||||||
{
|
{
|
||||||
char c = _IBMPC_inch();
|
printk("assert failed: %s: ", file);
|
||||||
|
printk("%d: ", line);
|
||||||
|
printk("%s\n", msg);
|
||||||
|
|
||||||
/* Echo character to screen */
|
exit(1);
|
||||||
_IBMPC_outch(c);
|
|
||||||
if (c == '\r')
|
|
||||||
_IBMPC_outch('\n'); /* CR = CR + LF */
|
|
||||||
|
|
||||||
return c;
|
|
||||||
} /* inbyte */
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Function: outbyte
|
|
||||||
| Description: Write a character to the console (display).
|
|
||||||
| Global Variables: None.
|
|
||||||
| Arguments: Character to be written.
|
|
||||||
| Returns: Nothing.
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
void
|
|
||||||
outbyte(char c)
|
|
||||||
{
|
|
||||||
_IBMPC_outch(c);
|
|
||||||
} /* outbyte */
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
/*-------------------------------------------------------------------------+
|
||||||
| Console device driver INITIALIZE entry point.
|
| Console device driver INITIALIZE entry point.
|
||||||
@@ -135,6 +93,9 @@ console_initialize(rtems_device_major_number major,
|
|||||||
/* Initialize video */
|
/* Initialize video */
|
||||||
_IBMPC_initVideo();
|
_IBMPC_initVideo();
|
||||||
|
|
||||||
|
if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE)
|
||||||
|
{
|
||||||
|
|
||||||
/* Install keyboard interrupt handler */
|
/* Install keyboard interrupt handler */
|
||||||
status = PC386_installRtemsIrqHandler(KEYBOARD_IRQ, _IBMPC_keyboard_isr);
|
status = PC386_installRtemsIrqHandler(KEYBOARD_IRQ, _IBMPC_keyboard_isr);
|
||||||
|
|
||||||
@@ -144,16 +105,61 @@ console_initialize(rtems_device_major_number major,
|
|||||||
rtems_fatal_error_occurred(status);
|
rtems_fatal_error_occurred(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
status =
|
status = rtems_io_register_name("/dev/console", major, 0);
|
||||||
rtems_io_register_name("/dev/console", major, (rtems_device_minor_number)0);
|
if (status != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
printk("Error registering console device!\n");
|
||||||
|
rtems_fatal_error_occurred(status);
|
||||||
|
}
|
||||||
|
printk("Initialized console on port CONSOLE\n\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set up TERMIOS
|
||||||
|
*/
|
||||||
|
rtems_termios_initialize ();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do device-specific initialization
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 9600-8-N-1 */
|
||||||
|
PC386_uart_init(PC386ConsolePort, 9600, 0);
|
||||||
|
|
||||||
|
|
||||||
|
/* Set interrupt handler */
|
||||||
|
if(PC386ConsolePort == PC386_UART_COM1)
|
||||||
|
{
|
||||||
|
status = PC386_installRtemsIrqHandler(PC386_UART_COM1_IRQ,
|
||||||
|
PC386_uart_termios_isr_com1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(PC386ConsolePort == PC386_UART_COM2);
|
||||||
|
|
||||||
|
status = PC386_installRtemsIrqHandler(PC386_UART_COM2_IRQ,
|
||||||
|
PC386_uart_termios_isr_com2);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Register the device
|
||||||
|
*/
|
||||||
|
status = rtems_io_register_name ("/dev/console", major, 0);
|
||||||
if (status != RTEMS_SUCCESSFUL)
|
if (status != RTEMS_SUCCESSFUL)
|
||||||
{
|
{
|
||||||
printk("Error registering console device!\n");
|
printk("Error registering console device!\n");
|
||||||
rtems_fatal_error_occurred (status);
|
rtems_fatal_error_occurred (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
atexit(console_cleanup);
|
if(PC386ConsolePort == PC386_UART_COM1)
|
||||||
|
{
|
||||||
|
printk("Initialized console on port COM1 9600-8-N-1\n\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printk("Initialized console on port COM2 9600-8-N-1\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
} /* console_initialize */
|
} /* console_initialize */
|
||||||
@@ -167,9 +173,48 @@ console_open(rtems_device_major_number major,
|
|||||||
rtems_device_minor_number minor,
|
rtems_device_minor_number minor,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
return RTEMS_SUCCESSFUL;
|
rtems_status_code status;
|
||||||
} /* console_open */
|
static rtems_termios_callbacks cb =
|
||||||
|
{
|
||||||
|
NULL, /* firstOpen */
|
||||||
|
NULL, /* lastClose */
|
||||||
|
NULL, /* pollRead */
|
||||||
|
PC386_uart_termios_write_com1, /* write */
|
||||||
|
conSetAttr, /* setAttributes */
|
||||||
|
NULL, /* stopRemoteTx */
|
||||||
|
NULL, /* startRemoteTx */
|
||||||
|
1 /* outputUsesInterrupts */
|
||||||
|
};
|
||||||
|
|
||||||
|
if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE)
|
||||||
|
{
|
||||||
|
return RTEMS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(PC386ConsolePort == PC386_UART_COM2)
|
||||||
|
{
|
||||||
|
cb.write = PC386_uart_termios_write_com2;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = rtems_termios_open (major, minor, arg, &cb);
|
||||||
|
|
||||||
|
if(status != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
printk("Error openning console device\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass data area info down to driver
|
||||||
|
*/
|
||||||
|
PC386_uart_termios_set(PC386ConsolePort,
|
||||||
|
((rtems_libio_open_close_args_t *)arg)->iop->data1);
|
||||||
|
|
||||||
|
/* Enable interrupts on channel */
|
||||||
|
PC386_uart_intr_ctrl(PC386ConsolePort, PC386_UART_INTR_CTRL_TERMIOS);
|
||||||
|
|
||||||
|
return RTEMS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
/*-------------------------------------------------------------------------+
|
||||||
| Console device driver CLOSE entry point
|
| Console device driver CLOSE entry point
|
||||||
@@ -179,6 +224,11 @@ console_close(rtems_device_major_number major,
|
|||||||
rtems_device_minor_number minor,
|
rtems_device_minor_number minor,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
|
if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
|
||||||
|
{
|
||||||
|
return rtems_termios_close (arg);
|
||||||
|
}
|
||||||
|
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
} /* console_close */
|
} /* console_close */
|
||||||
|
|
||||||
@@ -197,9 +247,23 @@ console_read(rtems_device_major_number major,
|
|||||||
char *buffer = rw_args->buffer;
|
char *buffer = rw_args->buffer;
|
||||||
int count, maximum = rw_args->count;
|
int count, maximum = rw_args->count;
|
||||||
|
|
||||||
|
if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
|
||||||
|
{
|
||||||
|
return rtems_termios_read (arg);
|
||||||
|
}
|
||||||
|
|
||||||
for (count = 0; count < maximum; count++)
|
for (count = 0; count < maximum; count++)
|
||||||
{
|
{
|
||||||
buffer[count] = inbyte();
|
/* Get character */
|
||||||
|
buffer[count] = _IBMPC_inch_sleep();
|
||||||
|
|
||||||
|
/* Echo character to screen */
|
||||||
|
_IBMPC_outch(buffer[count]);
|
||||||
|
if (buffer[count] == '\r')
|
||||||
|
{
|
||||||
|
_IBMPC_outch('\n'); /* CR = CR + LF */
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer[count] == '\n' || buffer[count] == '\r')
|
if (buffer[count] == '\n' || buffer[count] == '\r')
|
||||||
{
|
{
|
||||||
/* What if this goes past the end of the buffer? We're hosed. [bhc] */
|
/* What if this goes past the end of the buffer? We're hosed. [bhc] */
|
||||||
@@ -228,11 +292,16 @@ console_write(rtems_device_major_number major,
|
|||||||
char *buffer = rw_args->buffer;
|
char *buffer = rw_args->buffer;
|
||||||
int count, maximum = rw_args->count;
|
int count, maximum = rw_args->count;
|
||||||
|
|
||||||
|
if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
|
||||||
|
{
|
||||||
|
return rtems_termios_write (arg);
|
||||||
|
}
|
||||||
|
|
||||||
for (count = 0; count < maximum; count++)
|
for (count = 0; count < maximum; count++)
|
||||||
{
|
{
|
||||||
outbyte(buffer[count]);
|
_IBMPC_outch(buffer[count]);
|
||||||
if (buffer[count] == '\n')
|
if (buffer[count] == '\n')
|
||||||
outbyte('\r'); /* LF = LF + CR */
|
_IBMPC_outch('\r'); /* LF = LF + CR */
|
||||||
}
|
}
|
||||||
|
|
||||||
rw_args->bytes_moved = maximum;
|
rw_args->bytes_moved = maximum;
|
||||||
@@ -240,13 +309,98 @@ console_write(rtems_device_major_number major,
|
|||||||
} /* console_write */
|
} /* console_write */
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Console device driver CONTROL entry point
|
/*
|
||||||
+--------------------------------------------------------------------------*/
|
* Handle ioctl request.
|
||||||
|
*/
|
||||||
rtems_device_driver
|
rtems_device_driver
|
||||||
console_control(rtems_device_major_number major,
|
console_control(rtems_device_major_number major,
|
||||||
rtems_device_minor_number minor,
|
rtems_device_minor_number minor,
|
||||||
void *arg)
|
void * arg
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE)
|
||||||
|
{
|
||||||
|
return rtems_termios_ioctl (arg);
|
||||||
|
}
|
||||||
|
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
} /* console_control */
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
conSetAttr(int minor, const struct termios *t)
|
||||||
|
{
|
||||||
|
int baud;
|
||||||
|
|
||||||
|
switch (t->c_cflag & CBAUD)
|
||||||
|
{
|
||||||
|
case B50:
|
||||||
|
baud = 50;
|
||||||
|
break;
|
||||||
|
case B75:
|
||||||
|
baud = 75;
|
||||||
|
break;
|
||||||
|
case B110:
|
||||||
|
baud = 110;
|
||||||
|
break;
|
||||||
|
case B134:
|
||||||
|
baud = 134;
|
||||||
|
break;
|
||||||
|
case B150:
|
||||||
|
baud = 150;
|
||||||
|
break;
|
||||||
|
case B200:
|
||||||
|
baud = 200;
|
||||||
|
break;
|
||||||
|
case B300:
|
||||||
|
baud = 300;
|
||||||
|
break;
|
||||||
|
case B600:
|
||||||
|
baud = 600;
|
||||||
|
break;
|
||||||
|
case B1200:
|
||||||
|
baud = 1200;
|
||||||
|
break;
|
||||||
|
case B1800:
|
||||||
|
baud = 1800;
|
||||||
|
break;
|
||||||
|
case B2400:
|
||||||
|
baud = 2400;
|
||||||
|
break;
|
||||||
|
case B4800:
|
||||||
|
baud = 4800;
|
||||||
|
break;
|
||||||
|
case B9600:
|
||||||
|
baud = 9600;
|
||||||
|
break;
|
||||||
|
case B19200:
|
||||||
|
baud = 19200;
|
||||||
|
break;
|
||||||
|
case B38400:
|
||||||
|
baud = 38400;
|
||||||
|
break;
|
||||||
|
case B57600:
|
||||||
|
baud = 57600;
|
||||||
|
break;
|
||||||
|
case B115200:
|
||||||
|
baud = 115200;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
baud = 0;
|
||||||
|
rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PC386_uart_set_baud(PC386ConsolePort, baud);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ static char shift_map[] =
|
|||||||
static char kbd_buffer[KBD_BUF_SIZE];
|
static char kbd_buffer[KBD_BUF_SIZE];
|
||||||
static rtems_unsigned16 kbd_first = 0;
|
static rtems_unsigned16 kbd_first = 0;
|
||||||
static rtems_unsigned16 kbd_last = 0;
|
static rtems_unsigned16 kbd_last = 0;
|
||||||
|
static rtems_unsigned16 kbd_end = KBD_BUF_SIZE - 1;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
/*-------------------------------------------------------------------------+
|
||||||
| Function: rtemsReboot
|
| Function: rtemsReboot
|
||||||
@@ -223,11 +224,13 @@ _IBMPC_keyboard_isr(rtems_vector_number vector)
|
|||||||
if (_IBMPC_scankey(&kbd_buffer[kbd_last]))
|
if (_IBMPC_scankey(&kbd_buffer[kbd_last]))
|
||||||
{
|
{
|
||||||
/* Got one; save it if there is enough room in buffer. */
|
/* Got one; save it if there is enough room in buffer. */
|
||||||
unsigned int next = (kbd_last + 1) % KBD_BUF_SIZE;
|
unsigned int next = (kbd_last == kbd_end) ? 0 : kbd_last + 1;
|
||||||
|
|
||||||
if (next != kbd_first)
|
if (next != kbd_first)
|
||||||
|
{
|
||||||
kbd_last = next;
|
kbd_last = next;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PC386_ackIrq(vector - PC386_IRQ_VECTOR_BASE); /* Mark interrupt as handled. */
|
PC386_ackIrq(vector - PC386_IRQ_VECTOR_BASE); /* Mark interrupt as handled. */
|
||||||
} /* _IBMPC_keyboard_isr */
|
} /* _IBMPC_keyboard_isr */
|
||||||
@@ -277,3 +280,38 @@ _IBMPC_inch(void)
|
|||||||
|
|
||||||
return c;
|
return c;
|
||||||
} /* _IBMPC_inch */
|
} /* _IBMPC_inch */
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------+
|
||||||
|
| Function: _IBMPC_inch_sleep
|
||||||
|
| Description: If charcter is ready return it, otherwise sleep until
|
||||||
|
| it is ready
|
||||||
|
| Global Variables: None.
|
||||||
|
| Arguments: None.
|
||||||
|
| Returns: character read from keyboard.
|
||||||
|
+--------------------------------------------------------------------------*/
|
||||||
|
char
|
||||||
|
_IBMPC_inch_sleep(void)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
extern rtems_interval _TOD_Ticks_per_second; /* XXX should not do this */
|
||||||
|
rtems_interval ticks_to_delay;
|
||||||
|
|
||||||
|
ticks_to_delay = (_TOD_Ticks_per_second + 24) / 25;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(_IBMPC_chrdy(&c))
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
rtems_task_wake_after(ticks_to_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
} /* _IBMPC_inch */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ static unsigned short attribute;
|
|||||||
static unsigned int nLines;
|
static unsigned int nLines;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
scroll()
|
scroll(void)
|
||||||
{
|
{
|
||||||
int i, j; /* Counters */
|
int i, j; /* Counters */
|
||||||
unsigned short *pt_scroll, *pt_bitmap; /* Pointers on the bit-map */
|
unsigned short *pt_scroll, *pt_bitmap; /* Pointers on the bit-map */
|
||||||
@@ -56,7 +56,7 @@ scroll()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
endColumn()
|
endColumn(void)
|
||||||
{
|
{
|
||||||
if (++row == maxRow) {
|
if (++row == maxRow) {
|
||||||
scroll(); /* Scroll the screen now */
|
scroll(); /* Scroll the screen now */
|
||||||
@@ -118,7 +118,7 @@ videoPutChar(char car)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clear_screen()
|
clear_screen(void)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ VPATH = @srcdir@
|
|||||||
RTEMS_ROOT = @top_srcdir@
|
RTEMS_ROOT = @top_srcdir@
|
||||||
PROJECT_ROOT = @PROJECT_ROOT@
|
PROJECT_ROOT = @PROJECT_ROOT@
|
||||||
|
|
||||||
H_FILES = $(srcdir)/bsp.h $(srcdir)/coverhd.h $(srcdir)/irq.h $(srcdir)/crt.h
|
H_FILES = $(srcdir)/bsp.h $(srcdir)/coverhd.h $(srcdir)/irq.h \
|
||||||
|
$(srcdir)/crt.h $(srcdir)/pc386uart.h $(srcdir)/pcibios.h
|
||||||
|
|
||||||
#
|
#
|
||||||
# Equate files are for including from assembly preprocessed by
|
# Equate files are for including from assembly preprocessed by
|
||||||
|
|||||||
@@ -133,8 +133,8 @@ extern "C" {
|
|||||||
/*-------------------------------------------------------------------------+
|
/*-------------------------------------------------------------------------+
|
||||||
| External Variables.
|
| External Variables.
|
||||||
+--------------------------------------------------------------------------*/
|
+--------------------------------------------------------------------------*/
|
||||||
extern i386_IDT_slot Interrupt_descriptor_table[256];
|
extern i386_IDT_slot Interrupt_descriptor_table[];
|
||||||
extern i386_GDT_slot Global_descriptor_table [8192];
|
extern i386_GDT_slot Global_descriptor_table [];
|
||||||
|
|
||||||
extern rtems_configuration_table BSP_Configuration;
|
extern rtems_configuration_table BSP_Configuration;
|
||||||
/* User provided BSP configuration table. */
|
/* User provided BSP configuration table. */
|
||||||
@@ -149,14 +149,32 @@ void _IBMPC_initVideo(void); /* from 'outch.c' */
|
|||||||
void _IBMPC_outch (char); /* from 'outch.c' */
|
void _IBMPC_outch (char); /* from 'outch.c' */
|
||||||
rtems_boolean _IBMPC_chrdy (char *); /* from 'inch.c' */
|
rtems_boolean _IBMPC_chrdy (char *); /* from 'inch.c' */
|
||||||
char _IBMPC_inch (void); /* from 'inch.c' */
|
char _IBMPC_inch (void); /* from 'inch.c' */
|
||||||
|
char _IBMPC_inch_sleep (void); /* from 'inch.c' */
|
||||||
|
|
||||||
void printk(char *fmt, ...); /* from 'printk.c' */
|
void printk(char *fmt, ...); /* from 'printk.c' */
|
||||||
|
|
||||||
void rtemsReboot(void); /* from 'exit.c' */
|
void rtemsReboot(void); /* from 'exit.c' */
|
||||||
|
|
||||||
|
/* Definitions for PC386ConsolePort */
|
||||||
|
#define PC386_CONSOLE_PORT_CONSOLE (-1)
|
||||||
|
#define PC386_CONSOLE_PORT_COM1 (PC386_UART_COM1)
|
||||||
|
#define PC386_CONSOLE_PORT_COM2 (PC386_UART_COM2)
|
||||||
|
|
||||||
|
/* GDB stub stuff */
|
||||||
|
void i386_stub_glue_init(int uart);
|
||||||
|
void i386_stub_glue_init_breakin(void);
|
||||||
|
void set_debug_traps(void);
|
||||||
|
void breakpoint(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __BSP_H_ */
|
#endif /* __BSP_H_ */
|
||||||
/* end of include file */
|
/* end of include file */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ BEGIN_CODE
|
|||||||
* to video mode set by the loader, you may try to define
|
* to video mode set by the loader, you may try to define
|
||||||
* the following variable:
|
* the following variable:
|
||||||
*/
|
*/
|
||||||
#define DEBUG_EARLY_START
|
/* #define DEBUG_EARLY_START */
|
||||||
|
|
||||||
SYM (start):
|
SYM (start):
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ void bsp_start( void )
|
|||||||
BSP_Configuration.work_space_start = (void *)rtemsFreeMemStart;
|
BSP_Configuration.work_space_start = (void *)rtemsFreeMemStart;
|
||||||
rtemsFreeMemStart += BSP_Configuration.work_space_size;
|
rtemsFreeMemStart += BSP_Configuration.work_space_size;
|
||||||
|
|
||||||
|
console_reserve_resources(&BSP_Configuration);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following information is very useful when debugging.
|
* The following information is very useful when debugging.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -33,8 +33,14 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <bsp.h>
|
#include <bsp.h>
|
||||||
|
#include <pc386uart.h>
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------+
|
||||||
|
| Which console is in use: either (-1) which means normal console or
|
||||||
|
| uart id if uart was used
|
||||||
|
+-------------------------------------------------------------------------*/
|
||||||
|
extern int PC386ConsolePort;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
/*-------------------------------------------------------------------------+
|
||||||
| External Prototypes
|
| External Prototypes
|
||||||
@@ -50,11 +56,44 @@ extern rtems_boolean _IBMPC_scankey(char *); /* defined in 'inch.c' */
|
|||||||
+--------------------------------------------------------------------------*/
|
+--------------------------------------------------------------------------*/
|
||||||
void _exit(int status)
|
void _exit(int status)
|
||||||
{
|
{
|
||||||
unsigned char ch;
|
unsigned char ch, *cp;
|
||||||
puts("\nEXECUTIVE SHUTDOWN! Any key to reboot...");
|
static char line[]="EXECUTIVE SHUTDOWN! Any key to reboot...";
|
||||||
|
|
||||||
|
if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE)
|
||||||
|
{
|
||||||
|
|
||||||
|
printk("\n");
|
||||||
|
printk(line);
|
||||||
while(!_IBMPC_scankey(&ch))
|
while(!_IBMPC_scankey(&ch))
|
||||||
;
|
;
|
||||||
|
printk("\n\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PC386_uart_intr_ctrl(PC386ConsolePort, PC386_UART_INTR_CTRL_DISABLE);
|
||||||
|
|
||||||
|
PC386_uart_polled_write(PC386ConsolePort, '\r');
|
||||||
|
PC386_uart_polled_write(PC386ConsolePort, '\n');
|
||||||
|
|
||||||
|
for(cp=line; *cp != 0; cp++)
|
||||||
|
{
|
||||||
|
PC386_uart_polled_write(PC386ConsolePort, *cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
PC386_uart_polled_read(PC386ConsolePort);
|
||||||
|
|
||||||
|
PC386_uart_polled_write(PC386ConsolePort, '\r');
|
||||||
|
PC386_uart_polled_write(PC386ConsolePort, '\n');
|
||||||
|
PC386_uart_polled_write(PC386ConsolePort, '\r');
|
||||||
|
PC386_uart_polled_write(PC386ConsolePort, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
rtemsReboot();
|
rtemsReboot();
|
||||||
} /* _exit */
|
} /* _exit */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -66,10 +66,10 @@ SYM(delay):
|
|||||||
| Function: _load_segments
|
| Function: _load_segments
|
||||||
| Description: Current environment is standard PC booted by grub.
|
| Description: Current environment is standard PC booted by grub.
|
||||||
| So, there is no value in saving current GDT and IDT
|
| So, there is no value in saving current GDT and IDT
|
||||||
| Settings we have to set it up ourseves. (Naturally
|
| settings we have to set it up ourseves. (Naturally
|
||||||
| it will be not so in case we are booted by some
|
| it will be not so in case we are booted by some
|
||||||
| boot monitor, however, then it will be different
|
| boot monitor, however, then it will be different
|
||||||
| BSP), After that we have to load board segment registers
|
| BSP). After that we have to load board segment registers
|
||||||
| with apropriate values + reprogram PIC.
|
| with apropriate values + reprogram PIC.
|
||||||
| Global Variables: None.
|
| Global Variables: None.
|
||||||
| Arguments: None.
|
| Arguments: None.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ VPATH=@srcdir@
|
|||||||
USE_HOST_COMPILER=yes
|
USE_HOST_COMPILER=yes
|
||||||
|
|
||||||
# C source names, if any, go here -- minus the .c
|
# C source names, if any, go here -- minus the .c
|
||||||
C_PIECES=bin2boot Header Image
|
C_PIECES= bin2boot binpatch
|
||||||
C_FILES=$(C_PIECES:%=%.c)
|
C_FILES=$(C_PIECES:%=%.c)
|
||||||
C_O_FILES=$(C_PIECES:%=$(ARCH)/%.o)
|
C_O_FILES=$(C_PIECES:%=$(ARCH)/%.o)
|
||||||
|
|
||||||
@@ -30,12 +30,12 @@ CC_PIECES=
|
|||||||
CC_FILES=$(CC_PIECES:%=%.cc)
|
CC_FILES=$(CC_PIECES:%=%.cc)
|
||||||
CC_O_FILES=$(CC_PIECES:%=$(ARCH)/%.o)
|
CC_O_FILES=$(CC_PIECES:%=$(ARCH)/%.o)
|
||||||
|
|
||||||
H_FILES=bytetype.h Header.h Image.h
|
H_FILES=
|
||||||
|
|
||||||
SRCS=$(C_FILES) $(CC_FILES) $(H_FILES)
|
SRCS=$(C_FILES) $(CC_FILES) $(H_FILES)
|
||||||
OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
|
OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
|
||||||
|
|
||||||
PGMS=$(ARCH)/bin2boot
|
PGMS=$(ARCH)/bin2boot $(ARCH)/binpatch
|
||||||
|
|
||||||
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
|
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
|
||||||
include $(RTEMS_ROOT)/make/leaf.cfg
|
include $(RTEMS_ROOT)/make/leaf.cfg
|
||||||
@@ -66,9 +66,10 @@ CLOBBER_ADDITIONS +=
|
|||||||
all: $(ARCH) $(SRCS) $(PGMS)
|
all: $(ARCH) $(SRCS) $(PGMS)
|
||||||
$(INSTALL) -m 555 $(PGMS) ${PROJECT_RELEASE}/build-tools
|
$(INSTALL) -m 555 $(PGMS) ${PROJECT_RELEASE}/build-tools
|
||||||
|
|
||||||
$(ARCH)/bin2boot: $(OBJS)
|
$(ARCH)/bin2boot: $(srcdir)/bin2boot.c
|
||||||
$(CC) $(LDFLAGS) $^ -o $@ $(LD_LIBS)
|
$(CC) $(LDFLAGS) -o $@ $(srcdir)/bin2boot.c $(LD_LIBS)
|
||||||
$(ARCH)/bin2boot.o: bin2boot.c Header.h Image.h bytetype.h
|
|
||||||
$(ARCH)/Header.o: Header.c Header.h bytetype.h
|
$(ARCH)/binpatch: $(srcdir)/binpatch.c
|
||||||
$(ARCH)/Image.o: Image.c Image.h bytetype.h
|
$(CC) $(LDFLAGS) -o $@ $(srcdir)/binpatch.c $(LD_LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,198 +1,414 @@
|
|||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| bin2boot.c v1.0 - PC386 BSP - 1998/04/09
|
|
||||||
+--------------------------------------------------------------------------+
|
|
||||||
| This file contains the i386 binary to boot image filter.
|
|
||||||
+--------------------------------------------------------------------------+
|
|
||||||
| (C) Copyright 1997 -
|
|
||||||
| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
|
||||||
|
|
|
||||||
| http://pandora.ist.utl.pt
|
|
||||||
|
|
|
||||||
| Instituto Superior Tecnico * Lisboa * PORTUGAL
|
|
||||||
+--------------------------------------------------------------------------+
|
|
||||||
| Disclaimer:
|
|
||||||
|
|
|
||||||
| This file is provided "AS IS" without warranty of any kind, either
|
|
||||||
| expressed or implied.
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "Image.h"
|
/*
|
||||||
#include "Header.h"
|
* Simplyfied version of original bin2boot
|
||||||
#include "bytetype.h"
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Constants
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define MAX_IMAGES 15
|
static unsigned char buf[512];
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
static void usage(void)
|
||||||
| Global Variables
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
// Help message for users
|
|
||||||
const char UsageMsg[] = "\
|
|
||||||
Usage: bin2boot <outFile> <locAddr> <inFile1> <startAddr1> <memSize1> \\\n\
|
|
||||||
[<infile2> <startAddr2> <memSize2>][...][-v][-h][-?]\n\
|
|
||||||
\n\
|
|
||||||
<outFile> : output file name (mandatory)\n\
|
|
||||||
<locAddr> : location address in memory of image header (mandatory)\n\
|
|
||||||
<inFileX> : name of Xth input file\n\
|
|
||||||
<startAddrX> : start address of Xth image\n\
|
|
||||||
<memSizeX> : actual size (for compressed images), use 0 if uncompressed\n\
|
|
||||||
-v : verbose output\n\
|
|
||||||
-h, -? : this help message\n\
|
|
||||||
\n\
|
|
||||||
At least one set of <inFile> <startAddr> and <memSize> is mandatory!\n\
|
|
||||||
<locAddr>, <startAddrX> and <memSizeX> can be in Decimal, Hexadecimal or Octal.\n\
|
|
||||||
The maximum number of input files is 15.\n";
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| External Prototypes (for use with getopt)
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
extern char *optarg;
|
|
||||||
|
|
||||||
int getopt(int, char *const[], const char *);
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Auxiliary Functions
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static DWord
|
|
||||||
getNumArg(char *arg)
|
|
||||||
{
|
{
|
||||||
char *dummy;
|
printf("usage: bin2boot [-h][-v] <outFile> <headerAddr> \n");
|
||||||
|
printf("<imFile1> <imAddr1> <imSize1> [<imFile2> <imAddr2> <imSize2>]\n");
|
||||||
|
printf("this function makes image bootable by netboot\n");
|
||||||
|
printf("from one or two binary images\n");
|
||||||
|
printf("-h - prints this message\n");
|
||||||
|
printf("-v - verbose output\n");
|
||||||
|
printf("outFile - output file\n");
|
||||||
|
printf("headerAddr - address to place header in memory\n");
|
||||||
|
printf(" it should be below or equal 0x97e00\n");
|
||||||
|
printf("imFile1 - first image\n");
|
||||||
|
printf("imAddr1 - its start address, image has to be placed whole\n");
|
||||||
|
printf(" below 0x98000 and should not overlap with header\n");
|
||||||
|
printf("imSize1 - actual size of compressed image, 0 for uncompressed\n");
|
||||||
|
printf("imFile2 - second image\n");
|
||||||
|
printf("imAddr2 - its start address\n");
|
||||||
|
printf("imSize2 - actual size of compressed image, 0 for uncompressed\n");
|
||||||
|
|
||||||
if (arg[0] == '0') {
|
return;
|
||||||
if ((arg[1] == 'x') || (arg[1] == 'X')) /* Hexadecimal */
|
}
|
||||||
return (DWord)strtol(arg, &dummy, 16);
|
|
||||||
else /* Octal */
|
|
||||||
return (DWord)strtol(arg, &dummy, 8);
|
|
||||||
} else /* Decimal */
|
|
||||||
return (DWord)strtol(arg, &dummy, 10);
|
|
||||||
} /* getNumArg */
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Main
|
|
||||||
+--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
Image img[MAX_IMAGES]; /* array to store up to MAX_IMAGE images */
|
int c, verbose;
|
||||||
Header hdr; /* boot image file header */
|
extern int optind;
|
||||||
FILE* outFile; /* boot image file stream */
|
FILE *ofp, *ifp;
|
||||||
char* outFileName; /* name of boot image file */
|
unsigned long headerAddr, addr1, addr2;
|
||||||
|
int size1, size2, len1, len2, len, imageCnt, cnt;
|
||||||
|
char *ofile, *ifile, *end;
|
||||||
|
|
||||||
int argPos = 1, numImages, i;
|
verbose = 0;
|
||||||
int verboseFlag = 0, helpFlag = 0; /* flags for command line options */
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
|
||||||
| Parse command line arguments and options
|
|
||||||
+-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
{
|
|
||||||
char opt;
|
|
||||||
|
|
||||||
/* parse command line options */
|
/* parse command line options */
|
||||||
while ((opt = getopt(argc, argv, "vh?")) >= 0)
|
while ((c = getopt(argc, argv, "hv")) >= 0)
|
||||||
{
|
{
|
||||||
argPos++;
|
switch (c)
|
||||||
switch (opt)
|
|
||||||
{
|
{
|
||||||
case 'v' : verboseFlag = 1; break;
|
case 'v':
|
||||||
case 'h' : case '?' : helpFlag = 1; break;
|
verbose = 1;
|
||||||
}
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (helpFlag)
|
if((argc - optind) != 8 && (argc - optind) != 5)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", UsageMsg);
|
usage();
|
||||||
if (argc == 2)
|
return 1;
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
numImages = (argc - argPos - 2) / 3;
|
ofile = argv[optind];
|
||||||
|
ofp = fopen(ofile, "w");
|
||||||
if (numImages < 1)
|
if(ofp == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr, "unable to open file %s\n", ofile);
|
||||||
"ERROR!!! Not enough command line arguments.\n\n%s\n",
|
return 1;
|
||||||
UsageMsg);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
if (numImages > 15)
|
|
||||||
|
/*
|
||||||
|
* Layout is very simple first 512 is header shared by all
|
||||||
|
* images, then images at 512 bytes border
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Fill buffer with 0's */
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
fwrite(buf, 1, sizeof(buf), ofp);
|
||||||
|
|
||||||
|
optind++;
|
||||||
|
headerAddr = strtoul(argv[optind], &end, 0);
|
||||||
|
if(end == argv[optind])
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ERROR!!! Too many input files.\n\n%s\n", UsageMsg);
|
fprintf(stderr, "bad headerAddr %s\n", argv[optind]);
|
||||||
exit(1);
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
newHeader(&hdr); /* initialize hdr */
|
if(headerAddr > 0x97e00)
|
||||||
|
|
||||||
argPos = 1;
|
|
||||||
|
|
||||||
while (argv[argPos][0] == '-') argPos++; /* discard options */
|
|
||||||
if(!(outFile = fopen((outFileName = argv[argPos++]), "w")))
|
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr, "headerAddr is too high 0x%08lx\n", headerAddr);
|
||||||
"ERROR!!! While opening file '%s' for output.\n",
|
fclose(ofp);
|
||||||
outFileName);
|
return 1;
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
reserveSpaceHeader(outFile);
|
|
||||||
|
|
||||||
while (argv[argPos][0] == '-') argPos++; /* discard options */
|
/* Copy the first image */
|
||||||
setLocAddrHeader(&hdr, getNumArg(argv[argPos++]));
|
optind++;
|
||||||
|
ifile = argv[optind];
|
||||||
/*-------------------------------------------------------------------------+
|
ifp = fopen(ifile,"r");
|
||||||
| Parse command line arguments concerning images
|
if(ifp == NULL)
|
||||||
+-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
for(i = 0; i < numImages; i++)
|
|
||||||
{
|
{
|
||||||
newImage(&img[i]);
|
fprintf(stderr, "unable to open output file %s\n", ifile);
|
||||||
while (argv[argPos][0] == '-') argPos++; /* discard options */
|
fclose(ofp);
|
||||||
setImageFile(&img[i], argv[argPos++]);
|
return 1;
|
||||||
while (argv[argPos][0] == '-') argPos++; /* discard options */
|
|
||||||
setLoadAddrImage(&img[i], getNumArg(argv[argPos++]));
|
|
||||||
while (argv[argPos][0] == '-') argPos++; /* discard options */
|
|
||||||
setMemSizeImage(&img[i], getNumArg(argv[argPos++]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setLstImgFlagImage(&img[numImages - 1]); /* set flag on last image */
|
optind++;
|
||||||
setExecAddrHeader(&hdr, getLoadAddrImage(&img[0]));
|
addr1 = strtoul(argv[optind], &end, 0);
|
||||||
/* boot file execution address is the same as first image's */
|
if(end == argv[optind])
|
||||||
if (verboseFlag)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "BootImage file '%s' info:\n\n", outFileName);
|
fprintf(stderr, "bad image address %s\n", argv[optind]);
|
||||||
fprintHeader(stderr, &hdr);
|
fclose(ofp);
|
||||||
fprintf(stderr, "\n");
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------+
|
optind++;
|
||||||
| Dump images and header to file
|
size1 = strtoul(argv[optind], &end, 0);
|
||||||
+-------------------------------------------------------------------------*/
|
if(end == argv[optind])
|
||||||
|
|
||||||
for(i = 0; i < numImages; i++)
|
|
||||||
{
|
{
|
||||||
addImageToHeader(&hdr, &img[i]);
|
fprintf(stderr, "bad image size %s\n", argv[optind]);
|
||||||
dumpImageToFileAndPad(outFile, &img[i]);
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
if (verboseFlag)
|
|
||||||
fprintImage(stderr, &img[i]);
|
|
||||||
|
|
||||||
/* kill image. we don't need anymore and should free its resources */
|
|
||||||
killImage(&img[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dumpHeaderToFile(outFile, &hdr);
|
|
||||||
|
|
||||||
fclose(outFile);
|
/* Copy first image out and remember its length */
|
||||||
|
cnt = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
len = fread(buf, 1, sizeof(buf), ifp);
|
||||||
|
|
||||||
|
if(len != 0)
|
||||||
|
{
|
||||||
|
fwrite(buf, 1, len, ofp);
|
||||||
|
cnt += sizeof(buf);
|
||||||
|
|
||||||
|
if(len != sizeof(buf))
|
||||||
|
{
|
||||||
|
memset(buf, 0, sizeof(buf) - len);
|
||||||
|
fwrite(buf, 1, sizeof(buf) - len, ofp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ifp);
|
||||||
|
|
||||||
|
len1 = cnt;
|
||||||
|
|
||||||
|
if(size1 == 0)
|
||||||
|
{
|
||||||
|
size1 = cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
while(cnt < size1)
|
||||||
|
{
|
||||||
|
fwrite(buf, 1, sizeof(buf), ofp);
|
||||||
|
cnt += sizeof(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
size1 = cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Let us check agains overlapping */
|
||||||
|
if(!(addr1 >= (headerAddr + sizeof(buf)) || (headerAddr >= addr1+size1)))
|
||||||
|
{
|
||||||
|
/* Areas overlapped */
|
||||||
|
printf("area overlapping: \n");
|
||||||
|
printf("header address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
headerAddr, sizeof(buf));
|
||||||
|
printf("first image address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
addr1, size1);
|
||||||
|
|
||||||
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr1 + size1) > 0x98000)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "imAddr1 is too high 0x%08lx\n", addr1);
|
||||||
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(optind == (argc - 1))
|
||||||
|
{
|
||||||
|
imageCnt = 1;
|
||||||
|
goto writeHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageCnt = 2;
|
||||||
|
|
||||||
|
/* Copy Second Image */
|
||||||
|
optind++;
|
||||||
|
ifile = argv[optind];
|
||||||
|
ifp = fopen(ifile,"r");
|
||||||
|
if(ifp == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unable to open output file %s\n", ifile);
|
||||||
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
optind++;
|
||||||
|
addr2 = strtoul(argv[optind], &end, 0);
|
||||||
|
if(end == argv[optind])
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad image address %s\n", argv[optind]);
|
||||||
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
optind++;
|
||||||
|
size2 = strtoul(argv[optind], &end, 0);
|
||||||
|
if(end == argv[optind])
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad image size %s\n", argv[optind]);
|
||||||
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy second image out and remember its length */
|
||||||
|
cnt = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
len = fread(buf, 1, sizeof(buf), ifp);
|
||||||
|
|
||||||
|
if(len != 0)
|
||||||
|
{
|
||||||
|
fwrite(buf, len, 1, ofp);
|
||||||
|
cnt += sizeof(buf);
|
||||||
|
|
||||||
|
if(len != sizeof(buf))
|
||||||
|
{
|
||||||
|
memset(buf, 0, sizeof(buf) - len);
|
||||||
|
fwrite(buf, 1, sizeof(buf) - len, ofp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ifp);
|
||||||
|
|
||||||
|
len2 = cnt;
|
||||||
|
|
||||||
|
if(size2 == 0)
|
||||||
|
{
|
||||||
|
size2 = cnt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
while(cnt < size2)
|
||||||
|
{
|
||||||
|
fwrite(buf, 1, sizeof(buf), ofp);
|
||||||
|
cnt += sizeof(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
size2 = cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let us check against overlapping */
|
||||||
|
if(!((addr2 >= (addr1 + size1) && addr2 >= (headerAddr + sizeof(buf))) ||
|
||||||
|
(addr2 < addr1 && addr2 < headerAddr) ||
|
||||||
|
(addr1 > headerAddr && addr2 > (headerAddr + sizeof(buf)) &&
|
||||||
|
(addr2 + size2) <= addr1) ||
|
||||||
|
(addr1 < headerAddr && addr2 > (addr1 + size1) &&
|
||||||
|
(addr2 + size2) <= headerAddr)))
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Areas overlapped */
|
||||||
|
printf("area overlapping: \n");
|
||||||
|
printf("header address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
headerAddr, sizeof(buf));
|
||||||
|
printf("first image address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
addr1, size1);
|
||||||
|
printf("second image address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
addr2, size2);
|
||||||
|
|
||||||
|
fclose(ofp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeHeader:
|
||||||
|
|
||||||
|
/* We know everything so it is time to write buffer */
|
||||||
|
memset(buf, 0, 0x30);
|
||||||
|
|
||||||
|
buf[0x0] = 0x36;
|
||||||
|
buf[0x1] = 0x13;
|
||||||
|
buf[0x2] = 0x03;
|
||||||
|
buf[0x3] = 0x1b;
|
||||||
|
|
||||||
|
buf[0x4] = 4;
|
||||||
|
|
||||||
|
/* Header address in ds:bx format */
|
||||||
|
buf[0x8] = headerAddr & 0xf;
|
||||||
|
buf[0x9] = 0;
|
||||||
|
buf[0xa] = (headerAddr >> 4) & 0xff;
|
||||||
|
buf[0xb] = (headerAddr >> 12) & 0xff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Execute address in cs:ip format, which addr1
|
||||||
|
*/
|
||||||
|
buf[0xc] = addr1 & 0xf;
|
||||||
|
buf[0xd] = 0;
|
||||||
|
buf[0xe] = (addr1 >> 4) & 0xff;
|
||||||
|
buf[0xf] = (addr1 >> 12) & 0xff;
|
||||||
|
|
||||||
|
/* Flags, tags and lengths */
|
||||||
|
buf[0x10] = 4;
|
||||||
|
|
||||||
|
if(imageCnt == 1)
|
||||||
|
{
|
||||||
|
buf[0x13] = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load address */
|
||||||
|
buf[0x14] = addr1 & 0xff;
|
||||||
|
buf[0x15] = (addr1 >> 8) & 0xff;
|
||||||
|
buf[0x16] = (addr1 >> 16) & 0xff;
|
||||||
|
buf[0x17] = (addr1 >> 24) & 0xff;
|
||||||
|
|
||||||
|
/* Image Length */
|
||||||
|
buf[0x18] = len1 & 0xff;
|
||||||
|
buf[0x19] = (len1 >> 8) & 0xff;
|
||||||
|
buf[0x1a] = (len1 >> 16) & 0xff;
|
||||||
|
buf[0x1b] = (len1 >> 24) & 0xff;
|
||||||
|
|
||||||
|
/* Memory Size */
|
||||||
|
buf[0x1c] = size1 & 0xff;
|
||||||
|
buf[0x1d] = (size1 >> 8) & 0xff;
|
||||||
|
buf[0x1e] = (size1 >> 16) & 0xff;
|
||||||
|
buf[0x1f] = (size1 >> 24) & 0xff;
|
||||||
|
|
||||||
|
if(imageCnt != 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Flags, tags and lengths */
|
||||||
|
buf[0x20] = 4;
|
||||||
|
|
||||||
|
buf[0x23] = 4;
|
||||||
|
|
||||||
|
|
||||||
|
/* Load address */
|
||||||
|
buf[0x24] = addr2 & 0xff;
|
||||||
|
buf[0x25] = (addr2 >> 8) & 0xff;
|
||||||
|
buf[0x26] = (addr2 >> 16) & 0xff;
|
||||||
|
buf[0x27] = (addr2 >> 24) & 0xff;
|
||||||
|
|
||||||
|
/* Image Length */
|
||||||
|
buf[0x28] = len2 & 0xff;
|
||||||
|
buf[0x29] = (len2 >> 8) & 0xff;
|
||||||
|
buf[0x2a] = (len2 >> 16) & 0xff;
|
||||||
|
buf[0x2b] = (len2 >> 24) & 0xff;
|
||||||
|
|
||||||
|
/* Memory Size */
|
||||||
|
buf[0x2c] = size2 & 0xff;
|
||||||
|
buf[0x2d] = (size2 >> 8) & 0xff;
|
||||||
|
buf[0x2e] = (size2 >> 16) & 0xff;
|
||||||
|
buf[0x2f] = (size2 >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind(ofp);
|
||||||
|
|
||||||
|
fwrite(buf, 1, 0x30, ofp);
|
||||||
|
|
||||||
|
fclose(ofp);
|
||||||
|
|
||||||
|
if(verbose)
|
||||||
|
{
|
||||||
|
printf("header address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
headerAddr, sizeof(buf));
|
||||||
|
printf("first image address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
addr1, size1);
|
||||||
|
printf("second image address 0x%08lx, its memory size 0x%08x\n",
|
||||||
|
addr2, size2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
} /* main */
|
|
||||||
|
|
||||||
|
|||||||
168
c/src/lib/libbsp/i386/pc386/tools/binpatch.c
Normal file
168
c/src/lib/libbsp/i386/pc386/tools/binpatch.c
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will patch binary file
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static char buf[512];
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
printf("usage: binpatch [-h] <ofile> <ifile> <reloc> <off> <byte0> "
|
||||||
|
"[<byte1> [<byte2> [<byte3>]]]\n");
|
||||||
|
printf("this function patches binary file at specified offset with\n");
|
||||||
|
printf("up to 4 bytes provided on command line \n");
|
||||||
|
printf("-h - prints this message\n\n");
|
||||||
|
printf("<ofile> - output file\n");
|
||||||
|
printf("<ifile> - input ifile\n");
|
||||||
|
printf("<reloc> - relocation address of image\n");
|
||||||
|
printf("<off> - offset of patch, offset in file is at off - reloc\n");
|
||||||
|
printf("<byte0> - byte 0 of patch\n");
|
||||||
|
printf("<byte1> - byte 1 of patch\n");
|
||||||
|
printf("<byte2> - byte 1 of patch\n");
|
||||||
|
printf("<byte3> - byte 1 of patch\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
FILE *ofp, *ifp;
|
||||||
|
char patch[4], *end;
|
||||||
|
int patchLen, tmp, i, off, cnt, patched, len, reloc;
|
||||||
|
|
||||||
|
|
||||||
|
/* parse command line options */
|
||||||
|
while ((c = getopt(argc, argv, "h")) >= 0)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc < 6)
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let us get offset in file */
|
||||||
|
reloc = strtol(argv[3], &end, 0);
|
||||||
|
if(end == argv[3] || off < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad reloc value %s\n", argv[3]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
off = strtol(argv[4], &end, 0);
|
||||||
|
if(end == argv[4] || off < 0 || off < reloc)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad offset value %s\n", argv[4]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
off -= reloc;
|
||||||
|
|
||||||
|
/* Let us get patch */
|
||||||
|
patchLen = argc - 5;
|
||||||
|
|
||||||
|
for(i=0; i<patchLen; i++)
|
||||||
|
{
|
||||||
|
tmp = strtol(argv[5+i], &end, 0);
|
||||||
|
|
||||||
|
if(end == argv[4+i] || tmp < 0 || tmp > 0xff)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad byte value %s\n", argv[5+i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
patch[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifp = fopen(argv[2], "r");
|
||||||
|
if(ifp == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unable to open file %s\n", argv[2]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofp = fopen(argv[1], "w");
|
||||||
|
if(ofp == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unable to open file %s\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = 0;
|
||||||
|
patched = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
len = fread(buf, 1, sizeof(buf), ifp);
|
||||||
|
|
||||||
|
if(len == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cnt <= off && (cnt + len) > off)
|
||||||
|
{
|
||||||
|
/* Perform patch */
|
||||||
|
for(i=0; i<patchLen && (off+i)<(cnt+len); i++)
|
||||||
|
{
|
||||||
|
buf[off-cnt+i] = patch[i];
|
||||||
|
}
|
||||||
|
patched = 1;
|
||||||
|
}
|
||||||
|
else if(cnt > off && cnt < (off + patchLen))
|
||||||
|
{
|
||||||
|
/* Perform patch */
|
||||||
|
for(i=cnt-off; i<patchLen; i++)
|
||||||
|
{
|
||||||
|
buf[off-cnt+i] = patch[i];
|
||||||
|
}
|
||||||
|
patched = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(buf, 1, len, ofp);
|
||||||
|
|
||||||
|
cnt += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ifp);
|
||||||
|
fclose(ofp);
|
||||||
|
|
||||||
|
if(!patched)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "warning: offset is beyond input file length\n");
|
||||||
|
fprintf(stderr, " no patch is performed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ VPATH = @srcdir@
|
|||||||
RTEMS_ROOT = @top_srcdir@
|
RTEMS_ROOT = @top_srcdir@
|
||||||
PROJECT_ROOT = @PROJECT_ROOT@
|
PROJECT_ROOT = @PROJECT_ROOT@
|
||||||
|
|
||||||
BSP_PIECES=startup clock console timer
|
BSP_PIECES=startup clock console timer pc386dev
|
||||||
GENERIC_PIECES=
|
GENERIC_PIECES=
|
||||||
|
|
||||||
# bummer; have to use $foreach since % pattern subst rules only replace 1x
|
# bummer; have to use $foreach since % pattern subst rules only replace 1x
|
||||||
|
|||||||
@@ -102,8 +102,12 @@ define make-exe
|
|||||||
$(NM) -g -n $(basename $@).obj > $(basename $@).num
|
$(NM) -g -n $(basename $@).obj > $(basename $@).num
|
||||||
$(SIZE) $(basename $@).obj
|
$(SIZE) $(basename $@).obj
|
||||||
$(INSTALL_VARIANT) -m 555 $(basename $@).bt ${PROJECT_RELEASE}/BootImgs
|
$(INSTALL_VARIANT) -m 555 $(basename $@).bt ${PROJECT_RELEASE}/BootImgs
|
||||||
|
$(CC) $(CFLAGS) $(CFLAGS_LD) -Wl,-Ttext,$(RELOCADDR) \
|
||||||
|
-o $(basename $@).coff $(LINK_OBJS) $(LINK_LIBS)
|
||||||
endef
|
endef
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Miscellaneous additions go here
|
# Miscellaneous additions go here
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
168
tools/build/binpatch.c
Normal file
168
tools/build/binpatch.c
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function will patch binary file
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static char buf[512];
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
printf("usage: binpatch [-h] <ofile> <ifile> <reloc> <off> <byte0> "
|
||||||
|
"[<byte1> [<byte2> [<byte3>]]]\n");
|
||||||
|
printf("this function patches binary file at specified offset with\n");
|
||||||
|
printf("up to 4 bytes provided on command line \n");
|
||||||
|
printf("-h - prints this message\n\n");
|
||||||
|
printf("<ofile> - output file\n");
|
||||||
|
printf("<ifile> - input ifile\n");
|
||||||
|
printf("<reloc> - relocation address of image\n");
|
||||||
|
printf("<off> - offset of patch, offset in file is at off - reloc\n");
|
||||||
|
printf("<byte0> - byte 0 of patch\n");
|
||||||
|
printf("<byte1> - byte 1 of patch\n");
|
||||||
|
printf("<byte2> - byte 1 of patch\n");
|
||||||
|
printf("<byte3> - byte 1 of patch\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
FILE *ofp, *ifp;
|
||||||
|
char patch[4], *end;
|
||||||
|
int patchLen, tmp, i, off, cnt, patched, len, reloc;
|
||||||
|
|
||||||
|
|
||||||
|
/* parse command line options */
|
||||||
|
while ((c = getopt(argc, argv, "h")) >= 0)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc < 6)
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let us get offset in file */
|
||||||
|
reloc = strtol(argv[3], &end, 0);
|
||||||
|
if(end == argv[3] || off < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad reloc value %s\n", argv[3]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
off = strtol(argv[4], &end, 0);
|
||||||
|
if(end == argv[4] || off < 0 || off < reloc)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad offset value %s\n", argv[4]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
off -= reloc;
|
||||||
|
|
||||||
|
/* Let us get patch */
|
||||||
|
patchLen = argc - 5;
|
||||||
|
|
||||||
|
for(i=0; i<patchLen; i++)
|
||||||
|
{
|
||||||
|
tmp = strtol(argv[5+i], &end, 0);
|
||||||
|
|
||||||
|
if(end == argv[4+i] || tmp < 0 || tmp > 0xff)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bad byte value %s\n", argv[5+i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
patch[i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifp = fopen(argv[2], "r");
|
||||||
|
if(ifp == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unable to open file %s\n", argv[2]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofp = fopen(argv[1], "w");
|
||||||
|
if(ofp == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "unable to open file %s\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = 0;
|
||||||
|
patched = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
len = fread(buf, 1, sizeof(buf), ifp);
|
||||||
|
|
||||||
|
if(len == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cnt <= off && (cnt + len) > off)
|
||||||
|
{
|
||||||
|
/* Perform patch */
|
||||||
|
for(i=0; i<patchLen && (off+i)<(cnt+len); i++)
|
||||||
|
{
|
||||||
|
buf[off-cnt+i] = patch[i];
|
||||||
|
}
|
||||||
|
patched = 1;
|
||||||
|
}
|
||||||
|
else if(cnt > off && cnt < (off + patchLen))
|
||||||
|
{
|
||||||
|
/* Perform patch */
|
||||||
|
for(i=cnt-off; i<patchLen; i++)
|
||||||
|
{
|
||||||
|
buf[off-cnt+i] = patch[i];
|
||||||
|
}
|
||||||
|
patched = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(buf, 1, len, ofp);
|
||||||
|
|
||||||
|
cnt += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(ifp);
|
||||||
|
fclose(ofp);
|
||||||
|
|
||||||
|
if(!patched)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "warning: offset is beyond input file length\n");
|
||||||
|
fprintf(stderr, " no patch is performed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user