From 5d18fb057a9158336a79953b88d481c74c6eb0ae Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Sat, 27 Jun 1998 18:51:49 +0000 Subject: PC386 BSP enhancements from Aleksey Romanov (Quality Quorum ). 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 --- c/src/lib/libbsp/i386/pc386/Makefile.in | 2 +- c/src/lib/libbsp/i386/pc386/bsp_specs | 2 +- c/src/lib/libbsp/i386/pc386/console/console.c | 346 ++++++++++---- c/src/lib/libbsp/i386/pc386/console/inch.c | 44 +- c/src/lib/libbsp/i386/pc386/console/outch.c | 14 +- c/src/lib/libbsp/i386/pc386/include/Makefile.in | 3 +- c/src/lib/libbsp/i386/pc386/include/bsp.h | 22 +- c/src/lib/libbsp/i386/pc386/start/start.s | 2 +- c/src/lib/libbsp/i386/pc386/startup/bspstart.c | 2 + c/src/lib/libbsp/i386/pc386/startup/exit.c | 49 +- c/src/lib/libbsp/i386/pc386/startup/ldsegs.s | 4 +- c/src/lib/libbsp/i386/pc386/tools/Makefile.in | 17 +- c/src/lib/libbsp/i386/pc386/tools/bin2boot.c | 586 ++++++++++++++++-------- c/src/lib/libbsp/i386/pc386/tools/binpatch.c | 168 +++++++ c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in | 2 +- 15 files changed, 950 insertions(+), 313 deletions(-) create mode 100644 c/src/lib/libbsp/i386/pc386/tools/binpatch.c (limited to 'c/src/lib/libbsp/i386') 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 +#include #include #include #include +#include +#include + +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 - #include +#include + +/*-------------------------------------------------------------------------+ + | 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 #include +#include +#include -/*-------------------------------------------------------------------------+ -| Constants -+--------------------------------------------------------------------------*/ - -#define MAX_IMAGES 15 - -/*-------------------------------------------------------------------------+ -| Global Variables -+--------------------------------------------------------------------------*/ - -// Help message for users -const char UsageMsg[] = "\ -Usage: bin2boot \\\n\ - [ ][...][-v][-h][-?]\n\ -\n\ - : output file name (mandatory)\n\ - : location address in memory of image header (mandatory)\n\ - : name of Xth input file\n\ - : start address of Xth image\n\ - : 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 and is mandatory!\n\ -, and 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] \n"); + printf(" [ ]\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 +#include + +/* + * This function will patch binary file + */ + + +static char buf[512]; + +static void +usage(void) +{ + printf("usage: binpatch [-h] " + "[ [ []]]\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(" - output file\n"); + printf(" - input ifile\n"); + printf(" - relocation address of image\n"); + printf(" - offset of patch, offset in file is at off - reloc\n"); + printf(" - byte 0 of patch\n"); + printf(" - byte 1 of patch\n"); + printf(" - byte 1 of patch\n"); + printf(" - 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 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 off && cnt < (off + patchLen)) + { + /* Perform patch */ + for(i=cnt-off; i