static int efirtc_settime(device_t dev, struct timespec *ts) { struct clocktime ct; struct efi_tm tm; /* * We request a timespec with no resolution-adjustment so that we can * apply it ourselves based on whether or not the clock zeroes the * sub-second part of the time when setting the time. */ ts->tv_sec -= utc_offset(); if (!efirtc_zeroes_subseconds) timespecadd(ts, &efirtc_resadj); clock_ts_to_ct(ts, &ct); clock_dbgprint_ct(dev, CLOCK_DBG_WRITE, &ct); bzero(&tm, sizeof(tm)); tm.tm_sec = ct.sec; tm.tm_min = ct.min; tm.tm_hour = ct.hour; tm.tm_mday = ct.day; tm.tm_mon = ct.mon; tm.tm_year = ct.year; tm.tm_nsec = ct.nsec; return (efi_set_time(&tm)); }
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 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); }