github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/soc/imx6/rngb/rngb.go (about)

     1  // NXP Random Number Generator (RNGB) driver
     2  // https://github.com/f-secure-foundry/tamago
     3  //
     4  // Copyright (c) F-Secure Corporation
     5  // https://foundry.f-secure.com
     6  //
     7  // Use of this source code is governed by the license
     8  // that can be found in the LICENSE file.
     9  
    10  // Package rngb implements a driver for the NXP True Random Number Generator
    11  // (RNGB) included in i.MX6ULL/i.MX6ULZ SoCs.
    12  //
    13  // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as
    14  // supported by the TamaGo framework for bare metal Go on ARM SoCs, see
    15  // https://github.com/f-secure-foundry/tamago.
    16  package rngb
    17  
    18  import (
    19  	"sync"
    20  
    21  	"github.com/f-secure-foundry/tamago/internal/reg"
    22  )
    23  
    24  // RNGB registers
    25  const (
    26  	RNG_BASE = 0x02284000
    27  
    28  	RNG_CMD    = RNG_BASE + 0x04
    29  	RNG_CMD_SR = 6
    30  	RNG_CMD_CE = 5
    31  	RNG_CMD_CI = 4
    32  	RNG_CMD_GS = 1
    33  	RNG_CMD_ST = 0
    34  
    35  	RNG_CR    = RNG_BASE + 0x08
    36  	RNG_CR_AR = 4
    37  	RNG_CR_GS = 1
    38  
    39  	RNG_SR          = RNG_BASE + 0x0c
    40  	RNG_SR_ST_PF    = 21
    41  	RNG_SR_ERR      = 16
    42  	RNG_SR_FIFO_LVL = 8
    43  	RNG_SR_SDN      = 5
    44  	RNG_SR_STDN     = 4
    45  
    46  	RNG_ESR = RNG_BASE + 0x10
    47  	RNG_OUT = RNG_BASE + 0x14
    48  )
    49  
    50  var mux sync.Mutex
    51  
    52  // Reset resets the RNGB module.
    53  func Reset() {
    54  	mux.Lock()
    55  	defer mux.Unlock()
    56  
    57  	// soft reset RNGB
    58  	reg.Set(RNG_CMD, RNG_CMD_SR)
    59  }
    60  
    61  // Init initializes the RNGB module with automatic seeding.
    62  func Init() {
    63  	mux.Lock()
    64  	defer mux.Unlock()
    65  
    66  	// p3105, 44.5.2 Automatic seeding, IMX6ULLRM
    67  
    68  	// clear errors
    69  	reg.Set(RNG_CMD, RNG_CMD_CE)
    70  
    71  	// soft reset RNGB
    72  	reg.Set(RNG_CMD, RNG_CMD_SR)
    73  
    74  	// perform self-test
    75  	reg.Set(RNG_CMD, RNG_CMD_ST)
    76  
    77  	for reg.Get(RNG_SR, RNG_SR_STDN, 1) != 1 {
    78  		// reg.Wait cannot be used before runtime initialization
    79  	}
    80  
    81  	if reg.Get(RNG_SR, RNG_SR_ERR, 1) != 0 || reg.Get(RNG_SR, RNG_SR_ST_PF, 1) != 0 {
    82  		panic("imx6_rng: self-test failure\n")
    83  	}
    84  
    85  	// enable auto-reseed
    86  	reg.Set(RNG_CR, RNG_CR_AR)
    87  	// generate a seed
    88  	reg.Set(RNG_CMD, RNG_CR_GS)
    89  
    90  	for reg.Get(RNG_SR, RNG_SR_SDN, 1) != 1 {
    91  		// reg.Wait cannot be used before runtime initialization
    92  	}
    93  
    94  	// clear interrupts
    95  	reg.Set(RNG_CMD, RNG_CMD_CI)
    96  }
    97  
    98  // GetRandomData returns len(b) random bytes gathered from the RNGB module.
    99  func GetRandomData(b []byte) {
   100  	read := 0
   101  	need := len(b)
   102  
   103  	for read < need {
   104  		if reg.Get(RNG_SR, RNG_SR_ERR, 1) != 0 {
   105  			panic("imx6_rng: error during getRandomData\n")
   106  		}
   107  
   108  		if reg.Get(RNG_SR, RNG_SR_FIFO_LVL, 0b1111) > 0 {
   109  			read = Fill(b, read, reg.Read(RNG_OUT))
   110  		}
   111  	}
   112  }
   113  
   114  func Fill(b []byte, index int, val uint32) int {
   115  	shift := 0
   116  	limit := len(b)
   117  
   118  	for (index < limit) && (shift <= 24) {
   119  		b[index] = byte((val >> shift) & 0xff)
   120  		index += 1
   121  		shift += 8
   122  	}
   123  
   124  	return index
   125  }