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)); }
/* 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; }
/* 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)); }
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); }
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)); }
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); }