All of lore.kernel.org
 help / color / mirror / Atom feed
From: "André Schaller" <an.schall@googlemail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] RNG implementation fails
Date: Tue, 30 Jul 2013 14:14:31 +0200	[thread overview]
Message-ID: <51F7AE27.8060403@googlemail.com> (raw)

HI,

I wanted to include a RNG implementation of the Mersenne-Twister into
the SPL part of u-boot. However, although the (standalone) code compiles
and runs fine on my linux box, u-boot stops to boot and I am not sure
why. I am sure I am missing a rather basic design principle of the
u-boot code but I can't figure which.

SPL stops booting at the twisted feedback line in function genrand_int32().

Here is the code of the hwinit-common.h in arch/arm/cpu/armv7/omap-common/:


#include <common.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/sizes.h>
#include <asm/emif.h>
#include <asm/omap_common.h>

/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */

static unsigned long x[N];      /* the array for the state vector  */
static unsigned long *p0, *p1, *pm;


DECLARE_GLOBAL_DATA_PTR;

/*
   initialize MT with a seed
*/
void init_genrand(unsigned long s)
{
  int i;

  x[0] = s & 0xffffffffUL;
  for (i = 1; i < N; ++i) {
    x[i] = (1812433253UL * (x[i - 1] ^ (x[i - 1] >> 30)) + i)
      & 0xffffffffUL;           /* for >32 bit machines */
  }
  p0 = x;
  p1 = x + 1;
  pm = x + M;
}

/*
   initialize by an array with array-length
   init_key is the array for initializing keys
   key_length is its length
*/
void init_by_array(unsigned long init_key[], int key_length)
{
  int i, j, k;

  init_genrand(19650218UL);
  i = 1;
  j = 0;
  for (k = (N > key_length ? N : key_length); k; --k) {
    /* non linear */
    x[i] = ((x[i] ^ ((x[i - 1] ^ (x[i - 1] >> 30)) * 1664525UL))
            + init_key[j] + j) & 0xffffffffUL;  /* for WORDSIZE > 32
machines */
    if (++i >= N) {
      x[0] = x[N - 1];
      i = 1;
    }
    if (++j >= key_length) {
      j = 0;
    }
  }
  for (k = N - 1; k; --k) {
    /* non linear */
    x[i] = ((x[i] ^ ((x[i - 1] ^ (x[i - 1] >> 30)) * 1566083941UL)) - i)
      & 0xffffffffUL;           /* for WORDSIZE > 32 machines */
    if (++i >= N) {
      x[0] = x[N - 1];
      i = 1;
    }
  }
  x[0] = 0x80000000UL;          /* MSB is 1; assuring non-zero initial
array */
}

/* generates a random number on the interval [0,0xffffffff] */
unsigned long genrand_int32(void)
{
  unsigned long y;


  if (!p0) {
    /* Default seed */
    init_genrand(5489UL);
  }

  /* Twisted feedback -- HERE WE GET STUCK*/
  y = *p0 = *pm++ ^ (((*p0 & UPPER_MASK) | (*p1 & LOWER_MASK)) >> 1)
    ^ (-(*p1 & 1) & MATRIX_A);
  p0 = p1++;

  if (pm == x + N) {
    pm = x;
  }

  if (p1 == x + N) {
    p1 = x;
  }
  /* Temper */

  y ^= y >> 11;
  y ^= y << 7 & 0x9d2c5680UL;
  y ^= y << 15 & 0xefc60000UL;
  y ^= y >> 18;
  return y;
}

void do_set_mux(u32 base, struct pad_conf_entry const *array, int size)
{
    int i;
    struct pad_conf_entry *pad = (struct pad_conf_entry *) array;

    for (i = 0; i < size; i++, pad++)
        writew(pad->val, base + pad->offset);
}

static void set_mux_conf_regs(void)
{
    switch (omap_hw_init_context()) {
    case OMAP_INIT_CONTEXT_SPL:
        set_muxconf_regs_essential();
        break;
    case OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL:
#ifdef CONFIG_SYS_ENABLE_PADS_ALL
        set_muxconf_regs_non_essential();
#endif
        break;
    case OMAP_INIT_CONTEXT_UBOOT_FROM_NOR:
    case OMAP_INIT_CONTEXT_UBOOT_AFTER_CH:
        set_muxconf_regs_essential();
#ifdef CONFIG_SYS_ENABLE_PADS_ALL
        set_muxconf_regs_non_essential();
#endif
        break;
    }
}

u32 cortex_rev(void)
{

    unsigned int rev;

    /* Read Main ID Register (MIDR) */
    asm ("mrc p15, 0, %0, c0, c0, 0" : "=r" (rev));

    return rev;
}

void omap_rev_string(void)
{
    u32 omap_rev = omap_revision();
    u32 omap_variant = (omap_rev & 0xFFFF0000) >> 16;
    u32 major_rev = (omap_rev & 0x00000F00) >> 8;
    u32 minor_rev = (omap_rev & 0x000000F0) >> 4;

    printf("OMAP%x ES%x.%x\n", omap_variant, major_rev,
        minor_rev);
}

#ifdef CONFIG_SPL_BUILD
static void init_boot_params(void)
{
    boot_params_ptr = (u32 *) &boot_params;
}
#endif

/*
 * Routine: s_init
 * Description: Does early system init of watchdog, muxing,  andclocks
 * Watchdog disable is done always. For the rest what gets done
 * depends on the boot mode in which this function is executed
 *   1. s_init of SPL running from SRAM
 *   2. s_init of U-Boot running from FLASH
 *   3. s_init of U-Boot loaded to SDRAM by SPL
 *   4. s_init of U-Boot loaded to SDRAM by ROM code using the
 *    Configuration Header feature
 * Please have a look at the respective functions to see what gets
 * done in each of these cases
 * This function is called with SRAM stack.
 */
