示例#1
0
static void dhcp_send_packet(struct uip_udp_conn *conn, const char *name,
			     DhcpPacket *out, DhcpPacket *in)
{
	// Send the outbound packet.
	printf("Sending %s... ", name);
	uip_udp_packet_send(conn, out, sizeof(*out));
	printf("done.\n");

	// Prepare for the reply.
	printf("Waiting for reply... ");
	dhcp_in = in;
	dhcp_out = out;
	dhcp_in_ready = 0;

	// Poll network driver until we get a reply. Resend periodically.
	net_set_callback(&dhcp_callback);
	for (;;) {
		uint64_t start = timer_us(0);
		do {
			net_poll();
		} while (!dhcp_in_ready &&
			 timer_us(start) < DhcpRespTimeoutUs);
		if (dhcp_in_ready)
			break;
		// No response, try again.
		uip_udp_packet_send(conn, out, sizeof(*out));
	}
	net_set_callback(NULL);
	printf("done.\n");
}
示例#2
0
uint64_t VbExGetTimer(void)
{
	static uint64_t start = 0;
	if (!start)
		start = timer_us(0);
	return timer_us(start);
}
示例#3
0
// print per-task accumulated usec runtime since last dump
void TaskDump()
{
	int i;
	TASK *t;
	u4_t now = timer_us();
	u4_t elapsed = now - epoch;
	float f_elapsed = ((float) elapsed) / 1e6;
	float f_sum = 0;
	
	for (i=0; i<MAX_TASKS; i++) {
		t = Tasks + i;
		if (t->valid) {
			float f_usec = ((float) t->usec) / 1e6;
			f_sum += f_usec;
			lprintf("T%02d %c%c%c %.3fuS %4.1f%% %6.3fM %7.3fdl %s\n", i,
				(t->priority == HIGH_PRIORITY)? 'H':'L',
				t->stopped? 'S':'R',
				t->quanta? 'q':' ',
				f_usec, f_usec/f_elapsed*100, (float) t->run / 1e6,
				t->deadline? ((float) (t->deadline-now) / 1e3) : 0, t->name);
			t->usec = 0;
		}
	}
	float f_remain = f_elapsed - f_sum;
	if (f_remain > 0) lprintf("   %.3f %4.1f%% (unaccounted)\n", f_remain, f_remain/f_elapsed*100);
	epoch = timer_us();
}
示例#4
0
int apollolake_get_gpe(int gpe)
{
	int bank;
	uint32_t mask, sts;
	uint64_t start;
	int rc = 0;
	const uint64_t timeout_us = 1000;

	if (gpe < 0 || gpe > GPE0_DW3_31)
		return -1;

	bank = gpe / 32;
	mask = 1 << (gpe % 32);

	/* Wait for GPE status to clear */
	start = timer_us(0);
	do {
		if (timer_us(start) > timeout_us)
			break;

		sts = inl(ACPI_PMIO_BASE + GPE0_STS(bank));
		if (sts & mask) {
			outl(mask, ACPI_PMIO_BASE + GPE0_STS(bank));
			rc = 1;
		}
	} while (sts & mask);

	return rc;
}
示例#5
0
void spin_us(u4_t usec)
{
	u4_t tref = timer_us(), diff;
	
	do {
		diff = time_diff(timer_us(), tref);
	} while (diff < usec);
}
示例#6
0
//void s4285_data(int rx_chan, int ch, int nsamps, TYPECPX *samps)
void s4285_data(int rx_chan, int ch, int nsamps, TYPEMONO16 *samps)
{
	s4285_t *e = &s4285[rx_chan];
	
	if (e->mode == MODE_TX_LOOPBACK) {
		//m_CSt4285[rx_chan].getTxOutput((void *) samps, nsamps, TYPE_IQ_F32_DATA, K_AMPMAX);
		m_CSt4285[rx_chan].getTxOutput((void *) samps, nsamps, TYPE_REAL_S16_DATA, K_AMPMAX);
		if (e->rx_task) TaskWakeup(e->rx_task, TRUE, e->rx_chan);
	} else {
		#if 0
		static u4_t last_time;
		u4_t now = timer_us();
		printf("s4285 nsamps %d %7.3f msec\n", nsamps, (float) (now - last_time) / 1e3);
		last_time = now;
		#endif
		
		assert(nsamps == N_RXBLK);
		memcpy(&s4285_rx_blocks[s4285_rx_wa][0], samps, sizeof(TYPEMONO16)*N_RXBLK);
		s4285_rx_wa++;
		if (s4285_rx_wa == N_RXBLKS) s4285_rx_wa = 0;
		s4285_rx_count++;
		if (s4285_rx_count > s4285_rx_count_max) {
			printf("%d\n", s4285_rx_count);
			s4285_rx_count_max = s4285_rx_count;
		}
		assert(s4285_rx_count < N_RXBLKS);
		if (e->rx_task) TaskWakeup(e->rx_task, TRUE, e->rx_chan);
	}
}
示例#7
0
/*
 * apl_i2s_send - Send audio samples to I2s controller.
 * @me: I2sOps structure
 * @data: Audio samples
 * @length: Number of samples
 *
 * Send audio samples to I2s controller.
*/
static int apl_i2s_send(I2sOps *me, unsigned int *data, unsigned int length)
{
	int i;
	uint64_t start;
	AplI2s *bus = container_of(me, AplI2s, ops);
	struct AplI2sRegs *i2s_reg = bus->regs;

	if (!bus->initialized) {
		if (apl_i2s_init(bus))
			return -1;
		bus->initialized = 1;
	}

	if (length < LPE_SSP_FIFO_SIZE) {
		printf("%s : Invalid data size\n", __func__);
		return -1;
	}

	gpio_set(bus->sdmode_gpio, 1);

	for (i = 0; i < LPE_SSP_FIFO_SIZE; i++)
		writel(*data++, &i2s_reg->ssdr);

	i2s_enable(bus->regs);
	length -= LPE_SSP_FIFO_SIZE;

	while (length > 0) {
		start = timer_us(0);
		if (read_SSSR(bus->regs) & 0x4) {
			writel(*data++, &i2s_reg->ssdr);
			length--;
		} else {
			if (timer_us(start) > 100000) {
				i2s_disable(bus->regs);
				gpio_set(bus->sdmode_gpio, 0);
				printf("I2S Transfer Timeout\n");
				return -1;
			}
		}
	}

	mdelay(1);
	gpio_set(bus->sdmode_gpio, 0);
	i2s_disable(bus->regs);
	return 0;
}
示例#8
0
void ev(int event, const char *s, const char *s2)
{
	int i;
	ev_t *e = &evs[evc++];
	u4_t now = timer_us();
	int reset=0;
	u64_t freeS2 = (u64_t) s2 & 1;
	s2 = (char*) ((u64_t) s2 & ~1);
	
	if (!triggered && (event == EV_TRIGGER)) {
		epoch = last_time = now;
		for (i=0; i<NEVT; i++) tlast[i] = now;
		evc=0;
		triggered=1;
		if (freeS2) free((void*) s2);
		return;
	}
	
	if (!triggered) {
		if (freeS2) free((void*) s2);
		return;
	}
	
	if (event < 0) {
		event = -event;
		tlast[event] = now;
		reset=1;
	}
	
	e->event = event;
	e->reset = reset;
	e->s = s;
	e->s2 = s2;
	e->tseq = now - last_time;
	e->tlast = now - tlast[event];
	e->tepoch = now - epoch;
	e->task = TaskName();
	
	if (evc == NEV) {
		for (i=0; i<NEV; i++) {
			e = &evs[i];
			printf("%4d %8s%c %7.3f %7.3f %9.3f %16s, %16s %s\n", i, evn[e->event], e->reset? '*':' ',
				(float) e->tlast / 1000, (float) e->tseq / 1000, (float) e->tepoch / 1000,
				e->task, e->s, e->s2);
		}
		exit(0);
	}
	
	last_time = now;
}
示例#9
0
void TaskInit()
{
	static bool init;
    TASK *t;
	
	//printf("MAX_TASKS %d\n", MAX_TASKS);
	epoch = start_us = timer_us();
	start_ms = timer_ms();
	t = Tasks;
	cur_task = cur_low = t;
	prio_low = t;
	t->next = t->prev = NULL;
	task_init(t, 0, NULL, NULL, "main", LOW_PRIORITY);
}
示例#10
0
int TaskSleep(u4_t usec)
{
    TASK *t = cur_task;

//printf("sleep T%02d %d usec\n", t->id, usec);
    t->deadline = usec? (timer_us() + usec) : 0;
    t->stopped = TRUE;
    do { NextTaskL("TaskSleep"); } while (!t->wakeup);
//printf("woke T%02d %d usec\n", t->id, usec);
//if (t->id==4 || t->id==6) printf("wo%d ", t->id); fflush(stdout);
    t->deadline = 0;
    t->stopped = FALSE;
	t->wakeup = FALSE;
	return t->wake_param;
}
示例#11
0
void pru_start()
{
    unsigned int ret;
    char *bin;
    
    tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;

    prussdrv_init();		
    if (prussdrv_open(PRU_EVTOUT_0)) panic("prussdrv_open");
    if (prussdrv_pruintc_init(&pruss_intc_initdata)) panic("prussdrv_pruintc_init");

	if (prussdrv_map_prumem(PRUSS0_PRU0_DATARAM, &pruDataMem)) panic("prussdrv_map_prumem");
    pru = (com_t *) pruDataMem;
    pru2 = (com2_t *) (pruDataMem + PRU_COM_SIZE);

	bin = background_mode? "/usr/local/bin/hp5370d_realtime.bin" : "pru/pru_realtime.bin";
    if (prussdrv_exec_program(PRU_NUM, bin)) panic("prussdrv_exec_program");
    
    u4_t key1 = timer_us();
    u4_t key2 = key1 >> 8;
    pru->p[0] = key1;
    pru->p[1] = key2;
    pru->p[2] = 0;
    pru->p[3] = 0;
    pru2->m2_offset = 0xbeefcafe;
    send_pru_cmd(PRU_PING);
    if (pru->p[2] != (key1+key2)) panic("PRU didn't start");
    if (pru->p[3] != 0xbeefcafe) panic("PRU com2_t at wrong offset?");
    send_pru_cmd(PRU_CLEAR);
    lprintf("PRU started\n");

#if 0
    prussdrv_pru_wait_event(PRU_EVTOUT_0);		// wait for halt
    prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
    prussdrv_pru_disable(PRU_NUM);
    prussdrv_exit();
#endif
}
示例#12
0
文件: NewPing.cpp 项目: kpws/Plane
void NewPing::ping_timer(void (*userFunc)(void), unsigned int updateInterval_us,unsigned int maxTime_us) {
	if (!ping_trigger(maxTime_us)) return;         // Trigger a ping, if it returns false, return without starting the echo timer.
	timer_us(updateInterval_us, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS.
    _isRunning=true;
}
示例#13
0
	void NewPing::ping_timer(void (*userFunc)(void), unsigned int max_cm_distance) {
		if (max_cm_distance > 0) set_max_distance(max_cm_distance); // Call function to set a new max sensor distance.

		if (!ping_trigger()) return;         // Trigger a ping, if it returns false, return without starting the echo timer.
		timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS.
	}
示例#14
0
static void spi_scan(SPI_MOSI *mosi, SPI_MISO *miso=&junk, int rbytes=0) {
	int i;
	
	assert(rbytes <= NSPI_RX);
	
	int tx_bytes = sizeof(SPI_MOSI);
    int tx_xfers = SPI_B2X(tx_bytes);
    
    int rx_bytes = sizeof(miso->status) + rbytes;
    int rx_xfers = SPI_B2X(rx_bytes);

    int arx_xfers = MAX(tx_xfers, prev->len_xfers);
    int arx_bytes = SPI_X2B(arx_xfers);

//jks
#if 0
static u4_t last_st;
static float acc_st, acc2_st;
static int big_rx;
if (arx_bytes > 1024) big_rx = 1;
u4_t st = timer_us();
float inc_st = (float) (st - last_st) / 1000.0;
acc_st += inc_st;
if (mosi->cmd == CmdSetWFFreq) acc2_st = 0;
printf("SCAN +%.3f %6.3f %6.3f %12s %16s tx(%dX=%dB) rx(%dX=%dB) arx(%dX=%dB)\n",
inc_st, acc_st, acc2_st, TaskName(), cmds[mosi->cmd], tx_xfers, tx_bytes, rx_xfers, rx_bytes, arx_xfers, arx_bytes);
if (mosi->cmd == CmdDuplex && big_rx) {
	acc_st = 0;
	big_rx = 0;
} else {
}
acc2_st += inc_st;
last_st = st;
#endif

//memset(miso, 0xee, sizeof(*miso));

    miso->len_xfers = rx_xfers;
    miso->cmd = mosi->cmd;
    rx_xfers = arx_xfers;

	if (mosi->cmd == CmdDuplex) mosi->cmd = CmdDummy;
	if (mosi->cmd == CmdNoDuplex) mosi->cmd = CmdDummy;

    for (;;) {
        peri_spi(SPI_HOST,
            mosi->msg, tx_xfers,   // MOSI: new request
            prev->msg, rx_xfers);  // MISO: response to previous caller's request
        evSpi(EV_SPILOOP, "spiScan", "peri_spi done");

		// fixme: understand why is this needed (hangs w/o it)
        if (spi_delay) spin_us(spi_delay); else usleep(10);
        evSpi(EV_SPILOOP, "spiScan", "spin_us done");
        if (prev->status != BUSY) break; // new request accepted?
        evSpi(EV_SPILOOP, "spiScan", "BUSY -> NextTask");
        NextTaskL("spi_scan"); // wait and try again
    }
    
    //jks
    #if 0
    printf("RX %d: ", prev->len_xfers);
    if (prev == &junk) {
    	printf("(junk) ");
    } else {
    	printf("%s ", cmds[prev->cmd]);
    }
	for (i=0; i<(prev->len_xfers+10); i++) {
		printf("%d:", i);
		#ifdef SPI_8
		printf("%02x ", prev->msg[i]);
		#endif
		#ifdef SPI_16
		printf("%04x ", prev->msg[i]);
		#endif
		#ifdef SPI_32
		printf("%08x ", prev->msg[i]);
		#endif
	}
    printf("\n");
    #endif

	u4_t status = prev->status;
    prev = miso; // next caller collects this for us
pcmd=mosi->cmd;

	//if (status & 0x0fff)
	//printf("st %04x\n", status);
	//if (mosi->cmd == CmdGetRXCount) printf("C");
	//if (mosi->cmd == CmdGetRX) printf("GRX\n");
	static int ff;
	if (status & (1<<SPI_SFT)) {
		rx0_wakeup = 1;
		evSnd(EV_SND, "wakeup", "");
		//printf(".");
		ff = 0;
	} else {
		rx0_wakeup = 0;
		if (!ff) {
			//printf(".");
			ff = 1;
		}
	}
	
	// process rx channel wakeup bits
	for (i=0; i<RX_CHANS; i++) {
		u4_t ch = 1<<(i+SPI_SFT);
		conn_t *c;
		if (status & ch) {
			c = &conns[i*2];
			assert(c->type == STREAM_SOUND);
			//if (c->task && !c->stop_data) printf("wakeup %d\n", c->task);
			//if (c->task && !c->stop_data) { printf("%d:%d ", i, c->task); fflush(stdout); }
			if (c->task && !c->stop_data) TaskWakeup(c->task, FALSE, 0);
		}
	}
}
示例#15
0
void NewPing::ping_timer(void (*userFunc)(void)) {
	ping_trigger();                      // Trigger a ping.
	if (!ping_wait()) return;            // Wait for ping to start, if it returns false, return without starting the echo timer.
	timer_us(ECHO_TIMER_FREQ, userFunc); // Set ping echo timer check every ECHO_TIMER_FREQ uS.
}
示例#16
0
/* Get charger power info in Watts.  Also returns type of charger */
int google_chromeec_get_usb_pd_power_info(enum usb_chg_type *type,
					  u32 *max_watts)
{
	struct ec_params_usb_pd_power_info req = {
		.port = PD_POWER_CHARGING_PORT,
	};
	struct ec_response_usb_pd_power_info rsp;
	struct chromeec_command cmd = {
		.cmd_code = EC_CMD_USB_PD_POWER_INFO,
		.cmd_version = 0,
		.cmd_data_in = &req,
		.cmd_size_in = sizeof(req),
		.cmd_data_out = &rsp,
		.cmd_size_out = sizeof(rsp),
		.cmd_dev_index = 0,
	};
	struct usb_chg_measures m;
	int rv = google_chromeec_command(&cmd);
	if (rv != 0)
		return rv;
	/* values are given in milliAmps and milliVolts */
	*type = rsp.type;
	m = rsp.meas;
	*max_watts = (m.current_max * m.voltage_max) / 1000000;

	return 0;
}

int google_chromeec_override_dedicated_charger_limit(u16 current_lim,
						     u16 voltage_lim)
{
	struct ec_params_dedicated_charger_limit p = {
		.current_lim = current_lim,
		.voltage_lim = voltage_lim,
	};
	struct chromeec_command cmd = {
		.cmd_code = EC_CMD_OVERRIDE_DEDICATED_CHARGER_LIMIT,
		.cmd_version = 0,
		.cmd_data_in = &p,
		.cmd_size_in = sizeof(p),
		.cmd_data_out = NULL,
		.cmd_size_out = 0,
		.cmd_dev_index = 0,
	};

	return google_chromeec_command(&cmd);
}

int google_chromeec_set_usb_pd_role(u8 port, enum usb_pd_control_role role)
{
	struct ec_params_usb_pd_control req = {
		.port = port,
		.role = role,
		.mux = USB_PD_CTRL_MUX_NO_CHANGE,
		.swap = USB_PD_CTRL_SWAP_NONE,
	};
	struct ec_response_usb_pd_control rsp;
	struct chromeec_command cmd = {
		.cmd_code = EC_CMD_USB_PD_CONTROL,
		.cmd_version = 0,
		.cmd_data_in = &req,
		.cmd_size_in = sizeof(req),
		.cmd_data_out = &rsp,
		.cmd_size_out = sizeof(rsp),
		.cmd_dev_index = 0,
	};

	return google_chromeec_command(&cmd);
}

static int google_chromeec_hello(void)
{
	struct chromeec_command cec_cmd;
	struct ec_params_hello cmd_hello;
	struct ec_response_hello rsp_hello;
	cmd_hello.in_data = 0x10203040;
	cec_cmd.cmd_code = EC_CMD_HELLO;
	cec_cmd.cmd_version = 0;
	cec_cmd.cmd_data_in = &cmd_hello.in_data;
	cec_cmd.cmd_data_out = &rsp_hello.out_data;
	cec_cmd.cmd_size_in = sizeof(cmd_hello.in_data);
	cec_cmd.cmd_size_out = sizeof(rsp_hello.out_data);
	cec_cmd.cmd_dev_index = 0;
	google_chromeec_command(&cec_cmd);
	printk(BIOS_DEBUG, "Google Chrome EC: Hello got back %x status (%x)\n",
	       rsp_hello.out_data, cec_cmd.cmd_code);
	return cec_cmd.cmd_code;
}

/* Cached EC image type (ro or rw). */
static int ec_image_type = EC_IMAGE_UNKNOWN;

static void google_chromeec_get_version(void)
{
	struct chromeec_command cec_cmd;
	struct ec_response_get_version cec_resp;
	cec_cmd.cmd_code = EC_CMD_GET_VERSION;
	cec_cmd.cmd_version = 0;
	cec_cmd.cmd_data_in = 0;
	cec_cmd.cmd_data_out = &cec_resp;
	cec_cmd.cmd_size_in = 0;
	cec_cmd.cmd_size_out = sizeof(cec_resp);
	cec_cmd.cmd_dev_index = 0;
	google_chromeec_command(&cec_cmd);

	if (cec_cmd.cmd_code) {
		printk(BIOS_DEBUG,
		       "Google Chrome EC: version command failed!\n");
	} else {
		printk(BIOS_DEBUG, "Google Chrome EC: version:\n");
		printk(BIOS_DEBUG, "    ro: %s\n", cec_resp.version_string_ro);
		printk(BIOS_DEBUG, "    rw: %s\n", cec_resp.version_string_rw);
		printk(BIOS_DEBUG, "  running image: %d\n",
		       cec_resp.current_image);
		ec_image_type = cec_resp.current_image;
	}
}

void google_chromeec_init(void)
{
	printk(BIOS_DEBUG, "Google Chrome EC: Initializing\n");

	google_chromeec_hello();

	/* Get version to check which EC image is active */
	google_chromeec_get_version();

	/* Check/update EC RW image if needed */
	if (google_chromeec_swsync()) {
		printk(BIOS_ERR, "ChromeEC: EC SW SYNC FAILED\n");
	} else if (ec_image_type != EC_IMAGE_RW) {
		/* EC RW image is up to date, switch to it if not already*/
		google_chromeec_reboot(0, EC_REBOOT_JUMP_RW, 0);
		mdelay(100);
		/* Use Hello cmd to "reset" EC now in RW mode */
		google_chromeec_hello();
		/* re-run version command & print */
		google_chromeec_get_version();
	}
}

int google_ec_running_ro(void)
{
	return (ec_image_type == EC_IMAGE_RO);
}

void google_chromeec_reboot_ro(void)
{
	/* Reboot the EC and make it come back in RO mode */
	printk(BIOS_DEBUG, "Rebooting with EC in RO mode:\n");
	post_code(0); /* clear current post code */
	google_chromeec_reboot(0, EC_REBOOT_COLD, 0);
	udelay(1000);
	board_reset();
	halt();
}

/* Timeout waiting for EC hash calculation completion */
static const int CROS_EC_HASH_TIMEOUT_MS = 2000;

/* Time to delay between polling status of EC hash calculation */
static const int CROS_EC_HASH_CHECK_DELAY_MS = 10;

int google_chromeec_swsync(void)
{
	static struct ec_response_vboot_hash resp;
	uint8_t *ec_hash;
	int ec_hash_size;
	uint8_t *ecrw_hash, *ecrw;
	int need_update = 0, i;
	size_t ecrw_size;

	/* skip if on S3 resume path */
	if (acpi_is_wakeup_s3())
		return 0;

	/* Get EC_RW hash from CBFS */
	ecrw_hash = cbfs_boot_map_with_leak("ecrw.hash", CBFS_TYPE_RAW, NULL);

	if (!ecrw_hash) {
		/* Assume no EC update file for this board */
		printk(BIOS_DEBUG, "ChromeEC SW Sync: no EC_RW update available\n");
		return 0;
	}

	/* Got an expected hash */
	printk(BIOS_DEBUG, "ChromeEC SW Sync: Expected hash: ");
	for (i = 0; i < SHA256_DIGEST_SIZE; i++)
		printk(BIOS_DEBUG, "%02x", ecrw_hash[i]);
	printk(BIOS_DEBUG, "\n");

	/* Get hash of current EC-RW */
	if (google_chromeec_read_hash(&resp)) {
		printk(BIOS_ERR, "Failed to read current EC_RW hash.\n");
		return -1;
	}
	ec_hash = resp.hash_digest;
	ec_hash_size = resp.digest_size;
	/* Check hash size */
	if (ec_hash_size != SHA256_DIGEST_SIZE) {
		printk(BIOS_ERR, "ChromeEC SW Sync: - "
			 "read_hash says size %d, not %d\n",
			 ec_hash_size, SHA256_DIGEST_SIZE);
		return -1;
	}

	/* We got a proper hash */
	printk(BIOS_DEBUG, "ChromeEC SW Sync: current EC_RW hash: ");
	for (i = 0; i < SHA256_DIGEST_SIZE; i++)
		printk(BIOS_DEBUG, "%02x", ec_hash[i]);
	printk(BIOS_DEBUG, "\n");

	/* compare hashes */
	need_update = SafeMemcmp(ec_hash, ecrw_hash, SHA256_DIGEST_SIZE);

	/* If in RW and need to update, return/reboot to RO */
	if (need_update && ec_image_type == EC_IMAGE_RW) {
		printk(BIOS_DEBUG, "ChromeEC SW Sync: EC_RW needs update but in RW; rebooting to RO\n");
		google_chromeec_reboot_ro();
		return -1;
	}

	/* Update EC if necessary */
	if (need_update) {
		printk(BIOS_DEBUG, "ChromeEC SW Sync: updating EC_RW...\n");

		/* Get ecrw image from CBFS */
		ecrw = cbfs_boot_map_with_leak("ecrw", CBFS_TYPE_RAW, &ecrw_size);
		if (!ecrw) {
			printk(BIOS_ERR, "ChromeEC SW Sync: no ecrw image found in CBFS; cannot update\n");
			return -1;
		}

		if (google_chromeec_flash_update_rw(ecrw, ecrw_size)) {
			printk(BIOS_ERR, "ChromeEC SW Sync: Failed to update EC_RW.\n");
			return -1;
		}

		/* Have EC recompute hash for new EC_RW block */
		if (google_chromeec_read_hash(&resp) ) {
			printk(BIOS_ERR, "ChromeEC SW Sync: Failed to read new EC_RW hash.\n");
			return -1;
		}

		/* Compare new EC_RW hash to value from CBFS */
		ec_hash = resp.hash_digest;
		if(SafeMemcmp(ec_hash, ecrw_hash, SHA256_DIGEST_SIZE)) {
			/* hash mismatch! */
			printk(BIOS_DEBUG, "ChromeEC SW Sync: Expected hash: ");
			for (i = 0; i < SHA256_DIGEST_SIZE; i++)
				printk(BIOS_DEBUG, "%02x", ecrw_hash[i]);
			printk(BIOS_DEBUG, "\n");
			printk(BIOS_DEBUG, "ChromeEC SW Sync: EC hash: ");
			for (i = 0; i < SHA256_DIGEST_SIZE; i++)
				printk(BIOS_DEBUG, "%02x", ec_hash[i]);
			printk(BIOS_DEBUG, "\n");
			return -1;
		}
		printk(BIOS_DEBUG, "ChromeEC SW Sync: EC_RW hashes match\n");
		printk(BIOS_DEBUG, "ChromeEC SW Sync: done\n");
	} else {
		printk(BIOS_DEBUG, "ChromeEC SW Sync: EC_RW is up to date\n");
	}

	return 0;
}

int google_chromeec_read_hash(struct ec_response_vboot_hash *hash)
{
	struct chromeec_command cec_cmd;
	struct ec_params_vboot_hash p;
	int recalc_requested = 0;
	uint64_t start = timer_us(0);

	do {
		/* Get hash if available. */
		p.cmd = EC_VBOOT_HASH_GET;
		cec_cmd.cmd_code = EC_CMD_VBOOT_HASH;
		cec_cmd.cmd_version = 0;
		cec_cmd.cmd_data_in = &p;
		cec_cmd.cmd_data_out = hash;
		cec_cmd.cmd_size_in = sizeof(p);
		cec_cmd.cmd_size_out = sizeof(*hash);
		cec_cmd.cmd_dev_index = 0;
		printk(BIOS_DEBUG, "ChromeEC: Getting hash:\n");
		if (google_chromeec_command(&cec_cmd))
			return -1;

		switch (hash->status) {
		case EC_VBOOT_HASH_STATUS_NONE:
			/* We have no valid hash - let's request a recalc
			 * if we haven't done so yet. */
			if (recalc_requested != 0) {
				mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
				break;
			}
			printk(BIOS_DEBUG, "ChromeEC: No valid hash (status=%d size=%d). "
			      "Compute one...\n", hash->status, hash->size);
			p.cmd = EC_VBOOT_HASH_RECALC;
			p.hash_type = EC_VBOOT_HASH_TYPE_SHA256;
			p.nonce_size = 0;
			p.offset = EC_VBOOT_HASH_OFFSET_RW;
			p.size = 0;
			cec_cmd.cmd_code = EC_CMD_VBOOT_HASH;
			cec_cmd.cmd_version = 0;
			cec_cmd.cmd_data_in = &p;
			cec_cmd.cmd_data_out = hash;
			cec_cmd.cmd_size_in = sizeof(p);
			cec_cmd.cmd_size_out = sizeof(*hash);
			cec_cmd.cmd_dev_index = 0;
			printk(BIOS_DEBUG, "ChromeEC: Starting EC hash:\n");
			if (google_chromeec_command(&cec_cmd))
				return -1;
			recalc_requested = 1;
			/* Command will wait to return until hash is done/ready */
			break;
		case EC_VBOOT_HASH_STATUS_BUSY:
			/* Hash is still calculating. */
			mdelay(CROS_EC_HASH_CHECK_DELAY_MS);
			break;
		case EC_VBOOT_HASH_STATUS_DONE:
		default:
			/* We have a valid hash. */
			break;
		}
	} while (hash->status != EC_VBOOT_HASH_STATUS_DONE &&
		 timer_us(start) < CROS_EC_HASH_TIMEOUT_MS * 1000);
	if (hash->status != EC_VBOOT_HASH_STATUS_DONE) {
		printk(BIOS_DEBUG, "ChromeEC: Hash status not done: %d\n", hash->status);
		return -1;
	}
	return 0;
}

int google_chromeec_flash_update_rw(const uint8_t *image, int image_size)
{
	uint32_t rw_offset, rw_size;
	int ret;

	/* get max size that can be written, offset to write */
	if (google_chromeec_flash_offset(EC_FLASH_REGION_RW, &rw_offset, &rw_size))
		return -1;
	if (image_size > rw_size)
		return -1;
	/*
	 * Erase the entire RW section, so that the EC doesn't see any garbage
	 * past the new image if it's smaller than the current image.
	 *
	 */
	ret = google_chromeec_flash_erase(rw_offset, rw_size);
	if (ret)
		return ret;
	/* Write the image */
	return(google_chromeec_flash_write(image, rw_offset, image_size));
}
示例#17
0
 void _NextTaskL()
#endif
{
	int i;
    TASK *t, *tn;
    u4_t now, quanta;

	t = cur_task;

    // don't switch until quanta expired (if any)
    if (t->quanta && ((timer_ms() - start_ms) < t->quanta))
    	return;
    
    ev(EV_NEXTTASK, "NextTask", "");
    
    now = timer_us();
    quanta = now - start_us;
    t->usec += quanta;
	
    if (slice) {
    	TSLICE *ts = &slices[slice-1];
    	ts->id = t->id;
    	ts->usec = quanta;
    	ts->wakeup = rx0_wakeup;
    	ts->twoke = now - rx0_twoke;
    	
    	#ifdef DEBUG
    		ts->s = s;
    	#endif
    	
    	slice++;
    	
    	if (slice == NSLICES) {
    		u4_t maxv=0; int maxi=0;
    		for (i=0; i<NSLICES; i++) {
    			ts = &slices[i];
    			if (ts->usec > maxv) { maxv = ts->usec; maxi = i; }
    		}
    		for (i=0; i<NSLICES; i++) {
    			ts = &slices[i];
    			printf("%4d T%02d %7.3f %7.3f w%d %s %s %s %s\n",
    				i, ts->id, ((float) ts->usec) / 1e3, ((float) ts->twoke) / 1e3,
    				ts->wakeup, Tasks[ts->id].name,
    				ts->s? ts->s : "", ts->msg,
    				(i==maxi)? "############################################": (
    				(ts->usec>=2000.0)? "------------------------------------------":"") );
    		}
    		xit(0);
    		slice = 0;
    	}
    }
    
    if (setjmp(t->jb)) {
    	return;
    }
    
	//printf("P%d-%s %.3f ms pc %p\n", t->id, t->name, ((float) quanta) / 1e3, (void *) t->pc); fflush(stdout);
    
    for (i=0; i<MAX_TASKS; i++) {
    	TASK *tp = Tasks + i;
    	if (tp->valid && tp->deadline && (tp->deadline < now)) {
    		tp->deadline = 0;
    		tp->stopped = FALSE;
    		tp->wakeup = TRUE;
//printf("wake T%02d\n", tp->id);
    	}
    }
    
    if (t->priority == HIGH_PRIORITY) {
		do {	// after a high priority finishes run next high priority
			t = t->next;
		} while (t && t->stopped);
		
    	if (!t) {	// no other high priority, so run next low priority
    		t = cur_low;
    		do {
    			t = t->next;
    			if (!t) t = prio_low;
    		} while (t->stopped);
    	}
    } else {
    	// run _all_ high priority after each low priority finishes
		for (t = prio_high; t && t->stopped; t = t->next)
			;
    	if (!t) {	// no high priority so run next low priority
    		t = cur_task;
    		do {
    			t = t->next;
    			if (!t) t = prio_low;
    		} while (t->stopped);
    	}
    }

    cur_task = t;
    if (t->priority == LOW_PRIORITY) cur_low = t;
    t->run++;

	//printf("N%d-%s pc %p\n", t->id, t->name, (void *) t->pc); fflush(stdout);
	start_us = now;
	if (t->quanta) start_ms = timer_ms();
    longjmp(t->jb, 1);
}
示例#18
0
static int i2ctpm_xmit(TpmOps *me, const uint8_t *sendbuf, size_t sbuf_size,
		       uint8_t *recvbuf, size_t *rbuf_len)
{
	I2cTpm *tpm = container_of(me, I2cTpm, ops);

	if (!tpm->initialized && i2ctpm_init(tpm))
		return -1;

	uint32_t count, ordinal;
	memcpy(&count, sendbuf + TpmCmdCountOffset, sizeof(count));
	count = betohl(count);
	memcpy(&ordinal, sendbuf + TpmCmdOrdinalOffset, sizeof(ordinal));
	ordinal = betohl(ordinal);

	if (count == 0) {
		printf("%s: No data.\n", __func__);
		return -1;
	}
	if (count > sbuf_size) {
		printf("%s: Invalid count value %x, max %zx.\n", __func__,
			count, sbuf_size);
		return -1;
	}

	assert(tpm->chip_ops.send);
	ssize_t rc = tpm->chip_ops.send(&tpm->chip_ops, sendbuf, count);
	if (rc < 0) {
		printf("%s: tpm_send: error %zd\n", __func__, rc);
		*rbuf_len = 0;
		return -1;
	}

	uint64_t start = timer_us(0);
	while (1) {
		assert(tpm->chip_ops.status);
		uint8_t status = tpm->chip_ops.status(&tpm->chip_ops);
		if ((status & tpm->req_complete_mask) ==
				tpm->req_complete_val) {
			break;
		}

		if (status == tpm->req_canceled) {
			printf("%s: Operation canceled.\n", __func__);
			return -1;
		}
		mdelay(1);

		// Two minute timeout.
		if (timer_us(start) > 2 * 60 * 1000 * 1000) {
			if (tpm->chip_ops.cancel)
				tpm->chip_ops.cancel(&tpm->chip_ops);
			printf("%s: Operation timed out.\n", __func__);
			return -1;
		}
	}

	ssize_t len = tpm->chip_ops.recv(&tpm->chip_ops, recvbuf, *rbuf_len);
	if (len < 0) {
		printf("%s: tpm_recv: error %zd\n", __func__, len);
		*rbuf_len = 0;
		return -1;
	}

	if (len < 10) {
		printf("%s: Too few bytes received (%zd).\n", __func__, len);
		*rbuf_len = 0;
		return -1;
	}

	if (len > *rbuf_len) {
		printf("%s: Too many bytes received (%zd).\n", __func__, len);
		*rbuf_len = len;
		return -1;
	}

	*rbuf_len = len;
	return 0;
}