pdc_stable.c
字号:
return -ENODATA; for (i = 0; devpath->layers[i] && (likely(i < 6)); i++) out += sprintf(out, "%u ", devpath->layers[i]); out += sprintf(out, "\n"); return out - buf;}/** * pdcspath_layer_write - This function handles extended layer modifying. * @entry: An allocated and populated pdscpath_entry struct. * @buf: The input buffer to read from. * @count: The number of bytes to be read. * * We will call this function to change the current layer value. * Layers are to be given '.'-delimited, without brackets. * XXX beware we are far less checky WRT input data provided than for hwpath. * Potential harm can be done, since there's no way to check the validity of * the layer fields. */static ssize_tpdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count){ unsigned int layers[6]; /* device-specific info (ctlr#, unit#, ...) */ unsigned short i; char in[count+1], *temp; if (!entry || !buf || !count) return -EINVAL; /* We'll use a local copy of buf */ memset(in, 0, count+1); strncpy(in, buf, count); /* Let's clean up the target. 0 is a blank pattern */ memset(&layers, 0, sizeof(layers)); /* First, pick the first layer */ if (unlikely(!isdigit(*in))) return -EINVAL; layers[0] = simple_strtoul(in, NULL, 10); DPRINTK("%s: layer[0]: %d\n", __func__, layers[0]); temp = in; for (i=1; ((temp = strchr(temp, '.'))) && (likely(i<6)); i++) { if (unlikely(!isdigit(*(++temp)))) return -EINVAL; layers[i] = simple_strtoul(temp, NULL, 10); DPRINTK("%s: layer[%d]: %d\n", __func__, i, layers[i]); } /* So far so good, let's get in deep */ write_lock(&entry->rw_lock); /* First, overwrite the current layers with the new ones, not touching the hardware path. */ memcpy(&entry->devpath.layers, &layers, sizeof(layers)); /* Now, dive in. Write back to the hardware */ pdcspath_store(entry); write_unlock(&entry->rw_lock); printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" layers to \"%s\"\n", entry->name, buf); return count;}/** * pdcspath_attr_show - Generic read function call wrapper. * @kobj: The kobject to get info from. * @attr: The attribute looked upon. * @buf: The output buffer. */static ssize_tpdcspath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf){ struct pdcspath_entry *entry = to_pdcspath_entry(kobj); struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr); ssize_t ret = 0; if (pdcs_attr->show) ret = pdcs_attr->show(entry, buf); return ret;}/** * pdcspath_attr_store - Generic write function call wrapper. * @kobj: The kobject to write info to. * @attr: The attribute to be modified. * @buf: The input buffer. * @count: The size of the buffer. */static ssize_tpdcspath_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count){ struct pdcspath_entry *entry = to_pdcspath_entry(kobj); struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr); ssize_t ret = 0; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (pdcs_attr->store) ret = pdcs_attr->store(entry, buf, count); return ret;}static struct sysfs_ops pdcspath_attr_ops = { .show = pdcspath_attr_show, .store = pdcspath_attr_store,};/* These are the two attributes of any PDC path. */static PATHS_ATTR(hwpath, 0644, pdcspath_hwpath_read, pdcspath_hwpath_write);static PATHS_ATTR(layer, 0644, pdcspath_layer_read, pdcspath_layer_write);static struct attribute *paths_subsys_attrs[] = { &paths_attr_hwpath.attr, &paths_attr_layer.attr, NULL,};/* Specific kobject type for our PDC paths */static struct kobj_type ktype_pdcspath = { .sysfs_ops = &pdcspath_attr_ops, .default_attrs = paths_subsys_attrs,};/* We hard define the 4 types of path we expect to find */static PDCSPATH_ENTRY(PDCS_ADDR_PPRI, primary);static PDCSPATH_ENTRY(PDCS_ADDR_PCON, console);static PDCSPATH_ENTRY(PDCS_ADDR_PALT, alternative);static PDCSPATH_ENTRY(PDCS_ADDR_PKBD, keyboard);/* An array containing all PDC paths we will deal with */static struct pdcspath_entry *pdcspath_entries[] = { &pdcspath_entry_primary, &pdcspath_entry_alternative, &pdcspath_entry_console, &pdcspath_entry_keyboard, NULL,};/* For more insight of what's going on here, refer to PDC Procedures doc, * Section PDC_STABLE *//** * pdcs_size_read - Stable Storage size output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. */static ssize_tpdcs_size_read(struct kset *kset, char *buf){ char *out = buf; if (!kset || !buf) return -EINVAL; /* show the size of the stable storage */ out += sprintf(out, "%ld\n", pdcs_size); return out - buf;}/** * pdcs_auto_read - Stable Storage autoboot/search flag output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. * @knob: The PF_AUTOBOOT or PF_AUTOSEARCH flag */static ssize_tpdcs_auto_read(struct kset *kset, char *buf, int knob){ char *out = buf; struct pdcspath_entry *pathentry; if (!kset || !buf) return -EINVAL; /* Current flags are stored in primary boot path entry */ pathentry = &pdcspath_entry_primary; read_lock(&pathentry->rw_lock); out += sprintf(out, "%s\n", (pathentry->devpath.flags & knob) ? "On" : "Off"); read_unlock(&pathentry->rw_lock); return out - buf;}/** * pdcs_autoboot_read - Stable Storage autoboot flag output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. */static inline ssize_tpdcs_autoboot_read(struct kset *kset, char *buf){ return pdcs_auto_read(kset, buf, PF_AUTOBOOT);}/** * pdcs_autosearch_read - Stable Storage autoboot flag output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. */static inline ssize_tpdcs_autosearch_read(struct kset *kset, char *buf){ return pdcs_auto_read(kset, buf, PF_AUTOSEARCH);}/** * pdcs_timer_read - Stable Storage timer count output (in seconds). * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. * * The value of the timer field correponds to a number of seconds in powers of 2. */static ssize_tpdcs_timer_read(struct kset *kset, char *buf){ char *out = buf; struct pdcspath_entry *pathentry; if (!kset || !buf) return -EINVAL; /* Current flags are stored in primary boot path entry */ pathentry = &pdcspath_entry_primary; /* print the timer value in seconds */ read_lock(&pathentry->rw_lock); out += sprintf(out, "%u\n", (pathentry->devpath.flags & PF_TIMER) ? (1 << (pathentry->devpath.flags & PF_TIMER)) : 0); read_unlock(&pathentry->rw_lock); return out - buf;}/** * pdcs_osid_read - Stable Storage OS ID register output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. */static ssize_tpdcs_osid_read(struct kset *kset, char *buf){ char *out = buf; if (!kset || !buf) return -EINVAL; out += sprintf(out, "%s dependent data (0x%.4x)\n", os_id_to_string(pdcs_osid), pdcs_osid); return out - buf;}/** * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. * * This can hold 16 bytes of OS-Dependent data. */static ssize_tpdcs_osdep1_read(struct kset *kset, char *buf){ char *out = buf; u32 result[4]; if (!kset || !buf) return -EINVAL; if (pdc_stable_read(PDCS_ADDR_OSD1, &result, sizeof(result)) != PDC_OK) return -EIO; out += sprintf(out, "0x%.8x\n", result[0]); out += sprintf(out, "0x%.8x\n", result[1]); out += sprintf(out, "0x%.8x\n", result[2]); out += sprintf(out, "0x%.8x\n", result[3]); return out - buf;}/** * pdcs_diagnostic_read - Stable Storage Diagnostic register output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. * * I have NFC how to interpret the content of that register ;-). */static ssize_tpdcs_diagnostic_read(struct kset *kset, char *buf){ char *out = buf; u32 result; if (!kset || !buf) return -EINVAL; /* get diagnostic */ if (pdc_stable_read(PDCS_ADDR_DIAG, &result, sizeof(result)) != PDC_OK) return -EIO; out += sprintf(out, "0x%.4x\n", (result >> 16)); return out - buf;}/** * pdcs_fastsize_read - Stable Storage FastSize register output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. * * This register holds the amount of system RAM to be tested during boot sequence. */static ssize_tpdcs_fastsize_read(struct kset *kset, char *buf){ char *out = buf; u32 result; if (!kset || !buf) return -EINVAL; /* get fast-size */ if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK) return -EIO; if ((result & 0x0F) < 0x0E) out += sprintf(out, "%d kB", (1<<(result & 0x0F))*256); else out += sprintf(out, "All"); out += sprintf(out, "\n"); return out - buf;}/** * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output. * @kset: An allocated and populated struct kset. We don't use it tho. * @buf: The output buffer to write to. * * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available. */static ssize_tpdcs_osdep2_read(struct kset *kset, char *buf){ char *out = buf; unsigned long size; unsigned short i; u32 result; if (unlikely(pdcs_size <= 224)) return -ENODATA; size = pdcs_size - 224; if (!kset || !buf) return -EINVAL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -