static int
nexus_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct efi_tm tm;

	efi_get_time(&tm);

	/*
	 * This code was written in 2005, so logically EFI cannot return
	 * a year smaller than that. Assume the EFI clock is out of whack
	 * in that case and reset the EFI clock.
	 */
	if (tm.tm_year < 2005)
		return (EINVAL);

	ct.nsec = tm.tm_nsec;
	ct.sec = tm.tm_sec;
	ct.min = tm.tm_min;
	ct.hour = tm.tm_hour;
	ct.day = tm.tm_mday;
	ct.mon = tm.tm_mon;
	ct.year = tm.tm_year;
	ct.dow = -1;
	return (clock_ct_to_ts(&ct, ts));
}
Exemple #2
0
/* not static: needed by APM */
unsigned long get_cmos_time(void)
{
	unsigned long retval;

	spin_lock(&rtc_lock);

	if (efi_enabled)
		retval = efi_get_time();
	else
		retval = mach_get_cmos_time();

	spin_unlock(&rtc_lock);

	return retval;
}
Exemple #3
0
/* not static: needed by APM */
unsigned long get_cmos_time(void)
{
	unsigned long retval;
	unsigned long flags;

	spin_lock_irqsave(&rtc_lock, flags);

	if (use_kvm_time)
		retval = kvm_get_wallclock();
	else if (efi_enabled)
		retval = efi_get_time();
	else
		retval = mach_get_cmos_time();

	spin_unlock_irqrestore(&rtc_lock, flags);

	return retval;
}
/* XXX debug stuff */
static int
efi_time_sysctl_handler(SYSCTL_HANDLER_ARGS)
{
	struct efi_tm tm;
	int error, val;

	val = 0;
	error = sysctl_handle_int(oidp, &val, 0, req);
	if (error != 0 || req->newptr == NULL)
		return (error);
	error = efi_get_time(&tm);
	if (error == 0) {
		uprintf("EFI reports: Year %d Month %d Day %d Hour %d Min %d "
		    "Sec %d\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
		    tm.tm_min, tm.tm_sec);
	}
	return (error);
}
static int
nexus_settime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct efi_tm tm;

	efi_get_time(&tm);

	clock_ts_to_ct(ts, &ct);
	tm.tm_nsec = ts->tv_nsec;
	tm.tm_sec = ct.sec;
	tm.tm_min = ct.min;
	tm.tm_hour = ct.hour;
	tm.tm_year = ct.year;
	tm.tm_mon = ct.mon;
	tm.tm_mday = ct.day;
	return (efi_set_time(&tm));
}
Exemple #6
0
static int
efirtc_probe(device_t dev)
{
	struct efi_tm tm;
	int error;

	/*
	 * Check whether we can read the time.  This will stop us from attaching
	 * when there is EFI Runtime support but the gettime function is
	 * unimplemented, e.g. on some builds of U-Boot.
	 */
	if ((error = efi_get_time(&tm)) != 0) {
		if (bootverbose)
			device_printf(dev, "cannot read EFI realtime clock\n");
		return (error);
	}
	device_set_desc(dev, "EFI Realtime Clock");
	return (BUS_PROBE_DEFAULT);
}
Exemple #7
0
static int
efirtc_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct efi_tm tm;
	int error;

	error = efi_get_time(&tm);
	if (error != 0)
		return (error);

	ct.sec = tm.tm_sec;
	ct.min = tm.tm_min;
	ct.hour = tm.tm_hour;
	ct.day = tm.tm_mday;
	ct.mon = tm.tm_mon;
	ct.year = tm.tm_year;
	ct.nsec = tm.tm_nsec;

	clock_dbgprint_ct(dev, CLOCK_DBG_READ, &ct);
	return (clock_ct_to_ts(&ct, ts));
}
Exemple #8
0
static int
efidev_ioctl(struct dev_ioctl_args *ap)
{
	u_long cmd = ap->a_cmd;
	caddr_t addr = ap->a_data;
	int error;

	switch (cmd) {
	case EFIIOC_GET_TABLE:
	{
		struct efi_get_table_ioc *egtioc =
		    (struct efi_get_table_ioc *)addr;

		error = efi_get_table(&egtioc->uuid, &egtioc->ptr);
		break;
	}
	case EFIIOC_GET_TIME:
	{
		struct efi_tm *tm = (struct efi_tm *)addr;

		error = efi_get_time(tm);
		break;
	}
	case EFIIOC_SET_TIME:
	{
		struct efi_tm *tm = (struct efi_tm *)addr;

		error = efi_set_time(tm);
		break;
	}
	case EFIIOC_VAR_GET:
	{
		struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
		void *data;
		efi_char *name;

		data = kmalloc(ev->datasize, M_TEMP, M_WAITOK);
		name = kmalloc(ev->namesize, M_TEMP, M_WAITOK);
		error = copyin(ev->name, name, ev->namesize);
		if (error)
			goto vg_out;
		if (name[ev->namesize / sizeof(efi_char) - 1] != 0) {
			error = EINVAL;
			goto vg_out;
		}

		error = efi_var_get(name, &ev->vendor, &ev->attrib,
		    &ev->datasize, data);

		if (error == 0) {
			error = copyout(data, ev->data, ev->datasize);
		} else if (error == EOVERFLOW) {
			/*
			 * Pass back the size we really need, but
			 * convert the error to 0 so the copyout
			 * happens. datasize was updated in the
			 * efi_var_get call.
			 */
			ev->data = NULL;
			error = 0;
		}
vg_out:
		kfree(data, M_TEMP);
		kfree(name, M_TEMP);
		break;
	}
	case EFIIOC_VAR_NEXT:
	{
		struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
		efi_char *name;

		name = kmalloc(ev->namesize, M_TEMP, M_WAITOK);
		error = copyin(ev->name, name, ev->namesize);
		if (error)
			goto vn_out;
		/* Note: namesize is the buffer size, not the string lenght */

		error = efi_var_nextname(&ev->namesize, name, &ev->vendor);
		if (error == 0) {
			error = copyout(name, ev->name, ev->namesize);
		} else if (error == EOVERFLOW) {
			ev->name = NULL;
			error = 0;
		}
	vn_out:
		kfree(name, M_TEMP);
		break;
	}
	case EFIIOC_VAR_SET:
	{
		struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
		void *data = NULL;
		efi_char *name;

		/* datasize == 0 -> delete (more or less) */
		if (ev->datasize > 0)
			data = kmalloc(ev->datasize, M_TEMP, M_WAITOK);
		name = kmalloc(ev->namesize, M_TEMP, M_WAITOK);
		if (ev->datasize) {
			error = copyin(ev->data, data, ev->datasize);
			if (error)
				goto vs_out;
		}
		error = copyin(ev->name, name, ev->namesize);
		if (error)
			goto vs_out;
		if (name[ev->namesize / sizeof(efi_char) - 1] != 0) {
			error = EINVAL;
			goto vs_out;
		}

		error = efi_var_set(name, &ev->vendor, ev->attrib, ev->datasize,
		    data);
vs_out:
		kfree(data, M_TEMP);
		kfree(name, M_TEMP);
		break;
	}
	default:
		error = ENOTTY;
		break;
	}

	return (error);
}