This review aims at introducing ubldr (loader with U-Boot interface) for MIPS

(32 and 64-bit, LE and BE).
The changes were tested with QEMU's 'mips' target.

Most of the implementation was lifted from the ARM version, the appropriate
MIPS-specific things were implemented.

With these changes I am able to go all the way through the u-boot->ubldr->kernel
boot chain in QEMU on all combinations of bit-ness and endian-ness.

For the tests I've used FAT32 disk images (as FAT32 is supported by U-boot),
which include /boot/kernel/kernel and /boot/kernel/ubldr.bin

In U-boot I do:
fatload ide 0 <LOAD_ADDR> /boot/kernel/ubldr.bin; go <LOAD_ADDR>
where LOAD_ADDR is 80800000 for 32-bit and ffffffff80800000 for 64-bit

Then it's the usual ubldr that takes over and loads and starts a kernel.

Approved by:	adrian (mentor)
Sponsored by:	Smartcom - Bulgaria AD
Differential Revision:	https://reviews.freebsd.org/D5313
This commit is contained in:
Stanislav Galabov 2016-02-29 07:47:04 +00:00
parent b981b8bd86
commit a1b701d82b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=296183
9 changed files with 540 additions and 1 deletions

View File

@ -3,3 +3,5 @@
.if ${MK_FDT} != "no"
SUBDIR+= fdt
.endif
SUBDIR+= uboot

View File

@ -1,12 +1,14 @@
# $FreeBSD$
SUBDIR= uboot
#
# The BERI boot loader port works only on 64-bit MIPS; not a hard port to
# 32-bit if someone is interested. Build on all 64-bit MIPS platforms to
# ensure it gets adequate build-test coverage.
#
.if ${MACHINE_ARCH} == "mips64"
SUBDIR= beri
SUBDIR+= beri
.endif
.include <bsd.subdir.mk>

View File

