static void bcmrng_get(struct bcm2835rng_softc *sc) { uint32_t status, cnt; uint32_t buf[RNG_DATA_MAX]; /* 1k on the stack */ mutex_spin_enter(&sc->sc_intr_lock); while (sc->sc_bytes_wanted) { status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, RNG_STATUS); cnt = __SHIFTOUT(status, RNG_STATUS_CNT); KASSERT(cnt < RNG_DATA_MAX); if (cnt == 0) continue; /* XXX Busy-waiting seems wrong... */ bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh, RNG_DATA, buf, cnt); /* * This lock dance is necessary because rnd_add_data * may call bcmrng_get_cb which takes the intr lock. */ mutex_spin_exit(&sc->sc_intr_lock); mutex_spin_enter(&sc->sc_rnd_lock); rnd_add_data(&sc->sc_rndsource, buf, (cnt * 4), (cnt * 4 * NBBY)); mutex_spin_exit(&sc->sc_rnd_lock); mutex_spin_enter(&sc->sc_intr_lock); sc->sc_bytes_wanted -= MIN(sc->sc_bytes_wanted, (cnt * 4)); } explicit_memset(buf, 0, sizeof(buf)); mutex_spin_exit(&sc->sc_intr_lock); }
static void feedrandom(size_t bytes, void *arg) { uint8_t *rnddata; size_t dsize; rnddata = kmem_intr_alloc(MAXGET, KM_SLEEP); if (rumpuser_getrandom(rnddata, MIN(MAXGET, bytes), RUMPUSER_RANDOM_HARD|RUMPUSER_RANDOM_NOWAIT, &dsize) == 0) rnd_add_data(&rndsrc, rnddata, dsize, NBBY*dsize); kmem_intr_free(rnddata, MAXGET); }
static void kprintf_rnd_get(size_t bytes, void *priv) { if (kprnd_added) { KASSERT(kprintf_inited); if (mutex_tryenter(&kprintf_mtx)) { SHA512_Final(kprnd_accum, &kprnd_sha); rnd_add_data(&rnd_printf_source, kprnd_accum, sizeof(kprnd_accum), 0); kprnd_added = 0; /* This, we must do, since we called _Final. */ SHA512_Init(&kprnd_sha); /* This is optional but seems useful. */ SHA512_Update(&kprnd_sha, kprnd_accum, sizeof(kprnd_accum)); mutex_exit(&kprintf_mtx); } } }
static void ingenic_rng_get(struct ingenic_rng_softc *sc) { uint32_t data; mutex_spin_enter(&sc->sc_intr_lock); while (sc->sc_bytes_wanted) { bus_space_read_region_4(sc->sc_bst, sc->sc_bsh, 0, &data, 1); #if 0 device_printf(sc->sc_dev, "random output: %x\n", data); #endif mutex_spin_exit(&sc->sc_intr_lock); mutex_spin_enter(&sc->sc_rnd_lock); rnd_add_data(&sc->sc_rndsource, &data, sizeof(data), sizeof(data) * NBBY); mutex_spin_exit(&sc->sc_rnd_lock); mutex_spin_enter(&sc->sc_intr_lock); sc->sc_bytes_wanted -= MIN(sc->sc_bytes_wanted, sizeof(data)); } explicit_memset(&data, 0, sizeof(data)); mutex_spin_exit(&sc->sc_intr_lock); }
int viornd_vq_done(struct virtqueue *vq) { struct virtio_softc *vsc = vq->vq_owner; struct viornd_softc *sc = device_private(vsc->sc_child); int slot, len; mutex_enter(&sc->sc_mutex); if (virtio_dequeue(vsc, vq, &slot, &len) != 0) { mutex_exit(&sc->sc_mutex); return 0; } sc->sc_active = false; bus_dmamap_sync(vsc->sc_dmat, sc->sc_dmamap, 0, VIORND_BUFSIZE, BUS_DMASYNC_POSTREAD); if (len > VIORND_BUFSIZE) { aprint_error_dev(sc->sc_dev, "inconsistent descriptor length %d > %d\n", len, VIORND_BUFSIZE); goto out; } #if VIORND_DEBUG aprint_normal("%s: got %d bytes of entropy\n", __func__, len); #endif rnd_add_data(&sc->sc_rndsource, sc->sc_buf, VIORND_BUFSIZE, VIORND_BUFSIZE * NBBY); out: virtio_dequeue_commit(vsc, vq, slot); mutex_exit(&sc->sc_mutex); return 1; }
/* * Set up the system's time, given a `reasonable' time value. */ void inittodr(time_t base) { bool badbase = false; bool waszero = (base == 0); bool goodtime = false; bool badrtc = false; int s; struct timespec ts; struct timeval tv; rnd_add_data(NULL, &base, sizeof(base), 0); if (base < 5 * SECS_PER_COMMON_YEAR) { struct clock_ymdhms basedate; /* * If base is 0, assume filesystem time is just unknown * instead of preposterous. Don't bark. */ if (base != 0) printf("WARNING: preposterous time in file system\n"); /* not going to use it anyway, if the chip is readable */ basedate.dt_year = 2010; basedate.dt_mon = 1; basedate.dt_day = 1; basedate.dt_hour = 12; basedate.dt_min = 0; basedate.dt_sec = 0; base = clock_ymdhms_to_secs(&basedate); badbase = true; } /* * Some ports need to be supplied base in order to fabricate a time_t. */ if (todr_handle) todr_handle->base_time = base; if ((todr_handle == NULL) || (todr_gettime(todr_handle, &tv) != 0) || (tv.tv_sec < (25 * SECS_PER_COMMON_YEAR))) { if (todr_handle != NULL) printf("WARNING: preposterous TOD clock time\n"); else printf("WARNING: no TOD clock present\n"); badrtc = true; } else { time_t deltat = tv.tv_sec - base; if (deltat < 0) deltat = -deltat; if (!badbase && deltat >= 2 * SECS_PER_DAY) { if (tv.tv_sec < base) { /* * The clock should never go backwards * relative to filesystem time. If it * does by more than the threshold, * believe the filesystem. */ printf("WARNING: clock lost %" PRId64 " days\n", deltat / SECS_PER_DAY); badrtc = true; } else { aprint_verbose("WARNING: clock gained %" PRId64 " days\n", deltat / SECS_PER_DAY); goodtime = true; } } else { goodtime = true; } rnd_add_data(NULL, &tv, sizeof(tv), 0); } /* if the rtc time is bad, use the filesystem time */ if (badrtc) { if (badbase) { printf("WARNING: using default initial time\n"); } else { printf("WARNING: using filesystem time\n"); } tv.tv_sec = base; tv.tv_usec = 0; } timeset = true; ts.tv_sec = tv.tv_sec; ts.tv_nsec = tv.tv_usec * 1000; s = splclock(); tc_setclock(&ts); splx(s); if (waszero || goodtime) return; printf("WARNING: CHECK AND RESET THE DATE!\n"); }