Set the "depth" flag on bulk transactions. Since SeaBIOS doesn't use
bandwidth reclamation, without the depth flag the uhci controller will
only transfer one bulk packet per 1 ms frame. This results in a
maximum of 64 bytes per millisecond, which severely limits the
transfer rate.
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
src/hw/usb-uhci.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/hw/usb-uhci.c b/src/hw/usb-uhci.c
index 6dcc340..…
[View More]7ef50d1 100644
--- a/src/hw/usb-uhci.c
+++ b/src/hw/usb-uhci.c
@@ -537,9 +537,9 @@ uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
int transfer = datasize;
if (transfer > maxpacket)
transfer = maxpacket;
- struct uhci_td *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
- , &tds[tdpos % STACKTDS]);
- td->link = (transfer==datasize ? UHCI_PTR_TERM : (u32)nexttd_fl);
+ u32 nexttd = (u32)MAKE_FLATPTR(GET_SEG(SS), &tds[tdpos % STACKTDS]);
+ td->link = (transfer==datasize
+ ? UHCI_PTR_TERM : (nexttd | UHCI_PTR_DEPTH));
td->token = (uhci_explen(transfer) | toggle
| (devaddr << TD_TOKEN_DEVADDR_SHIFT)
| (dir ? USB_PID_IN : USB_PID_OUT));
--
1.9.3
[View Less]
Update the debugging documentation with info on timing debug output
with readserial.py.
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
docs/Debugging.md | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/docs/Debugging.md b/docs/Debugging.md
index d651fc9..1ba56af 100644
--- a/docs/Debugging.md
+++ b/docs/Debugging.md
@@ -34,6 +34,43 @@ To report an issue, please collect the serial boot log with SeaBIOS
set to a debug level of 8 and …
[View More]forward the full log along with a
description of the problem to the SeaBIOS [mailing list](Mailinglist).
+Timing debug messages
+=====================
+
+The SeaBIOS repository has a tool (**scripts/readserial.py**) that can
+timestamp each diagnostic message produced. The timestamps can provide
+some additional information on how long internal processes take. It
+also provides a simple profiling mechanism.
+
+The tool can be used on coreboot builds that have diagnostic messages
+sent to a serial port. Make sure SeaBIOS is configured with
+CONFIG_DEBUG_SERIAL and run the following on the host receiving serial
+output:
+
+`/path/to/seabios/scripts/readserial.py /dev/ttyS0 115200`
+
+Update the above command with the appropriate serial device and baud
+rate.
+
+The tool can also timestamp the messages from the QEMU debug port. To
+use with QEMU run the following:
+
+`mkfifo qemudebugpipe`\
+`qemu -chardev pipe,path=qemudebugpipe,id=seabios -device isa-debugcon,iobase=0x402,chardev=seabios ...`
+
+and then in another session:
+
+`/path/to/seabios/scripts/readserial.py -nf qemudebugpipe`
+
+The mkfifo command only needs to be run once to create the pipe file.
+
+When readserial.py is running, it shows a timestamp with millisecond
+accuracy of the amount of time since the start of the log. If one
+presses the "enter" key in the readserial session it will add a blank
+line to the screen and also reset the time back to zero. The
+readserial.py program also keeps a log of all output in files that
+look like "seriallog-YYYYMMDD_HHMMSS.log".
+
Debugging with gdb on QEMU
==========================
--
1.9.3
[View Less]
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
docs/Developer_Documentation.md | 3 +
docs/Linking_overview.md | 166 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+)
create mode 100644 docs/Linking_overview.md
diff --git a/docs/Developer_Documentation.md b/docs/Developer_Documentation.md
index 1d891e9..d50455d 100644
--- a/docs/Developer_Documentation.md
+++ b/docs/Developer_Documentation.md
@@ -14,6 +14,9 @@ There is also information on …
[View More]the SeaBIOS [Memory Model](Memory Model).
Along with information on SeaBIOS [Execution and code flow](Execution
and code flow).
+A description of the process of linking the final SeaBIOS binary is
+available at [Linking overview](Linking overview).
+
To debug SeaBIOS and report problems see SeaBIOS
[debugging](Debugging).
diff --git a/docs/Linking_overview.md b/docs/Linking_overview.md
new file mode 100644
index 0000000..fb938b6
--- /dev/null
+++ b/docs/Linking_overview.md
@@ -0,0 +1,166 @@
+This page describes the process that the SeaBIOS build uses to link
+the compiled code into the final binary objects.
+
+Unfortunately, the SeaBIOS linking phase is complex. This complexity
+is due to several unusual requirements:
+
+* Some BIOS entry points must reside at specific hardcoded memory
+ locations. The build must support positioning code and variables at
+ specific locations.
+* In order to support multiple [memory models](Memory Model) the same
+ C code can be complied in three modes (16bit mode, 32bit segmented
+ mode, and 32bit "flat" mode). Binary code from these three modes
+ must be able to co-exist and on occasion reference each other.
+* There is a finite amount of memory available to the BIOS. The build
+ will attempt to weed out unused code and variables from the final
+ binary. It also supports self-relocation of one-time initialization
+ code.
+
+Code layout
+===========
+
+To support the unusual build requirements, several
+[gcc](http://en.wikipedia.org/wiki/GNU_Compiler_Collection) compiler
+options are used. The "-ffunction-sections" and "-fdata-sections"
+flags instruct the compiler to place each variable and function into
+its own
+[ELF](http://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
+section.
+
+The C code is compiled three times into three separate objects for
+each of the major supported [memory models](Memory Model):
+**code16.o**, **code32seg.o**, and **code32flat.o**. Information on
+the sections and symbols of these three objects are extracted (using
+**objdump**) and passed in to the **scripts/layoutrom.py** python
+script. This script analyzes this information and produces gnu
+[ld](http://en.wikipedia.org/wiki/GNU_linker) "linker scripts" which
+provide precise location information to the linker. These linker
+scripts are then used during the link phase which produces a **rom.o**
+object containing all the code.
+
+Fixed location entry points
+---------------------------
+
+The build supports placing code entry points and variables at fixed
+memory locations. This support is required in order to support the
+legacy BIOS standards. For example, a program might execute an "int
+0x15" to request system information from the BIOS, but another old
+program might use "ljmpw $0xf000, $0xf859" instead. Both must provide
+the same results and so the build must position the 0x15 interrupt
+entry point in physical memory at 0xff859.
+
+This support is accomplished by placing the given code/variables into
+ELF sections that have a name containing the substring
+".fixedaddr.0x1234" (where 0x1234 is the desired address). For
+variables in C code this is accomplished by marking the variables with
+the VARFSEGFIXED(0x1234) macro. For assembler entry points the ORG
+macro is used (see **romlayout.S**).
+
+During the build, the **layoutrom.py** script will detect sections
+that contain the ".fixedaddr." substring and will arrange for the
+final linker scripts to specify the desired address for the given
+section.
+
+Due to the sparse nature of these fixed address sections, the
+layoutrom.py script will also arrange to pack in other unrelated 16bit
+code into the free space between fixed address sections (see
+layoutrom.py:fitSections()). This maximizes the space available and
+reduces the overall size of the final binary.
+
+C code in three modes
+---------------------
+
+SeaBIOS must support multiple [memory models](Memory Model). This is
+accomplished by compiling the C code three separate times into three
+separate objects.
+
+The C code within a mode must not accidentally call a C function in
+another mode, but multiple modes must all access the same single copy
+of global variables. Further, it is occasionally necessary for the C
+code in one mode to obtain the address of C code in another mode.
+
+In order to use the same global variables between all modes, the
+layoutrom.py script will detect references to global variables and
+emit specific symbol definitions for those global variables in the
+linker scripts so that all references use the same physical memory
+address (see layoutrom.py:outXRefs()).
+
+To ensure C code does not accidentally call C code compiled in a
+different mode, the build will ensure the symbols for C code in each
+mode are isolated from each other during the linking stage. To support
+those situations where an address of a C function in another mode is
+required the build supports symbols with a special "\_cfuncX_"
+prefix. The layoutrom.py script detects these references and will emit
+a corresponding symbol definitions in the linker script that points to
+the C code of the specified mode. This is typically seen with code
+like:
+
+`extern void _cfunc32flat_process_op(void);`\
+`return call32(_cfunc32flat_process_op, 0, 0);`
+
+In the above example, when the build finds the symbol
+"\_cfunc32flat_process_op" it will emit that symbol with the physical
+address of the 32bit "flat" version of the process_op() C function.
+
+Build garbage collection
+------------------------
+
+To reduce the overall size of the final SeaBIOS binary the build
+supports automatically weeding out of unused code and variables. This
+is done with two separate processes: when supported the gcc
+"-fwhole-program" compilation flag is used, and the layoutrom.py
+script checks for unreferenced ELF sections. The layoutrom.py script
+builds the final linker scripts with only referenced ELF sections, and
+thus unreferenced sections are weeded out from the final objects.
+
+When writing C code, it is necessary to mark C functions with the
+VISIBLE16, VISIBLE32SEG, or VISIBLE32FLAT macros if the functions are
+ever referenced from assembler code. These macros ensure the
+corresponding C function is emitted by the C compiler when compiling
+for the given memory mode. These macros, however, do not affect the
+layoutrom.py reference check, so even a function decorated with one of
+the above macros can be weeded out from the final object if it is
+never referenced.
+
+Code relocation
+---------------
+
+To further reduce the runtime memory size of the BIOS, the build
+supports runtime self-relocation. Normally SeaBIOS is loaded into
+memory in the memory region at 0xC0000-0x100000. This is convenient
+for initial binary deployment, but the space competes with memory
+requirements for Option ROMs, BIOS tables, and runtime storage. By
+default, SeaBIOS will self-relocate its one-time initialization code
+to free up space in this region.
+
+To support this feature, the build attempts to automatically detect
+which C code is exclusively initialization phase code (see
+layoutrom.py:checkRuntime()). It does this by finding all functions
+decorated with the VISIBLE32INIT macro and all functions only
+reachable via functions with that macro. These "init only" functions
+are then grouped together and their location and size is stored in the
+binary for the runtime code to relocate (see post.c:reloc_preinit()).
+
+The build also locates all cross section code references along with
+all absolute memory addresses in the "init only" code. These addresses
+need to be modified with the new run-time address in order for the
+code to successfully run at a new address. The build finds the
+location of the addresses (see layoutrom.py:getRelocs()) and stores
+the information in the final binary.
+
+Final binary checks
+===================
+
+At the conclusion of the main linking stage, the code is contained in
+the file **rom.o**. This object file contains all of the assembler
+code, variables, and the C code from all three memory model modes.
+
+At this point the **scripts/checkrom.py** script is run to perform
+final checks on the code. The script performs some sanity checks, it
+may update some tables in the binary, and it reports some size
+information.
+
+After the checkrom.py script is run the final user visible binary is
+produced. The name of the final binary is either **bios.bin**,
+**Csm16.bin**, or **bios.bin.elf** depending on the SeaBIOS build
+requested.
--
1.9.3
[View Less]
On Mon, Dec 29, 2014 at 03:59:47PM +0100, Jenkins Build Host wrote:
> See <http://jenkins.xeni.kraxel.org:8080/job/seabios/142/changes>
>
> Changes:
>
> [kevin] sdcard: Initial support for SD cards on PCI SDHCI controllers on QEMU
[...]
> ROM size (in KB) (ROM_SIZE) [128] 128
[...]
> Version: 1.7.5-125.b142.g2c9870f-20141229_155946-jenkins.xeni.kraxel.org
> Fixed space: 0xe05b-0x10000 total: 8101 slack: 13 Percent slack: 0.2%
> 16bit size: 35196
…
[View More]> 32bit segmented size: 2127
> 32bit flat size: 21109
> 32bit flat init size: 66688
> Lowmem size: 2176
> f-segment var size: 1200
> Linking out/rom16.o
> Stripping out/rom16.strip.o
> Linking out/rom32seg.o
> Stripping out/rom32seg.strip.o
> Linking out/rom.o
> Prepping out/bios.bin.prep
> Error! ROM doesn't fit (132148 > 131072)
> You have to either increate the size (CONFIG_ROM_SIZE)
> or turn off some features (such as hardware support not
> needed) to make it fit. Trying a more recent gcc version
> might work too.
Looks like the 128K test build will need to turn off SDCARD support
(or something similar).
-Kevin
[View Less]
A cdrom boot image could be over 64K in size, but the low level
drivers may not support very large reads. If a large cdrom image is
found, issue multiple reads so that a read request over 64K is never
issued.
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
src/cdrom.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/src/cdrom.c b/src/cdrom.c
index de0e7de..92f34f4 100644
--- a/src/cdrom.c
+++ b/src/cdrom.c
@@ -212,12 +212,21 @@ cdrom_boot(…
[View More]struct drive_s *drive)
CDEmu.device_spec = drive->cntl_id % 2;
// And we read the image in memory
+ nbsectors = DIV_ROUND_UP(nbsectors, 4);
dop.lba = lba;
- dop.count = DIV_ROUND_UP(nbsectors, 4);
dop.buf_fl = MAKE_FLATPTR(boot_segment, 0);
- ret = scsi_process_op(&dop);
- if (ret)
- return 12;
+ while (nbsectors) {
+ int count = nbsectors;
+ if (count > 64*1024/CDROM_SECTOR_SIZE)
+ count = 64*1024/CDROM_SECTOR_SIZE;
+ dop.count = count;
+ ret = scsi_process_op(&dop);
+ if (ret)
+ return 12;
+ nbsectors -= count;
+ dop.lba += count;
+ dop.buf_fl += count*CDROM_SECTOR_SIZE;
+ }
if (media == 0) {
// No emulation requested - return success.
--
1.9.3
[View Less]