@ -0,0 +1,165 @@
# $FreeBSD$
.include <src.opts.mk>
FILES= ubldr
NEWVERSWHAT= "U-Boot loader" ${MACHINE_ARCH}
BINDIR?= /boot
INSTALLFLAGS= -b
WARNS?= 1
# Address at which ubldr will be loaded.
# This varies for different boards and SOCs.
UBLDR_LOADADDR?= 0xffffffff80800000
# Architecture-specific loader code
SRCS= start.S conf.c vers.c
.if !defined(LOADER_NO_DISK_SUPPORT)
LOADER_DISK_SUPPORT?= yes
.else
LOADER_DISK_SUPPORT= no
.endif
LOADER_MSDOS_SUPPORT?= yes
LOADER_UFS_SUPPORT?= yes
LOADER_CD9660_SUPPORT?= no
LOADER_EXT2FS_SUPPORT?= no
.if ${MK_NAND} != "no"
LOADER_NANDFS_SUPPORT?= yes
.else
LOADER_NANDFS_SUPPORT?= no
.endif
LOADER_NET_SUPPORT?= yes
LOADER_NFS_SUPPORT?= yes
LOADER_TFTP_SUPPORT?= no
LOADER_GZIP_SUPPORT?= no
LOADER_BZIP2_SUPPORT?= no
.if ${MK_FDT} != "no"
LOADER_FDT_SUPPORT= yes
.else
LOADER_FDT_SUPPORT= no
.endif
.if ${LOADER_DISK_SUPPORT} == "yes"
CFLAGS+= -DLOADER_DISK_SUPPORT
.endif
.if ${LOADER_MSDOS_SUPPORT} == "yes"
CFLAGS+= -DLOADER_MSDOS_SUPPORT
.endif
.if ${LOADER_UFS_SUPPORT} == "yes"
CFLAGS+= -DLOADER_UFS_SUPPORT
.endif
.if ${LOADER_CD9660_SUPPORT} == "yes"
CFLAGS+= -DLOADER_CD9660_SUPPORT
.endif
.if ${LOADER_EXT2FS_SUPPORT} == "yes"
CFLAGS+= -DLOADER_EXT2FS_SUPPORT
.endif
.if ${LOADER_NANDFS_SUPPORT} == "yes"
CFLAGS+= -DLOADER_NANDFS_SUPPORT
.endif
.if ${LOADER_GZIP_SUPPORT} == "yes"
CFLAGS+= -DLOADER_GZIP_SUPPORT
.endif
.if ${LOADER_BZIP2_SUPPORT} == "yes"
CFLAGS+= -DLOADER_BZIP2_SUPPORT
.endif
.if ${LOADER_NET_SUPPORT} == "yes"
CFLAGS+= -DLOADER_NET_SUPPORT
.endif
.if ${LOADER_NFS_SUPPORT} == "yes"
CFLAGS+= -DLOADER_NFS_SUPPORT
.endif
.if ${LOADER_TFTP_SUPPORT} == "yes"
CFLAGS+= -DLOADER_TFTP_SUPPORT
.endif
.if ${LOADER_FDT_SUPPORT} == "yes"
CFLAGS+= -I${.CURDIR}/../../fdt
CFLAGS+= -I${.OBJDIR}/../../fdt
CFLAGS+= -DLOADER_FDT_SUPPORT
LIBUBOOT_FDT= ${.OBJDIR}/../../uboot/fdt/libuboot_fdt.a
LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
.endif
CFLAGS+= -DNETIF_OPEN_CLOSE_ONCE
.if ${MK_FORTH} != "no"
# Enable BootForth
BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl
.if ${MACHINE_ARCH} == "mips64" || ${MACHINE_ARCH} == "mips64el"
CFLAGS+= -I${.CURDIR}/../../ficl/mips64
.else
CFLAGS+= -I${.CURDIR}/../../ficl/mips
.endif
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
.endif
# Always add MI sources
.PATH: ${.CURDIR}/../../common
.include "${.CURDIR}/../../common/Makefile.inc"
CFLAGS+= -I${.CURDIR}/../../common
CFLAGS+= -I.
CLEANFILES+= vers.c loader.help
CFLAGS+= -ffreestanding -msoft-float -g
LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.${MACHINE_CPUARCH}
# Pull in common loader code
.PATH: ${.CURDIR}/../../uboot/common
.include "${.CURDIR}/../../uboot/common/Makefile.inc"
CFLAGS+= -I${.CURDIR}/../../uboot/common
# U-Boot standalone support library
LIBUBOOT= ${.OBJDIR}/../../uboot/lib/libuboot.a
CFLAGS+= -I${.CURDIR}/../../uboot/lib
CFLAGS+= -I${.OBJDIR}/../../uboot/lib
# where to get libstand from
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
LIBSTAND= ${.OBJDIR}/../../../../lib/libstand/libstand.a
# clang doesn't understand %D as a specifier to printf
#NO_WERROR.clang=
#NO_WERROR=
DPADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBUBOOT_FDT} ${LIBSTAND}
LDADD= ${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBUBOOT_FDT} ${LIBSTAND}
OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
loader.help: help.common help.uboot ${.CURDIR}/../../fdt/help.fdt
cat ${.ALLSRC} | \
awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET}
ldscript.abs:
echo "UBLDR_LOADADDR = ${UBLDR_LOADADDR};" >${.TARGET}
ldscript.pie:
echo "UBLDR_LOADADDR = 0;" >${.TARGET}
ubldr: ${OBJS} ldscript.abs ${.CURDIR}/ldscript.${MACHINE_CPUARCH} ${DPADD}
${CC} ${CFLAGS} -T ldscript.abs ${LDFLAGS} \
-o ${.TARGET} ${OBJS} ${LDADD}
${OBJCOPY} -S -O binary ubldr ubldr.bin
CLEANFILES+= ldscript.abs ldscript.pie ubldr ubldr.pie ubldr.bin
.if !defined(LOADER_ONLY)
.PATH: ${.CURDIR}/../../forth
.include "${.CURDIR}/../../forth/Makefile.inc"
# Install loader.rc.
FILES+= loader.rc
# Put sample menu.rc on disk but don't enable it by default.
FILES+= menu.rc
FILESNAME_menu.rc= menu.rc.sample
.endif
.include <bsd.stand.mk>
.include <bsd.prog.mk>

