diff options
Diffstat (limited to 'c/src/lib')
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/Makefile.in | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/bsp_specs | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/console/console.c | 346 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/console/inch.c | 44 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/console/outch.c | 14 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/include/Makefile.in | 3 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/include/bsp.h | 22 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/start/start.s | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/startup/bspstart.c | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/startup/exit.c | 49 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/startup/ldsegs.s | 4 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/tools/Makefile.in | 17 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/tools/bin2boot.c | 586 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/tools/binpatch.c | 168 | ||||
-rw-r--r-- | c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in | 2 |
15 files changed, 950 insertions, 313 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.in b/c/src/lib/libbsp/i386/pc386/Makefile.in index 9e5e08f345..763c759d26 100644 --- a/c/src/lib/libbsp/i386/pc386/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/Makefile.in @@ -13,4 +13,4 @@ include $(RTEMS_ROOT)/make/directory.cfg # wrapup is the one that actually builds and installs the library # 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 diff --git a/c/src/lib/libbsp/i386/pc386/bsp_specs b/c/src/lib/libbsp/i386/pc386/bsp_specs index f131fa1d9c..61dac86b53 100644 --- a/c/src/lib/libbsp/i386/pc386/bsp_specs +++ b/c/src/lib/libbsp/i386/pc386/bsp_specs @@ -19,5 +19,5 @@ %{qrtems_debug: start_g.o%s}} *link: -%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N -e start --oformat=elf32-i386} +%{!qrtems: %(old_link)} %{qrtems: -dc -dp -N -e start} diff --git a/c/src/lib/libbsp/i386/pc386/console/console.c b/c/src/lib/libbsp/i386/pc386/console/console.c index 1689f5c546..8698ea8136 100644 --- a/c/src/lib/libbsp/i386/pc386/console/console.c +++ b/c/src/lib/libbsp/i386/pc386/console/console.c @@ -33,10 +33,17 @@ #include <stdlib.h> +#include <assert.h> #include <bsp.h> #include <irq.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 @@ -51,74 +58,25 @@ extern rtems_isr _IBMPC_keyboard_isr(rtems_vector_number); /* keyboard (IRQ 0x01) Interrupt Service Routine (defined in 'inch.c') */ -/*-------------------------------------------------------------------------+ -| 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) +void console_reserve_resources(rtems_configuration_table *conf) { - /* nothing */ -} /* 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); -} /* is_character_ready */ - + if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + { + rtems_termios_reserve_resources(conf, 1); + } + return; +} -/*-------------------------------------------------------------------------+ -| 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) +void __assert(const char *file, int line, const char *msg) { - char c = _IBMPC_inch(); - - /* Echo character to screen */ - _IBMPC_outch(c); - if (c == '\r') - _IBMPC_outch('\n'); /* CR = CR + LF */ + printk("assert failed: %s: ", file); + printk("%d: ", line); + printk("%s\n", msg); - 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 */ + exit(1); + return; +} /*-------------------------------------------------------------------------+ | Console device driver INITIALIZE entry point. @@ -135,26 +93,74 @@ console_initialize(rtems_device_major_number major, /* Initialize video */ _IBMPC_initVideo(); - /* Install keyboard interrupt handler */ - status = PC386_installRtemsIrqHandler(KEYBOARD_IRQ, _IBMPC_keyboard_isr); - - if (status != RTEMS_SUCCESSFUL) - { - printk("Error installing keyboard interrupt handler!\n"); - rtems_fatal_error_occurred(status); - } + if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE) + { - status = - 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); - } + /* Install keyboard interrupt handler */ + status = PC386_installRtemsIrqHandler(KEYBOARD_IRQ, _IBMPC_keyboard_isr); + + if (status != RTEMS_SUCCESSFUL) + { + printk("Error installing keyboard interrupt handler!\n"); + rtems_fatal_error_occurred(status); + } + + status = rtems_io_register_name("/dev/console", major, 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) + { + printk("Error registering console device!\n"); + rtems_fatal_error_occurred (status); + } + + 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"); + } + } - atexit(console_cleanup); - return RTEMS_SUCCESSFUL; } /* console_initialize */ @@ -164,12 +170,51 @@ console_initialize(rtems_device_major_number major, +--------------------------------------------------------------------------*/ rtems_device_driver console_open(rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg) + rtems_device_minor_number minor, + void *arg) { - return RTEMS_SUCCESSFUL; -} /* console_open */ + rtems_status_code status; + 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 @@ -179,6 +224,11 @@ console_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { + if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + { + return rtems_termios_close (arg); + } + return RTEMS_SUCCESSFUL; } /* console_close */ @@ -196,10 +246,24 @@ console_read(rtems_device_major_number major, rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; char *buffer = rw_args->buffer; int count, maximum = rw_args->count; + + if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + { + return rtems_termios_read (arg); + } 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') { /* What if this goes past the end of the buffer? We're hosed. [bhc] */ @@ -227,12 +291,17 @@ console_write(rtems_device_major_number major, rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; char *buffer = rw_args->buffer; int count, maximum = rw_args->count; + + if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + { + return rtems_termios_write (arg); + } for (count = 0; count < maximum; count++) { - outbyte(buffer[count]); + _IBMPC_outch(buffer[count]); if (buffer[count] == '\n') - outbyte('\r'); /* LF = LF + CR */ + _IBMPC_outch('\r'); /* LF = LF + CR */ } rw_args->bytes_moved = maximum; @@ -240,13 +309,98 @@ console_write(rtems_device_major_number major, } /* console_write */ -/*-------------------------------------------------------------------------+ -| Console device driver CONTROL entry point -+--------------------------------------------------------------------------*/ -rtems_device_driver + +/* + * Handle ioctl request. + */ +rtems_device_driver console_control(rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg) -{ + rtems_device_minor_number minor, + void * arg +) +{ + if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + { + return rtems_termios_ioctl (arg); + } + 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; +} + + + + + + + + + diff --git a/c/src/lib/libbsp/i386/pc386/console/inch.c b/c/src/lib/libbsp/i386/pc386/console/inch.c index bcb9a17312..f29f6124c8 100644 --- a/c/src/lib/libbsp/i386/pc386/console/inch.c +++ b/c/src/lib/libbsp/i386/pc386/console/inch.c @@ -70,6 +70,7 @@ static char shift_map[] = static char kbd_buffer[KBD_BUF_SIZE]; static rtems_unsigned16 kbd_first = 0; static rtems_unsigned16 kbd_last = 0; +static rtems_unsigned16 kbd_end = KBD_BUF_SIZE - 1; /*-------------------------------------------------------------------------+ | Function: rtemsReboot @@ -81,7 +82,7 @@ static rtems_unsigned16 kbd_last = 0; void rtemsReboot(void) { /* shutdown and reboot */ - outport_byte(0x64, 0xFE); /* use keyboard controler to do the job... */ + outport_byte(0x64, 0xFE); /* use keyboard controler to do the job... */ } /* rtemsReboot */ /*-------------------------------------------------------------------------+ @@ -223,10 +224,12 @@ _IBMPC_keyboard_isr(rtems_vector_number vector) if (_IBMPC_scankey(&kbd_buffer[kbd_last])) { /* 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) - kbd_last = next; + { + kbd_last = next; + } } PC386_ackIrq(vector - PC386_IRQ_VECTOR_BASE); /* Mark interrupt as handled. */ @@ -277,3 +280,38 @@ _IBMPC_inch(void) return c; } /* _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 */ + + + + + + diff --git a/c/src/lib/libbsp/i386/pc386/console/outch.c b/c/src/lib/libbsp/i386/pc386/console/outch.c index e4c45c2166..1d5c1f9c38 100644 --- a/c/src/lib/libbsp/i386/pc386/console/outch.c +++ b/c/src/lib/libbsp/i386/pc386/console/outch.c @@ -33,8 +33,8 @@ static unsigned char column; static unsigned short attribute; static unsigned int nLines; - static void -scroll() +static void +scroll(void) { int i, j; /* Counters */ unsigned short *pt_scroll, *pt_bitmap; /* Pointers on the bit-map */ @@ -55,8 +55,8 @@ scroll() } } - static void -endColumn() +static void +endColumn(void) { if (++row == maxRow) { scroll(); /* Scroll the screen now */ @@ -70,7 +70,7 @@ endColumn() - static void +static void videoPutChar(char car) { unsigned short *pt_bitmap = bitMapBaseAddr + row * maxCol; @@ -117,8 +117,8 @@ videoPutChar(char car) } } - void -clear_screen() +void +clear_screen(void) { int i,j; diff --git a/c/src/lib/libbsp/i386/pc386/include/Makefile.in b/c/src/lib/libbsp/i386/pc386/include/Makefile.in index 8f02fc9b25..49e4168eca 100644 --- a/c/src/lib/libbsp/i386/pc386/include/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/include/Makefile.in @@ -8,7 +8,8 @@ VPATH = @srcdir@ RTEMS_ROOT = @top_srcdir@ 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 diff --git a/c/src/lib/libbsp/i386/pc386/include/bsp.h b/c/src/lib/libbsp/i386/pc386/include/bsp.h index b404003d92..c7920f385b 100644 --- a/c/src/lib/libbsp/i386/pc386/include/bsp.h +++ b/c/src/lib/libbsp/i386/pc386/include/bsp.h @@ -133,8 +133,8 @@ extern "C" { /*-------------------------------------------------------------------------+ | External Variables. +--------------------------------------------------------------------------*/ -extern i386_IDT_slot Interrupt_descriptor_table[256]; -extern i386_GDT_slot Global_descriptor_table [8192]; +extern i386_IDT_slot Interrupt_descriptor_table[]; +extern i386_GDT_slot Global_descriptor_table []; extern rtems_configuration_table BSP_Configuration; /* User provided BSP configuration table. */ @@ -149,14 +149,32 @@ void _IBMPC_initVideo(void); /* from 'outch.c' */ void _IBMPC_outch (char); /* from 'outch.c' */ rtems_boolean _IBMPC_chrdy (char *); /* 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 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 } #endif #endif /* __BSP_H_ */ /* end of include file */ + + + + + + diff --git a/c/src/lib/libbsp/i386/pc386/start/start.s b/c/src/lib/libbsp/i386/pc386/start/start.s index 111962f0c5..fae56137e5 100644 --- a/c/src/lib/libbsp/i386/pc386/start/start.s +++ b/c/src/lib/libbsp/i386/pc386/start/start.s @@ -70,7 +70,7 @@ BEGIN_CODE * to video mode set by the loader, you may try to define * the following variable: */ -#define DEBUG_EARLY_START +/* #define DEBUG_EARLY_START */ SYM (start): /* diff --git a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c index d952457485..607e816d6d 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c +++ b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c @@ -126,6 +126,8 @@ void bsp_start( void ) BSP_Configuration.work_space_start = (void *)rtemsFreeMemStart; rtemsFreeMemStart += BSP_Configuration.work_space_size; + console_reserve_resources(&BSP_Configuration); + /* * The following information is very useful when debugging. */ diff --git a/c/src/lib/libbsp/i386/pc386/startup/exit.c b/c/src/lib/libbsp/i386/pc386/startup/exit.c index 85b5282c36..328a0afa76 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/exit.c +++ b/c/src/lib/libbsp/i386/pc386/startup/exit.c @@ -33,8 +33,14 @@ #include <stdio.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 @@ -50,11 +56,44 @@ extern rtems_boolean _IBMPC_scankey(char *); /* defined in 'inch.c' */ +--------------------------------------------------------------------------*/ void _exit(int status) { - unsigned char ch; - puts("\nEXECUTIVE SHUTDOWN! Any key to reboot..."); + unsigned char ch, *cp; + static char line[]="EXECUTIVE SHUTDOWN! Any key to reboot..."; + + if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE) + { - while(!_IBMPC_scankey(&ch)) - ; + printk("\n"); + printk(line); + 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(); } /* _exit */ + + + + + + + diff --git a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s index a8eb935322..f2171575ce 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s +++ b/c/src/lib/libbsp/i386/pc386/startup/ldsegs.s @@ -66,10 +66,10 @@ SYM(delay): | Function: _load_segments | Description: Current environment is standard PC booted by grub. | 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 | 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. | Global Variables: None. | Arguments: None. diff --git a/c/src/lib/libbsp/i386/pc386/tools/Makefile.in b/c/src/lib/libbsp/i386/pc386/tools/Makefile.in index f62a47bb69..0924a4afca 100644 --- a/c/src/lib/libbsp/i386/pc386/tools/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/tools/Makefile.in @@ -22,7 +22,7 @@ VPATH=@srcdir@ USE_HOST_COMPILER=yes # 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_O_FILES=$(C_PIECES:%=$(ARCH)/%.o) @@ -30,12 +30,12 @@ CC_PIECES= CC_FILES=$(CC_PIECES:%=%.cc) CC_O_FILES=$(CC_PIECES:%=$(ARCH)/%.o) -H_FILES=bytetype.h Header.h Image.h +H_FILES= SRCS=$(C_FILES) $(CC_FILES) $(H_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/leaf.cfg @@ -66,9 +66,10 @@ CLOBBER_ADDITIONS += all: $(ARCH) $(SRCS) $(PGMS) $(INSTALL) -m 555 $(PGMS) ${PROJECT_RELEASE}/build-tools -$(ARCH)/bin2boot: $(OBJS) - $(CC) $(LDFLAGS) $^ -o $@ $(LD_LIBS) -$(ARCH)/bin2boot.o: bin2boot.c Header.h Image.h bytetype.h -$(ARCH)/Header.o: Header.c Header.h bytetype.h -$(ARCH)/Image.o: Image.c Image.h bytetype.h +$(ARCH)/bin2boot: $(srcdir)/bin2boot.c + $(CC) $(LDFLAGS) -o $@ $(srcdir)/bin2boot.c $(LD_LIBS) + +$(ARCH)/binpatch: $(srcdir)/binpatch.c + $(CC) $(LDFLAGS) -o $@ $(srcdir)/binpatch.c $(LD_LIBS) + diff --git a/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c b/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c index d8d19b4166..a47ca2cee3 100644 --- a/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c +++ b/c/src/lib/libbsp/i386/pc386/tools/bin2boot.c @@ -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" -#include "bytetype.h" + +/* + * Simplyfied version of original bin2boot + */ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <memory.h> -/*-------------------------------------------------------------------------+ -| Constants -+--------------------------------------------------------------------------*/ - -#define MAX_IMAGES 15 - -/*-------------------------------------------------------------------------+ -| 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; - if (arg[0] == '0') { - 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 */ +static unsigned char buf[512]; + +static void usage(void) +{ + 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"); + + return; +} -/*-------------------------------------------------------------------------+ -| Main -+--------------------------------------------------------------------------*/ int main(int argc, char* argv[]) { - Image img[MAX_IMAGES]; /* array to store up to MAX_IMAGE images */ - Header hdr; /* boot image file header */ - FILE* outFile; /* boot image file stream */ - char* outFileName; /* name of boot image file */ + int c, verbose; + extern int optind; + FILE *ofp, *ifp; + unsigned long headerAddr, addr1, addr2; + int size1, size2, len1, len2, len, imageCnt, cnt; + char *ofile, *ifile, *end; + + verbose = 0; - int argPos = 1, numImages, i; - int verboseFlag = 0, helpFlag = 0; /* flags for command line options */ + /* parse command line options */ + while ((c = getopt(argc, argv, "hv")) >= 0) + { + switch (c) + { + case 'v': + verbose = 1; + break; + case 'h': + usage(); + return 0; + default: + usage(); + return 1; + } + } + + if((argc - optind) != 8 && (argc - optind) != 5) + { + usage(); + return 1; + } + + ofile = argv[optind]; + ofp = fopen(ofile, "w"); + if(ofp == NULL) + { + fprintf(stderr, "unable to open file %s\n", ofile); + return 1; + } + + /* + * 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); - /*-------------------------------------------------------------------------+ - | Parse command line arguments and options - +-------------------------------------------------------------------------*/ + optind++; + headerAddr = strtoul(argv[optind], &end, 0); + if(end == argv[optind]) + { + fprintf(stderr, "bad headerAddr %s\n", argv[optind]); + fclose(ofp); + return 1; + } + + if(headerAddr > 0x97e00) + { + fprintf(stderr, "headerAddr is too high 0x%08lx\n", headerAddr); + fclose(ofp); + return 1; + } - { - char opt; - - /* parse command line options */ - while ((opt = getopt(argc, argv, "vh?")) >= 0) - { - argPos++; - switch (opt) - { - case 'v' : verboseFlag = 1; break; - case 'h' : case '?' : helpFlag = 1; break; - } - } - } - - if (helpFlag) - { - fprintf(stderr, "%s\n", UsageMsg); - if (argc == 2) - exit(0); - } - - numImages = (argc - argPos - 2) / 3; - - if (numImages < 1) - { - fprintf(stderr, - "ERROR!!! Not enough command line arguments.\n\n%s\n", - UsageMsg); - exit(1); - } - if (numImages > 15) - { - fprintf(stderr, "ERROR!!! Too many input files.\n\n%s\n", UsageMsg); - exit(1); - } - - newHeader(&hdr); /* initialize hdr */ - - argPos = 1; - - while (argv[argPos][0] == '-') argPos++; /* discard options */ - if(!(outFile = fopen((outFileName = argv[argPos++]), "w"))) - { - fprintf(stderr, - "ERROR!!! While opening file '%s' for output.\n", - outFileName); - exit(1); - } - reserveSpaceHeader(outFile); - - while (argv[argPos][0] == '-') argPos++; /* discard options */ - setLocAddrHeader(&hdr, getNumArg(argv[argPos++])); - - /*-------------------------------------------------------------------------+ - | Parse command line arguments concerning images - +-------------------------------------------------------------------------*/ - - for(i = 0; i < numImages; i++) - { - newImage(&img[i]); - while (argv[argPos][0] == '-') argPos++; /* discard options */ - setImageFile(&img[i], argv[argPos++]); - 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 */ - setExecAddrHeader(&hdr, getLoadAddrImage(&img[0])); - /* boot file execution address is the same as first image's */ - if (verboseFlag) - { - fprintf(stderr, "BootImage file '%s' info:\n\n", outFileName); - fprintHeader(stderr, &hdr); - fprintf(stderr, "\n"); - } - - /*-------------------------------------------------------------------------+ - | Dump images and header to file - +-------------------------------------------------------------------------*/ - - for(i = 0; i < numImages; i++) - { - addImageToHeader(&hdr, &img[i]); - dumpImageToFileAndPad(outFile, &img[i]); - - 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); - - exit(0); -} /* main */ + /* Copy the first 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++; + addr1 = strtoul(argv[optind], &end, 0); + if(end == argv[optind]) + { + fprintf(stderr, "bad image address %s\n", argv[optind]); + fclose(ofp); + return 1; + } + + optind++; + size1 = strtoul(argv[optind], &end, 0); + if(end == argv[optind]) + { + fprintf(stderr, "bad image size %s\n", argv[optind]); + fclose(ofp); + return 1; + } + + + /* 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; +} + + + + + + + + diff --git a/c/src/lib/libbsp/i386/pc386/tools/binpatch.c b/c/src/lib/libbsp/i386/pc386/tools/binpatch.c new file mode 100644 index 0000000000..ab0900702a --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/tools/binpatch.c @@ -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; +} + + + + + + + + + + + + diff --git a/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in b/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in index 2adbda5433..eea0a83229 100644 --- a/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in @@ -8,7 +8,7 @@ VPATH = @srcdir@ RTEMS_ROOT = @top_srcdir@ PROJECT_ROOT = @PROJECT_ROOT@ -BSP_PIECES=startup clock console timer +BSP_PIECES=startup clock console timer pc386dev GENERIC_PIECES= # bummer; have to use $foreach since % pattern subst rules only replace 1x |