void s_init(void)
{
    init_omap_revision();
    watchdog_init();
    set_mux_conf_regs();
#ifdef CONFIG_SPL_BUILD
    setup_clocks_for_console();
    preloader_console_init();

 
    unsigned char current_rn_char;
    unsigned long current_rn;
    int i = 0;
    unsigned long init[4] = { 0x123, 0x234, 0x345, 0x456 }, length = 4;

    // Start PRNG
    init_by_array(init, length);

    for (i=0; i<22; i++){
        current_rn = genrand_real1();
        current_rn_char = (char)current_rn;
        secret[i] = current_rn_char;
    }

    secret[22] = 0x00;
    printf("\nmeh2\n");
    printf("\n[I] - These are our secret bytes (%d
bytes):\n\t==================================\n\t", sizeof(secret));
    i = 0;   
    while(secret[i]!=0x0){
        printf("0x%02x ", secret[i]);
        i++;
    }
    printf("\n\t==================================\n");
   
    do_io_settings();
#endif
    prcm_init();
#ifdef CONFIG_SPL_BUILD
    timer_init();

    /* For regular u-boot sdram_init() is called from dram_init() */
    sdram_init();
    init_boot_params();
#endif
}

/*
 * Routine: wait_for_command_complete
 * Description: Wait for posting to finish on watchdog
 */
void wait_for_command_complete(struct watchdog *wd_base)
{
    int pending = 1;
    do {
        pending = readl(&wd_base->wwps);
    } while (pending);
}

/*
 * Routine: watchdog_init
 * Description: Shut down watch dogs
 */
void watchdog_init(void)
{
    struct watchdog *wd2_base = (struct watchdog *)WDT2_BASE;

    writel(WD_UNLOCK1, &wd2_base->wspr);
    wait_for_command_complete(wd2_base);
    writel(WD_UNLOCK2, &wd2_base->wspr);
}


/*
 * This function finds the SDRAM size available in the system
 * based on DMM section configurations
 * This is needed because the size of memory installed may be
 * different on different versions of the board
 */
u32 omap_sdram_size(void)
{
    u32 section, i, total_size = 0, size, addr;

    for (i = 0; i < 4; i++) {
        section    = __raw_readl(DMM_BASE + i*4);
        addr = section & EMIF_SYS_ADDR_MASK;
        /* See if the address is valid */
        if ((addr >= DRAM_ADDR_SPACE_START) &&
            (addr < DRAM_ADDR_SPACE_END)) {
            size = ((section & EMIF_SYS_SIZE_MASK) >>
                   EMIF_SYS_SIZE_SHIFT);
            size = 1 << size;
            size *= SZ_16M;
            total_size += size;
        }
    }

    return total_size;
}


/*
 * Routine: dram_init
 * Description: sets uboots idea of sdram size
 */
int dram_init(void)
{
    sdram_init();
    gd->ram_size = omap_sdram_size();
    return 0;
}

/*
 * Print board information
 */
int checkboard(void)
{
    puts(sysinfo.board_string);
    return 0;
}

/*
* This function is called by start_armboot. You can reliably use static
* data. Any boot-time function that require static data should be
* called from here
*/
int arch_cpu_init(void)
{
    return 0;
}

/*
 *  get_device_type(): tell if GP/HS/EMU/TST
 */
u32 get_device_type(void)
{
    return 0;
}

/*
 * Print CPU information
 */
int print_cpuinfo(void)
{
    puts("CPU  : ");
    omap_rev_string();

    return 0;
}

/*
 * this uses the unique per-cpu info from the cpu fuses set at factory to
 * generate a 6-byte MAC address.  Two bits in the generated code are used
 * to elaborate the generated address into four, so it can be used on
multiple
 * network interfaces.
 */
void omap4_die_id_to_ethernet_mac(u8 *mac, int subtype)
{
    struct ctrl_id *id_base = (struct ctrl_id *)(CTRL_BASE + 0x200);
    u32 idcode;
    u32 id[4];

    idcode = readl(&id_base->idcode);
    id[0] = readl(&id_base->die_id_0);
    id[1] = readl(&id_base->die_id_1);
    id[2] = readl(&id_base->die_id_2);
    id[3] = readl(&id_base->die_id_3);

    mac[0] = id[2];
    mac[1] = id[2] >> 8;
    mac[2] = id[1];
    mac[3] = id[1] >> 8;
    mac[4] = id[1] >> 16;
    mac[5] = id[1] >> 24;
    /* XOR other chip-specific data with ID */
    idcode ^= id[3];

    mac[0] ^= idcode;
    mac[1] ^= idcode >> 8;
    mac[2] ^= idcode >> 16;
    mac[3] ^= idcode >> 24;

    /* allow four MACs from this same basic data */
    mac[1] = (mac[1] & ~0xc0) | ((subtype & 3) << 6);

    /* mark it as not multicast and outside official 80211 MAC namespace */
    mac[0] = (mac[0] & ~1) | 2;
}

#ifndef CONFIG_SYS_DCACHE_OFF
void enable_caches(void)
{
    /* Enable D-cache. I-cache is already enabled in start.S */
    dcache_enable();
}
#endif

                 reply	other threads:[~2013-07-30 12:14 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51F7AE27.8060403@googlemail.com \
    --to=an.schall@googlemail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.