115
sys/boot/mips/uboot/conf.c Normal file
View File

@ -0,0 +1,115 @@
/*-
* Copyright (c) 2008 Semihalf, Rafal Jaworowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include "bootstrap.h"
#include "libuboot.h"
#if defined(LOADER_NET_SUPPORT)
#include "dev_net.h"
#endif
struct devsw *devsw[] = {
#if defined(LOADER_DISK_SUPPORT) || defined(LOADER_CD9660_SUPPORT)
&uboot_storage,
#endif
#if defined(LOADER_NET_SUPPORT)
&netdev,
#endif
NULL
};
struct fs_ops *file_system[] = {
#if defined(LOADER_MSDOS_SUPPORT)
&dosfs_fsops,
#endif
#if defined(LOADER_UFS_SUPPORT)
&ufs_fsops,
#endif
#if defined(LOADER_CD9660_SUPPORT)
&cd9660_fsops,
#endif
#if defined(LOADER_EXT2FS_SUPPORT)
&ext2fs_fsops,
#endif
#if defined(LOADER_NANDFS_SUPPORT)
&nandfs_fsops,
#endif
#if defined(LOADER_NFS_SUPPORT)
&nfs_fsops,
#endif
#if defined(LOADER_TFTP_SUPPORT)
&tftp_fsops,
#endif
#if defined(LOADER_GZIP_SUPPORT)
&gzipfs_fsops,
#endif
#if defined(LOADER_BZIP2_SUPPORT)
&bzipfs_fsops,
#endif
NULL
};
struct netif_driver *netif_drivers[] = {
#if defined(LOADER_NET_SUPPORT)
&uboot_net,
#endif
NULL,
};
struct file_format *file_formats[] = {
&uboot_elf,
NULL
};
extern struct console uboot_console;
struct console *consoles[] = {
&uboot_console,
NULL
};
void
abort(void)
{
printf("error: loader abort\n");
while (1);
}
void
longjmperror(void)
{
printf("error: loader longjmp error\n");
while (1);
}
int debug = 1;

View File

@ -0,0 +1,27 @@
$FreeBSD$
###############################################################################
# Tubenv DShow or import U-Boot environment variables
ubenv <import | show> [varname ...]
Display U-Boot environment variables, or import them into the
loader environment (which makes them available in the kernel).
###############################################################################
# Tubenv Simport DImport U-Boot env vars
ubenv import [varname ...]
If no variable names are specified, all U-Boot environment
variables are imported. Each variable is prefixed with "uboot."
to avoid any possible conflicts with loader or kernel variables.
###############################################################################
# Tubenv Sshow DShow U-Boot env vars
ubenv show [varname ...]
If no variable names are specified, all U-Boot environment
variables are shown.

View File

@ -0,0 +1,135 @@
/* $FreeBSD$ */
OUTPUT_ARCH(mips)
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
/*. = UBLDR_LOADADDR + SIZEOF_HEADERS;*/
. = UBLDR_LOADADDR;
.text :
{
start.o(.text*)
*(EXCLUDE_FILE (start.o) .text*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0
_etext = .;
PROVIDE (etext = .);
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.text :
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rela.data :
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rela.rodata :
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rela.got : { *(.rela.got) }
.rela.got1 : { *(.rela.got1) }
.rela.got2 : { *(.rela.got2) }
.rela.ctors : { *(.rela.ctors) }
.rela.dtors : { *(.rela.dtors) }
.rela.init : { *(.rela.init) }
.rela.fini : { *(.rela.fini) }
.rela.bss : { *(.rela.bss) }
.rela.plt : { *(.rela.plt) }
.rela.sdata : { *(.rela.sdata) }
.rela.sbss : { *(.rela.sbss) }
.rela.sdata2 : { *(.rela.sdata2) }
.rela.sbss2 : { *(.rela.sbss2) }
.init : { *(.init) } =0
.fini : { *(.fini) } =0
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.sdata2 : { *(.sdata2) }
.sbss2 : { *(.sbss2) }
/* Adjust the address for the data segment to the next page up. */
. = ((. + 0x1000) & ~(0x1000 - 1));
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
.got1 : { *(.got1) }
.dynamic : { *(.dynamic) }
/* Put .ctors and .dtors next to the .got2 section, so that the pointers
get relocated with -mrelocatable. Also put in the .fixup pointers.
The current compiler no longer needs this, but keep it around for 2.7.2 */
PROVIDE (_GOT2_START_ = .);
.got2 : { *(.got2) }
PROVIDE (__CTOR_LIST__ = .);
.ctors : { *(.ctors) }
PROVIDE (__CTOR_END__ = .);
PROVIDE (__DTOR_LIST__ = .);
.dtors : { *(.dtors) }
PROVIDE (__DTOR_END__ = .);
PROVIDE (_FIXUP_START_ = .);
.fixup : { *(.fixup) }
PROVIDE (_FIXUP_END_ = .);
PROVIDE (_GOT2_END_ = .);
PROVIDE (_GOT_START_ = .);
.got : { *(.got) }
.got.plt : { *(.got.plt) }
PROVIDE (_GOT_END_ = .);
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
.sbss :
{
PROVIDE (__sbss_start = .);
*(.sbss)
*(.scommon)
*(.dynsbss)
PROVIDE (__sbss_end = .);
}
.plt : { *(.plt) }
.bss :
{
PROVIDE (__bss_start = .);
*(.dynbss)
*(.bss)
*(COMMON)
}
_end = . ;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

View File

@ -0,0 +1,13 @@
# This is defaults/loader.conf for ARM, containing defaults for loader(8).
# Do not modify the contents of this file, instead put your customizations
# into /boot/loader.conf or /boot/loader.conf.local
# $FreeBSD$
autoboot_delay=10
bootfile="kernel" # Kernel name (possibly absolute path)
kernel="kernel" # /boot sub-directory containing kernel and modules
loader_conf_files="/boot/loader.conf /boot/loader.conf.local"
module_path="/boot/kernel;/boot/modules;/boot/dtb"
nextboot_conf="/boot/nextboot.conf"
nextboot_enable="NO"
verbose_loading="NO"

View File

@ -0,0 +1,71 @@
/*-
* Copyright (c) 2016 Stanislav Galabov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <machine/asm.h>
.text
.extern _C_LABEL(main)
.weak _DYNAMIC
/*
* Entry point to the loader that U-Boot passes control to.
*/
ENTRY(_start)
PTR_S sp, uboot_address
j main
nop
END(_start)
/*
* syscall()
*/
ENTRY(syscall)
PTR_S ra, ret_address
PTR_L t9, syscall_ptr
jalr t9
nop
PTR_L ra, ret_address
jr ra
nop
END(syscall)
/*
* Data section
*/
.data
.align 8
.globl syscall_ptr
syscall_ptr:
.dword 0
.globl uboot_address
uboot_address:
.dword 0
ret_address:
.dword 0

View File

@ -0,0 +1,9 @@
$FreeBSD$
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
file is important. Make sure the current version number is on line 6.
1.2: Extended with NAND FS support.
1.1: Flattened Device Tree blob support.
1.0: Added storage support. Booting from HDD, USB, etc. is now possible.
0.5: Initial U-Boot/arm version (netbooting only).