Index: projects/make-check-sandbox/sys/boot/arm/at91/libat91/lib.h =================================================================== --- projects/make-check-sandbox/sys/boot/arm/at91/libat91/lib.h (revision 321969) +++ projects/make-check-sandbox/sys/boot/arm/at91/libat91/lib.h (revision 321970) @@ -1,65 +1,65 @@ /*- * Copyright (c) 2006 M. Warner Losh. 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 ``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 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$ */ #ifndef ARM_BOOT_LIB_H #define ARM_BOOT_LIB_H int getc(int); -void putchar(int); -void xputchar(int); -void printf(const char *fmt,...); +int putchar(int); +int xputchar(int); +int printf(const char *fmt,...); /* The following function write eeprom at ee_addr using data */ /* from data_add for size bytes. */ int ReadEEPROM(unsigned eeoff, unsigned char *data_addr, unsigned size); void WriteEEPROM(unsigned eeoff, char *data_addr, unsigned size); void InitEEPROM(void); /* XMODEM protocol */ int xmodem_rx(char *dst); /* */ void start_wdog(int n); void reset(void); /* Delay us */ void Delay(int us); #define ToASCII(x) ((x > 9) ? (x + 'A' - 0xa) : (x + '0')) int p_IsWhiteSpace(char cValue); unsigned p_HexCharValue(char cValue); unsigned p_ASCIIToHex(const char *buf); unsigned p_ASCIIToDec(const char *buf); void p_memset(char *buffer, char value, int size); int p_strlen(const char *buffer); char *strcpy(char *to, const char *from); void memcpy(void *to, const void *from, unsigned size); int p_memcmp(const char *to, const char *from, unsigned size); int strcmp(const char *to, const char *from); #endif Index: projects/make-check-sandbox/sys/boot/arm/at91/libat91/printf.c =================================================================== --- projects/make-check-sandbox/sys/boot/arm/at91/libat91/printf.c (revision 321969) +++ projects/make-check-sandbox/sys/boot/arm/at91/libat91/printf.c (revision 321970) @@ -1,70 +1,71 @@ /*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * Copyright (c) 2006 M. Warner Losh * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. * * $FreeBSD$ */ #include #include "lib.h" -void +int printf(const char *fmt,...) { va_list ap; const char *hex = "0123456789abcdef"; char buf[10]; + const char *fmt_orig = fmt; char *s; unsigned u; int c; va_start(ap, fmt); while ((c = *fmt++)) { if (c == '%') { c = *fmt++; switch (c) { case 'c': xputchar(va_arg(ap, int)); continue; case 's': for (s = va_arg(ap, char *); *s; s++) xputchar(*s); continue; case 'd': /* A lie, always prints unsigned */ case 'u': u = va_arg(ap, unsigned); s = buf; do *s++ = '0' + u % 10U; while (u /= 10U); dumpbuf:; while (--s >= buf) xputchar(*s); continue; case 'x': u = va_arg(ap, unsigned); s = buf; do *s++ = hex[u & 0xfu]; while (u >>= 4); goto dumpbuf; } } xputchar(c); } va_end(ap); - return; + return (int)(fmt - fmt_orig); } Index: projects/make-check-sandbox/sys/boot/arm/at91/libat91/putchar.c =================================================================== --- projects/make-check-sandbox/sys/boot/arm/at91/libat91/putchar.c (revision 321969) +++ projects/make-check-sandbox/sys/boot/arm/at91/libat91/putchar.c (revision 321970) @@ -1,62 +1,64 @@ /*- * Copyright (c) 2006 M. Warner Losh. 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 ``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 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. * * This software is derived from software provided by kwikbyte without * copyright as follows: * * No warranty, expressed or implied, is included with this software. It is * provided "AS IS" and no warranty of any kind including statutory or aspects * relating to merchantability or fitness for any purpose is provided. All * intellectual property rights of others is maintained with the respective * owners. This software is not copyrighted and is intended for reference * only. * * $FreeBSD$ */ #include "at91rm9200.h" #include "at91rm9200_lowlevel.h" #include "lib.h" /* - * void putchar(int ch) + * int putchar(int ch) * Writes a character to the DBGU port. It assumes that DBGU has * already been initialized. */ -void +int putchar(int ch) { AT91PS_USART pUSART = (AT91PS_USART)AT91C_BASE_DBGU; while (!(pUSART->US_CSR & AT91C_US_TXRDY)) continue; pUSART->US_THR = (ch & 0xFF); + return (1); } -void +int xputchar(int ch) { - if (ch == '\n') - putchar('\r'); - putchar(ch); + if (ch == '\n') + putchar('\r'); + putchar(ch); + return (ch == '\n' ? 2 : 1); } Index: projects/make-check-sandbox/sys/boot/arm/ixp425/boot2/ixp425_board.c =================================================================== --- projects/make-check-sandbox/sys/boot/arm/ixp425/boot2/ixp425_board.c (revision 321969) +++ projects/make-check-sandbox/sys/boot/arm/ixp425/boot2/ixp425_board.c (revision 321970) @@ -1,771 +1,773 @@ /*- * Copyright (c) 2008 John Hay. 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 ``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 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include "lib.h" #include "cf_ata.h" #include #include #include struct board_config { const char *desc; int (*probe)(int boardtype_hint); void (*init)(void); }; /* set of registered boards */ SET_DECLARE(boards, struct board_config); #define BOARD_CONFIG(name, _desc) \ static struct board_config name##config = { \ .desc = _desc, \ .probe = name##_probe, \ .init = name##_init, \ }; \ DATA_SET(boards, name##config) static u_int cputype; #define cpu_is_ixp43x() (cputype == CPU_ID_IXP435) static u_int8_t *ubase; static u_int8_t uart_getreg(u_int8_t *, int); static void uart_setreg(u_int8_t *, int, u_int8_t); static void cf_init(void); static void cf_clr(void); #ifdef DEBUG #define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__) #else #define DPRINTF(fmt, ...) #endif const char * board_init(void) { struct board_config **pbp; cputype = cpu_id() & CPU_ID_CPU_MASK; SET_FOREACH(pbp, boards) /* XXX pass down redboot board type */ if ((*pbp)->probe(0)) { (*pbp)->init(); return (*pbp)->desc; } /* XXX panic, unknown board type */ return "???"; } /* * This should be called just before starting the kernel. This is so * that one can undo incompatible hardware settings. */ void clr_board(void) { cf_clr(); } /* * General support functions. */ /* * DELAY should delay for the number of microseconds. * The idea is that the inner loop should take 1us, so val is the * number of usecs to delay. */ void DELAY(int val) { volatile int sub; volatile int subsub; sub = val; while(sub) { subsub = 3; while(subsub) subsub--; sub--; } } u_int32_t swap32(u_int32_t a) { return (((a & 0xff) << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) | ((a & 0xff000000) >> 24)); } u_int16_t swap16(u_int16_t val) { return (val << 8) | (val >> 8); } /* * uart related funcs */ static u_int8_t uart_getreg(u_int8_t *bas, int off) { return *((volatile u_int32_t *)(bas + (off << 2))) & 0xff; } static void uart_setreg(u_int8_t *bas, int off, u_int8_t val) { *((volatile u_int32_t *)(bas + (off << 2))) = (u_int32_t)val; } int getc(int seconds) { int c, delay, limit; c = 0; delay = 10000; limit = seconds * 1000000/10000; while ((uart_getreg(ubase, REG_LSR) & LSR_RXRDY) == 0 && --limit) DELAY(delay); if ((uart_getreg(ubase, REG_LSR) & LSR_RXRDY) == LSR_RXRDY) c = uart_getreg(ubase, REG_DATA); return c; } -void +int putchar(int ch) { int delay, limit; delay = 500; limit = 20; while ((uart_getreg(ubase, REG_LSR) & LSR_THRE) == 0 && --limit) DELAY(delay); uart_setreg(ubase, REG_DATA, ch); limit = 40; while ((uart_getreg(ubase, REG_LSR) & LSR_TEMT) == 0 && --limit) DELAY(delay); + return (1); } -void +int xputchar(int ch) { if (ch == '\n') putchar('\r'); putchar(ch); + return (ch == '\n' ? 2 : 1); } void putstr(const char *str) { while(*str) xputchar(*str++); } void puthex8(u_int8_t ch) { const char *hex = "0123456789abcdef"; putchar(hex[ch >> 4]); putchar(hex[ch & 0xf]); } void puthexlist(const u_int8_t *str, int length) { while(length) { puthex8(*str); putchar(' '); str++; length--; } } /* * * CF/IDE functions. * */ struct { u_int64_t dsize; u_int64_t total_secs; u_int8_t heads; u_int8_t sectors; u_int32_t cylinders; u_int32_t *cs1to; u_int32_t *cs2to; u_int8_t *cs1; u_int8_t *cs2; u_int32_t use_lba; u_int32_t use_stream8; u_int32_t debug; u_int8_t status; u_int8_t error; } dskinf; static void cfenable16(void); static void cfdisable16(void); static u_int8_t cfread8(u_int32_t off); static u_int16_t cfread16(u_int32_t off); static void cfreadstream8(void *buf, int length); static void cfreadstream16(void *buf, int length); static void cfwrite8(u_int32_t off, u_int8_t val); static u_int8_t cfaltread8(u_int32_t off); static void cfaltwrite8(u_int32_t off, u_int8_t val); static int cfwait(u_int8_t mask); static int cfaltwait(u_int8_t mask); static int cfcmd(u_int32_t cmd, u_int32_t cylinder, u_int32_t head, u_int32_t sector, u_int32_t count, u_int32_t feature); static void cfreset(void); #ifdef DEBUG static int cfgetparams(void); #endif static void cfprintregs(void); static void cf_init(void) { u_int8_t status; #ifdef DEBUG int rval; #endif /* NB: board init routines setup other parts of dskinf */ dskinf.use_stream8 = 0; dskinf.use_lba = 0; dskinf.debug = 1; DPRINTF("cs1 %x, cs2 %x\n", dskinf.cs1, dskinf.cs2); /* Setup the CF window */ *dskinf.cs1to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN); DPRINTF("t1 %x, ", *dskinf.cs1to); *dskinf.cs2to |= (EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN); DPRINTF("t2 %x\n", *dskinf.cs2to); /* Detect if there is a disk. */ cfwrite8(CF_DRV_HEAD, CF_D_IBM); DELAY(1000); status = cfread8(CF_STATUS); if (status != 0x50) printf("cf-ata0 %x\n", (u_int32_t)status); if (status == 0xff) { printf("cf_ata0: No disk!\n"); return; } cfreset(); if (dskinf.use_stream8) { DPRINTF("setting %d bit mode.\n", 8); cfwrite8(CF_FEATURE, 0x01); /* Enable 8 bit transfers */ cfwrite8(CF_COMMAND, ATA_SETFEATURES); cfaltwait(CF_S_READY); } #ifdef DEBUG rval = cfgetparams(); if (rval) return; #endif dskinf.use_lba = 1; dskinf.debug = 0; } static void cf_clr(void) { cfwrite8(CF_DRV_HEAD, CF_D_IBM); cfaltwait(CF_S_READY); cfwrite8(CF_FEATURE, 0x81); /* Enable 8 bit transfers */ cfwrite8(CF_COMMAND, ATA_SETFEATURES); cfaltwait(CF_S_READY); } static void cfenable16(void) { u_int32_t val; val = *dskinf.cs1to; *dskinf.cs1to = val &~ EXP_BYTE_EN; DELAY(100); #if 0 DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__); #endif } static void cfdisable16(void) { u_int32_t val; DELAY(100); val = *dskinf.cs1to; *dskinf.cs1to = val | EXP_BYTE_EN; #if 0 DPRINTF("%s: cs1 timing reg %x\n", *dskinf.cs1to, __func__); #endif } static u_int8_t cfread8(u_int32_t off) { volatile u_int8_t *vp; vp = (volatile u_int8_t *)(dskinf.cs1 + off); return *vp; } static void cfreadstream8(void *buf, int length) { u_int8_t *lbuf; u_int8_t tmp; lbuf = buf; while (length) { tmp = cfread8(CF_DATA); *lbuf = tmp; #ifdef DEBUG if (dskinf.debug && (length > (512 - 32))) { if ((length % 16) == 0) xputchar('\n'); puthex8(tmp); putchar(' '); } #endif lbuf++; length--; } #ifdef DEBUG if (dskinf.debug) xputchar('\n'); #endif } static u_int16_t cfread16(u_int32_t off) { volatile u_int16_t *vp; vp = (volatile u_int16_t *)(dskinf.cs1 + off); return swap16(*vp); } static void cfreadstream16(void *buf, int length) { u_int16_t *lbuf; length = length / 2; cfenable16(); lbuf = buf; while (length--) { *lbuf = cfread16(CF_DATA); lbuf++; } cfdisable16(); } static void cfwrite8(u_int32_t off, u_int8_t val) { volatile u_int8_t *vp; vp = (volatile u_int8_t *)(dskinf.cs1 + off); *vp = val; } #if 0 static void cfwrite16(u_int32_t off, u_int16_t val) { volatile u_int16_t *vp; vp = (volatile u_int16_t *)(dskinf.cs1 + off); *vp = val; } #endif static u_int8_t cfaltread8(u_int32_t off) { volatile u_int8_t *vp; off &= 0x0f; vp = (volatile u_int8_t *)(dskinf.cs2 + off); return *vp; } static void cfaltwrite8(u_int32_t off, u_int8_t val) { volatile u_int8_t *vp; /* * This is documented in the Intel appnote 302456. */ off &= 0x0f; vp = (volatile u_int8_t *)(dskinf.cs2 + off); *vp = val; } static int cfwait(u_int8_t mask) { u_int8_t status; u_int32_t tout; tout = 0; while (tout <= 5000000) { status = cfread8(CF_STATUS); if (status == 0xff) { printf("%s: master: no status, reselecting\n", __func__); cfwrite8(CF_DRV_HEAD, CF_D_IBM); DELAY(1); status = cfread8(CF_STATUS); } if (status == 0xff) return -1; dskinf.status = status; if (!(status & CF_S_BUSY)) { if (status & CF_S_ERROR) { dskinf.error = cfread8(CF_ERROR); printf("%s: error, status 0x%x error 0x%x\n", __func__, status, dskinf.error); } if ((status & mask) == mask) { DPRINTF("%s: status 0x%x mask 0x%x tout %u\n", __func__, status, mask, tout); return (status & CF_S_ERROR); } } if (tout > 1000) { tout += 1000; DELAY(1000); } else { tout += 10; DELAY(10); } } return -1; } static int cfaltwait(u_int8_t mask) { u_int8_t status; u_int32_t tout; tout = 0; while (tout <= 5000000) { status = cfaltread8(CF_ALT_STATUS); if (status == 0xff) { printf("cfaltwait: master: no status, reselecting\n"); cfwrite8(CF_DRV_HEAD, CF_D_IBM); DELAY(1); status = cfread8(CF_STATUS); } if (status == 0xff) return -1; dskinf.status = status; if (!(status & CF_S_BUSY)) { if (status & CF_S_ERROR) dskinf.error = cfread8(CF_ERROR); if ((status & mask) == mask) { DPRINTF("cfaltwait: tout %u\n", tout); return (status & CF_S_ERROR); } } if (tout > 1000) { tout += 1000; DELAY(1000); } else { tout += 10; DELAY(10); } } return -1; } static int cfcmd(u_int32_t cmd, u_int32_t cylinder, u_int32_t head, u_int32_t sector, u_int32_t count, u_int32_t feature) { if (cfwait(0) < 0) { printf("cfcmd: timeout\n"); return -1; } cfwrite8(CF_FEATURE, feature); cfwrite8(CF_CYL_L, cylinder); cfwrite8(CF_CYL_H, cylinder >> 8); if (dskinf.use_lba) cfwrite8(CF_DRV_HEAD, CF_D_IBM | CF_D_LBA | head); else cfwrite8(CF_DRV_HEAD, CF_D_IBM | head); cfwrite8(CF_SECT_NUM, sector); cfwrite8(CF_SECT_CNT, count); cfwrite8(CF_COMMAND, cmd); return 0; } static void cfreset(void) { u_int8_t status; u_int32_t tout; cfwrite8(CF_DRV_HEAD, CF_D_IBM); DELAY(1); #ifdef DEBUG cfprintregs(); #endif cfread8(CF_STATUS); cfaltwrite8(CF_ALT_DEV_CTR, CF_A_IDS | CF_A_RESET); DELAY(10000); cfaltwrite8(CF_ALT_DEV_CTR, CF_A_IDS); DELAY(10000); cfread8(CF_ERROR); DELAY(3000); for (tout = 0; tout < 310000; tout++) { cfwrite8(CF_DRV_HEAD, CF_D_IBM); DELAY(1); status = cfread8(CF_STATUS); if (!(status & CF_S_BUSY)) break; DELAY(100); } DELAY(1); if (status & CF_S_BUSY) { cfprintregs(); printf("cfreset: Status stayed busy after reset.\n"); } DPRINTF("cfreset: finished, tout %u\n", tout); } #ifdef DEBUG static int cfgetparams(void) { u_int8_t *buf; buf = (u_int8_t *)(0x170000); p_memset((char *)buf, 0, 1024); /* Select the drive. */ cfwrite8(CF_DRV_HEAD, CF_D_IBM); DELAY(1); cfcmd(ATA_ATA_IDENTIFY, 0, 0, 0, 0, 0); if (cfaltwait(CF_S_READY | CF_S_DSC | CF_S_DRQ)) { printf("cfgetparams: ATA_IDENTIFY failed.\n"); return -1; } if (dskinf.use_stream8) cfreadstream8(buf, 512); else cfreadstream16(buf, 512); if (dskinf.debug) cfprintregs(); #if 0 memcpy(&dskinf.ata_params, buf, sizeof(struct ata_params)); dskinf.cylinders = dskinf.ata_params.cylinders; dskinf.heads = dskinf.ata_params.heads; dskinf.sectors = dskinf.ata_params.sectors; printf("dsk0: sec %x, hd %x, cyl %x, stat %x, err %x\n", (u_int32_t)dskinf.ata_params.sectors, (u_int32_t)dskinf.ata_params.heads, (u_int32_t)dskinf.ata_params.cylinders, (u_int32_t)dskinf.status, (u_int32_t)dskinf.error); #endif dskinf.status = cfread8(CF_STATUS); if (dskinf.debug) printf("cfgetparams: ata_params * %x, stat %x\n", (u_int32_t)buf, (u_int32_t)dskinf.status); return 0; } #endif /* DEBUG */ static void cfprintregs(void) { u_int8_t rv; putstr("cfprintregs: regs error "); rv = cfread8(CF_ERROR); puthex8(rv); putstr(", count "); rv = cfread8(CF_SECT_CNT); puthex8(rv); putstr(", sect "); rv = cfread8(CF_SECT_NUM); puthex8(rv); putstr(", cyl low "); rv = cfread8(CF_CYL_L); puthex8(rv); putstr(", cyl high "); rv = cfread8(CF_CYL_H); puthex8(rv); putstr(", drv head "); rv = cfread8(CF_DRV_HEAD); puthex8(rv); putstr(", status "); rv = cfread8(CF_STATUS); puthex8(rv); putstr("\n"); } int avila_read(char *dest, unsigned source, unsigned length) { if (dskinf.use_lba == 0 && source == 0) source++; if (dskinf.debug) printf("avila_read: 0x%x, sect %d num secs %d\n", (u_int32_t)dest, source, length); while (length) { cfwait(CF_S_READY); /* cmd, cyl, head, sect, count, feature */ cfcmd(ATA_READ, (source >> 8) & 0xffff, source >> 24, source & 0xff, 1, 0); cfwait(CF_S_READY | CF_S_DRQ | CF_S_DSC); if (dskinf.use_stream8) cfreadstream8(dest, 512); else cfreadstream16(dest, 512); length--; source++; dest += 512; } return 0; } /* * Gateworks Avila Support. */ static int avila_probe(int boardtype_hint) { volatile u_int32_t *cs; /* * Redboot only configure the chip selects that are needed, so * use that to figure out if it is an Avila or ADI board. The * Avila boards use CS2 and ADI does not. */ cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET); return (*cs != 0); } static void avila_init(void) { /* Config the serial port. RedBoot should do the rest. */ ubase = (u_int8_t *)(IXP425_UART0_HWBASE); dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS1_OFFSET); dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET); dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS1_HWBASE; dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS2_HWBASE; cf_init(); } BOARD_CONFIG(avila, "Gateworks Avila"); /* * Gateworks Cambria Support. */ static int cambria_probe(int boardtype_hint) { return cpu_is_ixp43x(); } static void cambria_init(void) { /* Config the serial port. RedBoot should do the rest. */ ubase = (u_int8_t *)(IXP425_UART0_HWBASE); dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET); dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET); dskinf.cs1 = (u_int8_t *)CAMBRIA_CFSEL0_HWBASE; dskinf.cs2 = (u_int8_t *)CAMBRIA_CFSEL1_HWBASE; cf_init(); } BOARD_CONFIG(cambria, "Gateworks Cambria"); /* * Pronghorn Metro Support. */ static int pronghorn_probe(int boardtype_hint) { volatile u_int32_t *cs; /* * Redboot only configure the chip selects that are needed, so * use that to figure out if it is an Avila or ADI board. The * Avila boards use CS2 and ADI does not. */ cs = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS2_OFFSET); return (*cs == 0); } static void pronghorn_init(void) { /* Config the serial port. RedBoot should do the rest. */ ubase = (u_int8_t *)(IXP425_UART1_HWBASE); dskinf.cs1to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS3_OFFSET); dskinf.cs2to = (u_int32_t *)(IXP425_EXP_HWBASE + EXP_TIMING_CS4_OFFSET); dskinf.cs1 = (u_int8_t *)IXP425_EXP_BUS_CS3_HWBASE; dskinf.cs2 = (u_int8_t *)IXP425_EXP_BUS_CS4_HWBASE; cf_init(); } BOARD_CONFIG(pronghorn, "Pronghorn Metro"); Index: projects/make-check-sandbox/sys/boot/arm/ixp425/boot2/lib.h =================================================================== --- projects/make-check-sandbox/sys/boot/arm/ixp425/boot2/lib.h (revision 321969) +++ projects/make-check-sandbox/sys/boot/arm/ixp425/boot2/lib.h (revision 321970) @@ -1,67 +1,67 @@ /*- * Copyright (c) 2008 John Hay. 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 ``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 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$ */ #ifndef ARM_BOOT_LIB_H #define ARM_BOOT_LIB_H #include #include int main(void); void DELAY(int); int getc(int); -void putchar(int); -void xputchar(int); +int putchar(int); +int xputchar(int); void putstr(const char *); void puthex8(u_int8_t); void puthexlist(const u_int8_t *, int); -void printf(const char *fmt,...); +int printf(const char *fmt,...); void bzero(void *, size_t); char *strcpy(char *to, const char *from); int strcmp(const char *to, const char *from); int p_strlen(const char *); int p_memcmp(const char *, const char *, unsigned); void *memchr(const void *, int, size_t); void memcpy(void *to, const void *from, unsigned size); void *memmem(const void *, size_t, const void *, size_t); void p_memset(char *buffer, char value, int size); #define strlen p_strlen #define memcmp p_memcmp #define memset p_memset u_int16_t swap16(u_int16_t); u_int32_t swap32(u_int32_t); const char *board_init(void); void clr_board(void); int avila_read(char*, unsigned, unsigned); u_int cpu_id(void); #endif /* !ARM_BOOT_LIB_H */ Index: projects/make-check-sandbox/sys/boot/i386/boot2/boot2.c =================================================================== --- projects/make-check-sandbox/sys/boot/i386/boot2/boot2.c (revision 321969) +++ projects/make-check-sandbox/sys/boot/i386/boot2/boot2.c (revision 321970) @@ -1,646 +1,648 @@ /*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "boot2.h" #include "lib.h" #include "paths.h" #include "rbx.h" /* Define to 0 to omit serial support */ #ifndef SERIAL #define SERIAL 1 #endif #define IO_KEYBOARD 1 #define IO_SERIAL 2 #if SERIAL #define DO_KBD (ioctrl & IO_KEYBOARD) #define DO_SIO (ioctrl & IO_SERIAL) #else #define DO_KBD (1) #define DO_SIO (0) #endif #define SECOND 18 /* Circa that many ticks in a second. */ #define ARGS 0x900 #define NOPT 14 #define NDEV 3 #define MEM_BASE 0x12 #define MEM_EXT 0x15 #define DRV_HARD 0x80 #define DRV_MASK 0x7f #define TYPE_AD 0 #define TYPE_DA 1 #define TYPE_MAXHARD TYPE_DA #define TYPE_FD 2 extern uint32_t _end; static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ static const unsigned char flags[NOPT] = { RBX_DUAL, RBX_SERIAL, RBX_ASKNAME, RBX_CDROM, RBX_CONFIG, RBX_KDB, RBX_GDB, RBX_MUTE, RBX_NOINTR, RBX_PAUSE, RBX_QUIET, RBX_DFLTROOT, RBX_SINGLE, RBX_VERBOSE }; static const char *const dev_nm[NDEV] = {"ad", "da", "fd"}; static const unsigned char dev_maj[NDEV] = {30, 4, 2}; static struct dsk { unsigned drive; unsigned type; unsigned unit; uint8_t slice; uint8_t part; unsigned start; int init; } dsk; static char cmd[512], cmddup[512], knamebuf[1024]; static const char *kname; uint32_t opts; static struct bootinfo bootinfo; #if SERIAL static int comspeed = SIOSPD; static uint8_t ioctrl = IO_KEYBOARD; #endif int main(void); void exit(int); static void load(void); static int parse(void); static int dskread(void *, unsigned, unsigned); -static void printf(const char *,...); -static void putchar(int); +static int printf(const char *,...); +static int putchar(int); static int drvread(void *, unsigned, unsigned); static int keyhit(unsigned); static int xputc(int); static int xgetc(int); static inline int getc(int); static void memcpy(void *, const void *, int); static void memcpy(void *dst, const void *src, int len) { const char *s = src; char *d = dst; while (len--) *d++ = *s++; } static inline int strcmp(const char *s1, const char *s2) { for (; *s1 == *s2 && *s1; s1++, s2++); return (unsigned char)*s1 - (unsigned char)*s2; } #define UFS_SMALL_CGBASE #include "ufsread.c" static int xfsread(ufs_ino_t inode, void *buf, size_t nbyte) { if ((size_t)fsread(inode, buf, nbyte) != nbyte) { printf("Invalid %s\n", "format"); return -1; } return 0; } static inline void getstr(void) { char *s; int c; s = cmd; for (;;) { switch (c = xgetc(0)) { case 0: break; case '\177': case '\b': if (s > cmd) { s--; printf("\b \b"); } break; case '\n': case '\r': *s = 0; return; default: if (s - cmd < sizeof(cmd) - 1) *s++ = c; putchar(c); } } } static inline void putc(int c) { v86.addr = 0x10; v86.eax = 0xe00 | (c & 0xff); v86.ebx = 0x7; v86int(); } int main(void) { uint8_t autoboot; ufs_ino_t ino; size_t nbyte; dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base); v86.ctl = V86_FLAGS; v86.efl = PSL_RESERVED_DEFAULT | PSL_I; dsk.drive = *(uint8_t *)PTOV(ARGS); dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; dsk.unit = dsk.drive & DRV_MASK; dsk.slice = *(uint8_t *)PTOV(ARGS + 1) + 1; bootinfo.bi_version = BOOTINFO_VERSION; bootinfo.bi_size = sizeof(bootinfo); /* Process configuration file */ autoboot = 1; if ((ino = lookup(PATH_CONFIG)) || (ino = lookup(PATH_DOTCONFIG))) { nbyte = fsread(ino, cmd, sizeof(cmd) - 1); cmd[nbyte] = '\0'; } if (*cmd) { memcpy(cmddup, cmd, sizeof(cmd)); if (parse()) autoboot = 0; if (!OPT_CHECK(RBX_QUIET)) printf("%s: %s", PATH_CONFIG, cmddup); /* Do not process this command twice */ *cmd = 0; } /* * Try to exec stage 3 boot loader. If interrupted by a keypress, * or in case of failure, try to load a kernel directly instead. */ if (!kname) { kname = PATH_LOADER; if (autoboot && !keyhit(3*SECOND)) { load(); kname = PATH_KERNEL; } } /* Present the user with the boot2 prompt. */ for (;;) { if (!autoboot || !OPT_CHECK(RBX_QUIET)) printf("\nFreeBSD/x86 boot\n" "Default: %u:%s(%u,%c)%s\n" "boot: ", dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, 'a' + dsk.part, kname); if (DO_SIO) sio_flush(); if (!autoboot || keyhit(3*SECOND)) getstr(); else if (!autoboot || !OPT_CHECK(RBX_QUIET)) putchar('\n'); autoboot = 0; if (parse()) putchar('\a'); else load(); } } /* XXX - Needed for btxld to link the boot2 binary; do not remove. */ void exit(int x) { } static void load(void) { union { struct exec ex; Elf32_Ehdr eh; } hdr; static Elf32_Phdr ep[2]; static Elf32_Shdr es[2]; caddr_t p; ufs_ino_t ino; uint32_t addr; int k; uint8_t i, j; if (!(ino = lookup(kname))) { if (!ls) printf("No %s\n", kname); return; } if (xfsread(ino, &hdr, sizeof(hdr))) return; if (N_GETMAGIC(hdr.ex) == ZMAGIC) { addr = hdr.ex.a_entry & 0xffffff; p = PTOV(addr); fs_off = PAGE_SIZE; if (xfsread(ino, p, hdr.ex.a_text)) return; p += roundup2(hdr.ex.a_text, PAGE_SIZE); if (xfsread(ino, p, hdr.ex.a_data)) return; } else if (IS_ELF(hdr.eh)) { fs_off = hdr.eh.e_phoff; for (j = k = 0; k < hdr.eh.e_phnum && j < 2; k++) { if (xfsread(ino, ep + j, sizeof(ep[0]))) return; if (ep[j].p_type == PT_LOAD) j++; } for (i = 0; i < 2; i++) { p = PTOV(ep[i].p_paddr & 0xffffff); fs_off = ep[i].p_offset; if (xfsread(ino, p, ep[i].p_filesz)) return; } p += roundup2(ep[1].p_memsz, PAGE_SIZE); bootinfo.bi_symtab = VTOP(p); if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { fs_off = hdr.eh.e_shoff + sizeof(es[0]) * (hdr.eh.e_shstrndx + 1); if (xfsread(ino, &es, sizeof(es))) return; for (i = 0; i < 2; i++) { *(Elf32_Word *)p = es[i].sh_size; p += sizeof(es[i].sh_size); fs_off = es[i].sh_offset; if (xfsread(ino, p, es[i].sh_size)) return; p += es[i].sh_size; } } addr = hdr.eh.e_entry & 0xffffff; bootinfo.bi_esymtab = VTOP(p); } else { printf("Invalid %s\n", "format"); return; } bootinfo.bi_kernelname = VTOP(kname); bootinfo.bi_bios_dev = dsk.drive; __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), MAKEBOOTDEV(dev_maj[dsk.type], dsk.slice, dsk.unit, dsk.part), 0, 0, 0, VTOP(&bootinfo)); } static int parse() { char *arg = cmd; char *ep, *p, *q; const char *cp; unsigned int drv; int c, i, j; size_t k; while ((c = *arg++)) { if (c == ' ' || c == '\t' || c == '\n') continue; for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); ep = p; if (*p) *p++ = 0; if (c == '-') { while ((c = *arg++)) { if (c == 'P') { if (*(uint8_t *)PTOV(0x496) & 0x10) { cp = "yes"; } else { opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL); cp = "no"; } printf("Keyboard: %s\n", cp); continue; #if SERIAL } else if (c == 'S') { j = 0; while ((unsigned int)(i = *arg++ - '0') <= 9) j = j * 10 + i; if (j > 0 && i == -'0') { comspeed = j; break; } /* Fall through to error below ('S' not in optstr[]). */ #endif } for (i = 0; c != optstr[i]; i++) if (i == NOPT - 1) return -1; opts ^= OPT_SET(flags[i]); } #if SERIAL ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) : OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; if (DO_SIO) { if (sio_init(115200 / comspeed) != 0) ioctrl &= ~IO_SERIAL; } #endif } else { for (q = arg--; *q && *q != '('; q++); if (*q) { drv = -1; if (arg[1] == ':') { drv = *arg - '0'; if (drv > 9) return (-1); arg += 2; } if (q - arg != 2) return -1; for (i = 0; arg[0] != dev_nm[i][0] || arg[1] != dev_nm[i][1]; i++) if (i == NDEV - 1) return -1; dsk.type = i; arg += 3; dsk.unit = *arg - '0'; if (arg[1] != ',' || dsk.unit > 9) return -1; arg += 2; dsk.slice = WHOLE_DISK_SLICE; if (arg[1] == ',') { dsk.slice = *arg - '0' + 1; if (dsk.slice > NDOSPART + 1) return -1; arg += 2; } if (arg[1] != ')') return -1; dsk.part = *arg - 'a'; if (dsk.part > 7) return (-1); arg += 2; if (drv == -1) drv = dsk.unit; dsk.drive = (dsk.type <= TYPE_MAXHARD ? DRV_HARD : 0) + drv; dsk_meta = 0; } k = ep - arg; if (k > 0) { if (k >= sizeof(knamebuf)) return -1; memcpy(knamebuf, arg, k + 1); kname = knamebuf; } } arg = p; } return 0; } static int dskread(void *buf, unsigned lba, unsigned nblk) { struct dos_partition *dp; struct disklabel *d; char *sec; unsigned i; uint8_t sl; const char *reason; if (!dsk_meta) { sec = dmadat->secbuf; dsk.start = 0; if (drvread(sec, DOSBBSECTOR, 1)) return -1; dp = (void *)(sec + DOSPARTOFF); sl = dsk.slice; if (sl < BASE_SLICE) { for (i = 0; i < NDOSPART; i++) if (dp[i].dp_typ == DOSPTYP_386BSD && (dp[i].dp_flag & 0x80 || sl < BASE_SLICE)) { sl = BASE_SLICE + i; if (dp[i].dp_flag & 0x80 || dsk.slice == COMPATIBILITY_SLICE) break; } if (dsk.slice == WHOLE_DISK_SLICE) dsk.slice = sl; } if (sl != WHOLE_DISK_SLICE) { if (sl != COMPATIBILITY_SLICE) dp += sl - BASE_SLICE; if (dp->dp_typ != DOSPTYP_386BSD) { reason = "slice"; goto error; } dsk.start = dp->dp_start; } if (drvread(sec, dsk.start + LABELSECTOR, 1)) return -1; d = (void *)(sec + LABELOFFSET); if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) { if (dsk.part != RAW_PART) { reason = "label"; goto error; } } else { if (!dsk.init) { if (d->d_type == DTYPE_SCSI) dsk.type = TYPE_DA; dsk.init++; } if (dsk.part >= d->d_npartitions || !d->d_partitions[dsk.part].p_size) { reason = "partition"; goto error; } dsk.start += d->d_partitions[dsk.part].p_offset; dsk.start -= d->d_partitions[RAW_PART].p_offset; } } return drvread(buf, dsk.start + lba, nblk); error: printf("Invalid %s\n", reason); return -1; } -static void +static int printf(const char *fmt,...) { va_list ap; static char buf[10]; + const char *fmt_orig = fmt; char *s; unsigned u; int c; va_start(ap, fmt); while ((c = *fmt++)) { if (c == '%') { c = *fmt++; switch (c) { case 'c': putchar(va_arg(ap, int)); continue; case 's': for (s = va_arg(ap, char *); *s; s++) putchar(*s); continue; case 'u': u = va_arg(ap, unsigned); s = buf; do *s++ = '0' + u % 10U; while (u /= 10U); while (--s >= buf) putchar(*s); continue; } } putchar(c); } va_end(ap); - return; + return (int)(fmt - fmt_orig); } -static void +static int putchar(int c) { if (c == '\n') xputc('\r'); xputc(c); + return (c == '\n' ? 2 : 1); } static int drvread(void *buf, unsigned lba, unsigned nblk) { static unsigned c = 0x2d5c7c2f; if (!OPT_CHECK(RBX_QUIET)) { xputc(c = c << 8 | c >> 24); xputc('\b'); } v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; v86.addr = XREADORG; /* call to xread in boot1 */ v86.es = VTOPSEG(buf); v86.eax = lba; v86.ebx = VTOPOFF(buf); v86.ecx = lba >> 16; v86.edx = nblk << 8 | dsk.drive; v86int(); v86.ctl = V86_FLAGS; if (V86_CY(v86.efl)) { printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); return -1; } return 0; } static int keyhit(unsigned ticks) { uint32_t t0, t1; if (OPT_CHECK(RBX_NOINTR)) return 0; t0 = 0; for (;;) { if (xgetc(1)) return 1; t1 = *(uint32_t *)PTOV(0x46c); if (!t0) t0 = t1; if ((uint32_t)(t1 - t0) >= ticks) return 0; } } static int xputc(int c) { if (DO_KBD) putc(c); if (DO_SIO) sio_putc(c); return c; } static int getc(int fn) { v86.addr = 0x16; v86.eax = fn << 8; v86int(); return fn == 0 ? v86.eax & 0xff : !V86_ZR(v86.efl); } static int xgetc(int fn) { if (OPT_CHECK(RBX_NOINTR)) return 0; for (;;) { if (DO_KBD && getc(1)) return fn ? 1 : getc(0); if (DO_SIO && sio_ischar()) return fn ? 1 : sio_getc(); if (fn) return 0; } } Index: projects/make-check-sandbox =================================================================== --- projects/make-check-sandbox (revision 321969) +++ projects/make-check-sandbox (revision 321970) Property changes on: projects/make-check-sandbox ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r321968-321969