diff --git a/payloads/libpayload/include/libpayload.h b/payloads/libpayload/include/libpayload.h index 781a41d354..c3ca123f1f 100644 --- a/payloads/libpayload/include/libpayload.h +++ b/payloads/libpayload/include/libpayload.h @@ -311,6 +311,13 @@ u8 bin2hex(u8 b); u8 hex2bin(u8 h); void hexdump(const void *memory, size_t length); void fatal(const char *msg) __attribute__ ((noreturn)); + +/* Count Leading Zeroes: clz(0) == 32, clz(0xf) == 28, clz(1 << 31) == 0 */ +static inline int clz(u32 x) { return x ? __builtin_clz(x) : sizeof(x) * 8; } +/* Integer binary logarithm (rounding down): log2(0) == -1, log2(5) == 2 */ +static inline int log2(u32 x) { return sizeof(x) * 8 - clz(x) - 1; } +/* Find First Set: __ffs(0xf) == 0, __ffs(0) == -1, __ffs(1 << 31) == 31 */ +static inline int __ffs(u32 x) { return log2(x & (u32)(-(s32)x)); } /** @} */ diff --git a/payloads/libpayload/include/strings.h b/payloads/libpayload/include/strings.h deleted file mode 100644 index 5beddc6a7f..0000000000 --- a/payloads/libpayload/include/strings.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2011 secunet Security Networks AG - * - * 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * 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. - */ - -#ifndef _STRINGS_H -#define _STRINGS_H - -int ffs(int i); - -#endif diff --git a/payloads/libpayload/libc/Makefile.inc b/payloads/libpayload/libc/Makefile.inc index b4f75a6cb5..272cda9ac4 100644 --- a/payloads/libpayload/libc/Makefile.inc +++ b/payloads/libpayload/libc/Makefile.inc @@ -29,10 +29,10 @@ ## libc-$(CONFIG_LP_LIBC) += malloc.c printf.c console.c string.c -libc-$(CONFIG_LP_LIBC) += memory.c ctype.c ipchecksum.c lib.c +libc-$(CONFIG_LP_LIBC) += memory.c ctype.c ipchecksum.c lib.c libgcc.c libc-$(CONFIG_LP_LIBC) += rand.c time.c exec.c libc-$(CONFIG_LP_LIBC) += readline.c getopt_long.c sysinfo.c -libc-$(CONFIG_LP_LIBC) += args.c strings.c +libc-$(CONFIG_LP_LIBC) += args.c libc-$(CONFIG_LP_LIBC) += strlcpy.c libc-$(CONFIG_LP_LIBC) += qsort.c libc-$(CONFIG_LP_LIBC) += hexdump.c diff --git a/payloads/libpayload/libc/strings.c b/payloads/libpayload/libc/libgcc.c similarity index 63% rename from payloads/libpayload/libc/strings.c rename to payloads/libpayload/libc/libgcc.c index 465ae4f12d..86698d8db3 100644 --- a/payloads/libpayload/libc/strings.c +++ b/payloads/libpayload/libc/libgcc.c @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2011 secunet Security Networks AG + * Copyright 2015 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -14,6 +14,10 @@ * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * * 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 @@ -27,16 +31,38 @@ * SUCH DAMAGE. */ -#include +#include -int ffs(int i) +/* + * Provide platform-independent backend implementation for __builtin_clz() in + * in case GCC does not have an assembly version for this arch. + */ + +int __clzsi2(u32 a); +int __clzsi2(u32 a) { - int count = 1; - if (i == 0) return 0; + static const u8 four_bit_table[] = { + [0x0] = 4, [0x1] = 3, [0x2] = 2, [0x3] = 2, + [0x4] = 1, [0x5] = 1, [0x6] = 1, [0x7] = 1, + [0x8] = 0, [0x9] = 0, [0xa] = 0, [0xb] = 0, + [0xc] = 0, [0xd] = 0, [0xe] = 0, [0xf] = 0, + }; + int r = 0; - while ((i & 1) != 1) { - i>>=1; - count++; + if (!(a & (0xffff << 16))) { + r += 16; + a <<= 16; } - return count; + + if (!(a & (0xff << 24))) { + r += 8; + a <<= 8; + } + + if (!(a & (0xf << 28))) { + r += 4; + a <<= 4; + } + + return r + four_bit_table[a >> 28]; } diff --git a/src/arch/arm/include/utils.h b/src/arch/arm/include/utils.h deleted file mode 100644 index 2482c6bf57..0000000000 --- a/src/arch/arm/include/utils.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * (C) Copyright 2010 - * Texas Instruments, - * Aneesh V - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc. - */ -#ifndef _UTILS_H_ -#define _UTILS_H_ - -static inline s32 log_2_n_round_up(u32 n) -{ - s32 log2n = -1; - u32 temp = n; - - while (temp) { - log2n++; - temp >>= 1; - } - - if (n & (n - 1)) - return log2n + 1; /* not power of 2 - round up */ - else - return log2n; /* power of 2 */ -} - -static inline s32 log_2_n_round_down(u32 n) -{ - s32 log2n = -1; - u32 temp = n; - - while (temp) { - log2n++; - temp >>= 1; - } - - return log2n; -} - -#endif diff --git a/src/arch/x86/include/arch/io.h b/src/arch/x86/include/arch/io.h index ce9477358a..5c85019daf 100644 --- a/src/arch/x86/include/arch/io.h +++ b/src/arch/x86/include/arch/io.h @@ -174,8 +174,8 @@ static inline __attribute__((always_inline)) void write32(volatile void *addr, u } /* Conflicts with definition in lib.h */ -#if defined(__ROMCC__) || defined(__SMM__) -static inline int log2(int value) +#if defined(__ROMCC__) +static inline int log2(u32 value) { unsigned int r = 0; __asm__ volatile ( @@ -187,10 +187,8 @@ static inline int log2(int value) return r; } -#endif -#if defined(__PRE_RAM__) || defined(__SMM__) -static inline int log2f(int value) +static inline int __ffs(u32 value) { unsigned int r = 0; __asm__ volatile ( diff --git a/src/include/lib.h b/src/include/lib.h index 7ad33dd552..b81b1b18bb 100644 --- a/src/include/lib.h +++ b/src/include/lib.h @@ -24,12 +24,6 @@ #include #include -#if !defined(__ROMCC__) /* Conflicts with inline function in arch/io.h */ -/* Defined in src/lib/clog2.c */ -unsigned long log2(unsigned long x); -#endif -unsigned long log2_ceil(unsigned long x); - /* Defined in src/lib/lzma.c */ unsigned long ulzma(unsigned char *src, unsigned char *dst); @@ -49,4 +43,16 @@ int checkstack(void *top_of_stack, int core); void hexdump(const void *memory, size_t length); void hexdump32(char LEVEL, const void *d, size_t len); +#if !defined(__ROMCC__) +/* Count Leading Zeroes: clz(0) == 32, clz(0xf) == 28, clz(1 << 31) == 0 */ +static inline int clz(u32 x) { return x ? __builtin_clz(x) : sizeof(x) * 8; } +/* Integer binary logarithm (rounding down): log2(0) == -1, log2(5) == 2 */ +static inline int log2(u32 x) { return sizeof(x) * 8 - clz(x) - 1; } +/* Find First Set: __ffs(1) == 0, __ffs(0) == -1, __ffs(1<<31) == 31 */ +static inline int __ffs(u32 x) { return log2(x & (u32)(-(s32)x)); } +#endif + +/* Integer binary logarithm (rounding up): log2_ceil(0) == -1, log2(5) == 3 */ +static inline int log2_ceil(u32 x) { return (x == 0) ? -1 : log2(x * 2 - 1); } + #endif /* __LIB_H__ */ diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 557cd66846..76c8fd3dc5 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -25,7 +25,7 @@ bootblock-y += cbfs.c bootblock-y += cbfs_boot_props.c bootblock-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c bootblock-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c - +bootblock-y += libgcc.c bootblock-$(CONFIG_GENERIC_UDELAY) += timer.c bootblock-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c @@ -45,6 +45,7 @@ verstage-y += cbfs.c verstage-y += halt.c verstage-y += fmap.c verstage-y += cbfs_boot_props.c +verstage-y += libgcc.c verstage-y += memcmp.c verstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c verstage-y += region.c @@ -77,6 +78,7 @@ romstage-y += cbfs.c romstage-y += cbfs_boot_props.c romstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c romstage-$(CONFIG_COMPRESS_RAMSTAGE) += lzma.c lzmadecode.c +romstage-y += libgcc.c romstage-$(CONFIG_PRIMITIVE_MEMTEST) += primitive_memtest.c ramstage-$(CONFIG_PRIMITIVE_MEMTEST) += primitive_memtest.c romstage-$(CONFIG_CACHE_AS_RAM) += ramtest.c @@ -115,8 +117,6 @@ ramstage-y += cbfs_boot_props.c ramstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c ramstage-y += lzma.c lzmadecode.c ramstage-y += stack.c -ramstage-y += clog2.c -romstage-y += clog2.c ramstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c ramstage-$(CONFIG_BOOTSPLASH) += jpeg.c ramstage-$(CONFIG_TRACE) += trace.c diff --git a/src/lib/clog2.c b/src/lib/clog2.c deleted file mode 100644 index 5e0d591de4..0000000000 --- a/src/lib/clog2.c +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include - -/* Assume 8 bits per byte */ -#define CHAR_BIT 8 - -unsigned long log2(unsigned long x) -{ - /* assume 8 bits per byte. */ - unsigned long pow = sizeof(x) * CHAR_BIT - 1ULL; - unsigned long i = 1ULL << pow; - - if (!x) { - printk(BIOS_WARNING, "%s called with invalid parameter of 0\n", - __func__); - return -1; - } - - for (; i > x; i >>= 1, pow--); - - return pow; -} - -unsigned long log2_ceil(unsigned long x) -{ - unsigned long pow; - - if (!x) - return -1; - - pow = log2(x); - - if (x > (1ULL << pow)) - pow++; - - return pow; -} diff --git a/src/lib/libgcc.c b/src/lib/libgcc.c new file mode 100644 index 0000000000..14685becf0 --- /dev/null +++ b/src/lib/libgcc.c @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include + +/* + * Provide platform-independent backend implementation for __builtin_clz() in + * in case GCC does not have an assembly version for this arch. + */ + +#if !IS_ENABLED(CONFIG_ARCH_X86) /* work around lack of --gc-sections on x86 */ +int __clzsi2(u32 a); +int __clzsi2(u32 a) +{ + static const u8 four_bit_table[] = { + [0x0] = 4, [0x1] = 3, [0x2] = 2, [0x3] = 2, + [0x4] = 1, [0x5] = 1, [0x6] = 1, [0x7] = 1, + [0x8] = 0, [0x9] = 0, [0xa] = 0, [0xb] = 0, + [0xc] = 0, [0xd] = 0, [0xe] = 0, [0xf] = 0, + }; + int r = 0; + + if (!(a & (0xffff << 16))) { + r += 16; + a <<= 16; + } + + if (!(a & (0xff << 24))) { + r += 8; + a <<= 8; + } + + if (!(a & (0xf << 28))) { + r += 4; + a <<= 4; + } + + return r + four_bit_table[a >> 28]; +} +#endif diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c index a8d87008f5..6554e075ea 100644 --- a/src/northbridge/amd/amdk8/coherent_ht.c +++ b/src/northbridge/amd/amdk8/coherent_ht.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include diff --git a/src/northbridge/amd/amdk8/raminit.c b/src/northbridge/amd/amdk8/raminit.c index 4213cfb3a2..c58abb15ae 100644 --- a/src/northbridge/amd/amdk8/raminit.c +++ b/src/northbridge/amd/amdk8/raminit.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1655,7 +1656,7 @@ static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller * /* if the next lower frequency gives a CL at least one whole cycle * shorter, select that (see end of BKDG 4.1.1.1) */ if (freq < sizeof(cl_at_freq)-1 && cl_at_freq[freq+1] && - log2f(cl_at_freq[freq]) - log2f(cl_at_freq[freq+1]) >= 2) + __ffs(cl_at_freq[freq]) - __ffs(cl_at_freq[freq+1]) >= 2) freq++; if (freq == sizeof(cl_at_freq)) @@ -1690,7 +1691,7 @@ static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller * /* Update DRAM Timing Low with our selected cas latency */ value = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); value &= ~(DTL_TCL_MASK << DTL_TCL_SHIFT); - value |= latencies[log2f(cl_at_freq[freq]) - 2] << DTL_TCL_SHIFT; + value |= latencies[__ffs(cl_at_freq[freq]) - 2] << DTL_TCL_SHIFT; pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, value); result.dimm_mask = dimm_mask; diff --git a/src/northbridge/amd/amdk8/raminit_f.c b/src/northbridge/amd/amdk8/raminit_f.c index 14696846dc..1c1a6ea142 100644 --- a/src/northbridge/amd/amdk8/raminit_f.c +++ b/src/northbridge/amd/amdk8/raminit_f.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include "raminit.h" diff --git a/src/northbridge/amd/amdk8/raminit_test.c b/src/northbridge/amd/amdk8/raminit_test.c index be46f27bca..87e281d645 100644 --- a/src/northbridge/amd/amdk8/raminit_test.c +++ b/src/northbridge/amd/amdk8/raminit_test.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/src/northbridge/intel/e7501/raminit.c b/src/northbridge/intel/e7501/raminit.c index f4fc9a8a77..93a3a5b5a9 100644 --- a/src/northbridge/intel/e7501/raminit.c +++ b/src/northbridge/intel/e7501/raminit.c @@ -12,6 +12,7 @@ /* converted to C 6/2004 yhlu */ #include +#include #include #include #include diff --git a/src/northbridge/intel/i3100/raminit_ep80579.c b/src/northbridge/intel/i3100/raminit_ep80579.c index 85660e9c08..ee8c4fd7f7 100644 --- a/src/northbridge/intel/i3100/raminit_ep80579.c +++ b/src/northbridge/intel/i3100/raminit_ep80579.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "raminit_ep80579.h" #include "ep80579.h" diff --git a/src/northbridge/intel/i855/raminit.c b/src/northbridge/intel/i855/raminit.c index 81dcbb507c..a43f5be6b7 100644 --- a/src/northbridge/intel/i855/raminit.c +++ b/src/northbridge/intel/i855/raminit.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include diff --git a/src/northbridge/intel/i945/raminit.c b/src/northbridge/intel/i945/raminit.c index a3be6803f0..7bd62402b6 100644 --- a/src/northbridge/intel/i945/raminit.c +++ b/src/northbridge/intel/i945/raminit.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/src/soc/rockchip/rk3288/clock.c b/src/soc/rockchip/rk3288/clock.c index 2c56376b04..a2e8d88ef3 100644 --- a/src/soc/rockchip/rk3288/clock.c +++ b/src/soc/rockchip/rk3288/clock.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -236,22 +237,6 @@ static int rkclk_set_pll(u32 *pll_con, const struct pll_div *div) return 0; } -/* - TODO: - it should be replaced by lib.h function - 'unsigned long log2(unsigned long x)' -*/ -static unsigned int log2(unsigned int value) -{ - unsigned int div = 0; - - while (value != 1) { - div++; - value = ALIGN_UP(value, 2) / 2; - } - return div; -} - void rkclk_init(void) { u32 aclk_div; diff --git a/src/southbridge/via/k8t890/traf_ctrl.c b/src/southbridge/via/k8t890/traf_ctrl.c index b4620da4ff..24c1e65707 100644 --- a/src/southbridge/via/k8t890/traf_ctrl.c +++ b/src/southbridge/via/k8t890/traf_ctrl.c @@ -24,10 +24,9 @@ #include #include #include +#include #include "k8t890.h" -extern unsigned long log2(unsigned long x); - static void mmconfig_set_resources(device_t dev) { struct resource *resource;