aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThibaut Varene <varenet@parisc-linux.org>2006-05-04 20:43:34 -0400
committerKyle McMartin <kyle@hera.kernel.org>2006-06-27 19:28:38 -0400
commit3f9edb53f74b4e18f92783da7b6f5ad1d36e05b2 (patch)
tree7cb0b21f835122d0de3c25e49c770cb0694cfb26
parent9b0703fed7ca1af95d4454f45e2f25733f0afa76 (diff)
[PARISC] pdc_stable version 0.30
pdc_stable v0.30: This patch introduces 3 more files to the /sys/firmware/stable tree: - diagnostic, which contains a cryptic hex string - osdep1, a 16 bytes os-dependent storage area always available - osdep2, another os-dependent storage area which existence/size depends on hversion. This patch also adds code to setup the "Linux" signature in stable storage. That is to say that starting with this patch, the kernel will now sign its OSID (0x0006, thx LaMont) in Stable Storage upon boot, whether pdc_stable is enabled or not. Signed-off-by: Thibaut VARENE <varenet@parisc-linux.org> Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
-rw-r--r--arch/parisc/kernel/setup.c5
-rw-r--r--drivers/parisc/pdc_stable.c219
2 files changed, 210 insertions, 14 deletions
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 4a36ec3f6ac1..8471486a7565 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -303,6 +303,8 @@ extern void eisa_init(void);
303 303
304static int __init parisc_init(void) 304static int __init parisc_init(void)
305{ 305{
306 u32 osid = (0x0006 << 16);
307
306 parisc_proc_mkdir(); 308 parisc_proc_mkdir();
307 parisc_init_resources(); 309 parisc_init_resources();
308 do_device_inventory(); /* probe for hardware */ 310 do_device_inventory(); /* probe for hardware */
@@ -311,6 +313,9 @@ static int __init parisc_init(void)
311 313
312 /* set up a new led state on systems shipped LED State panel */ 314 /* set up a new led state on systems shipped LED State panel */
313 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART); 315 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
316
317 /* tell PDC we're Linux. Nevermind failure. */
318 pdc_stable_write(0x40, &osid, sizeof(osid));
314 319
315 processor_init(); 320 processor_init();
316 printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n", 321 printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index bbeabe3fc4c6..4b991d50e578 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -28,8 +28,15 @@
28 * following code can deal with just 96 bytes of Stable Storage, and all 28 * following code can deal with just 96 bytes of Stable Storage, and all
29 * sizes between 96 and 192 bytes (provided they are multiple of struct 29 * sizes between 96 and 192 bytes (provided they are multiple of struct
30 * device_path size, eg: 128, 160 and 192) to provide full information. 30 * device_path size, eg: 128, 160 and 192) to provide full information.
31 * The code makes no use of data above 192 bytes. One last word: there's one 31 * One last word: there's one path we can always count on: the primary path.
32 * path we can always count on: the primary path. 32 * Anything above 224 bytes is used for 'osdep2' OS-dependent storage area.
33 *
34 * The first OS-dependent area should always be available. Obviously, this is
35 * not true for the other one. Also bear in mind that reading/writing from/to
36 * osdep2 is much more expensive than from/to osdep1.
37 * NOTE: We do not handle the 2 bytes OS-dep area at 0x5D, nor the first
38 * 2 bytes of storage available right after OSID. That's a total of 4 bytes
39 * sacrificed: -ETOOLAZY :P
33 * 40 *
34 * The current policy wrt file permissions is: 41 * The current policy wrt file permissions is:
35 * - write: root only 42 * - write: root only
@@ -64,15 +71,18 @@
64#include <asm/uaccess.h> 71#include <asm/uaccess.h>
65#include <asm/hardware.h> 72#include <asm/hardware.h>
66 73
67#define PDCS_VERSION "0.22" 74#define PDCS_VERSION "0.30"
68#define PDCS_PREFIX "PDC Stable Storage" 75#define PDCS_PREFIX "PDC Stable Storage"
69 76
70#define PDCS_ADDR_PPRI 0x00 77#define PDCS_ADDR_PPRI 0x00
71#define PDCS_ADDR_OSID 0x40 78#define PDCS_ADDR_OSID 0x40
79#define PDCS_ADDR_OSD1 0x48
80#define PDCS_ADDR_DIAG 0x58
72#define PDCS_ADDR_FSIZ 0x5C 81#define PDCS_ADDR_FSIZ 0x5C
73#define PDCS_ADDR_PCON 0x60 82#define PDCS_ADDR_PCON 0x60
74#define PDCS_ADDR_PALT 0x80 83#define PDCS_ADDR_PALT 0x80
75#define PDCS_ADDR_PKBD 0xA0 84#define PDCS_ADDR_PKBD 0xA0
85#define PDCS_ADDR_OSD2 0xE0
76 86
77MODULE_AUTHOR("Thibaut VARENE <varenet@parisc-linux.org>"); 87MODULE_AUTHOR("Thibaut VARENE <varenet@parisc-linux.org>");
78MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data"); 88MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
@@ -82,6 +92,9 @@ MODULE_VERSION(PDCS_VERSION);
82/* holds Stable Storage size. Initialized once and for all, no lock needed */ 92/* holds Stable Storage size. Initialized once and for all, no lock needed */
83static unsigned long pdcs_size __read_mostly; 93static unsigned long pdcs_size __read_mostly;
84 94
95/* holds OS ID. Initialized once and for all, hopefully to 0x0006 */
96static u16 pdcs_osid __read_mostly;
97
85/* This struct defines what we need to deal with a parisc pdc path entry */ 98/* This struct defines what we need to deal with a parisc pdc path entry */
86struct pdcspath_entry { 99struct pdcspath_entry {
87 rwlock_t rw_lock; /* to protect path entry access */ 100 rwlock_t rw_lock; /* to protect path entry access */
@@ -609,27 +622,74 @@ static ssize_t
609pdcs_osid_read(struct subsystem *entry, char *buf) 622pdcs_osid_read(struct subsystem *entry, char *buf)
610{ 623{
611 char *out = buf; 624 char *out = buf;
612 __u32 result;
613 char *tmpstr = NULL; 625 char *tmpstr = NULL;
614 626
615 if (!entry || !buf) 627 if (!entry || !buf)
616 return -EINVAL; 628 return -EINVAL;
617 629
618 /* get OSID */ 630 switch (pdcs_osid) {
619 if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
620 return -EIO;
621
622 /* the actual result is 16 bits away */
623 switch (result >> 16) {
624 case 0x0000: tmpstr = "No OS-dependent data"; break; 631 case 0x0000: tmpstr = "No OS-dependent data"; break;
625 case 0x0001: tmpstr = "HP-UX dependent data"; break; 632 case 0x0001: tmpstr = "HP-UX dependent data"; break;
626 case 0x0002: tmpstr = "MPE-iX dependent data"; break; 633 case 0x0002: tmpstr = "MPE-iX dependent data"; break;
627 case 0x0003: tmpstr = "OSF dependent data"; break; 634 case 0x0003: tmpstr = "OSF dependent data"; break;
628 case 0x0004: tmpstr = "HP-RT dependent data"; break; 635 case 0x0004: tmpstr = "HP-RT dependent data"; break;
629 case 0x0005: tmpstr = "Novell Netware dependent data"; break; 636 case 0x0005: tmpstr = "Novell Netware dependent data"; break;
637 case 0x0006: tmpstr = "Linux dependent data"; break;
630 default: tmpstr = "Unknown"; break; 638 default: tmpstr = "Unknown"; break;
631 } 639 }
632 out += sprintf(out, "%s (0x%.4x)\n", tmpstr, (result >> 16)); 640 out += sprintf(out, "%s (0x%.4x)\n", tmpstr, pdcs_osid);
641
642 return out - buf;
643}
644
645/**
646 * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output.
647 * @entry: An allocated and populated subsytem struct. We don't use it tho.
648 * @buf: The output buffer to write to.
649 *
650 * This can hold 16 bytes of OS-Dependent data.
651 */
652static ssize_t
653pdcs_osdep1_read(struct subsystem *entry, char *buf)
654{
655 char *out = buf;
656 u32 result[4];
657
658 if (!entry || !buf)
659 return -EINVAL;
660
661 if (pdc_stable_read(PDCS_ADDR_OSD1, &result, sizeof(result)) != PDC_OK)
662 return -EIO;
663
664 out += sprintf(out, "0x%.8x\n", result[0]);
665 out += sprintf(out, "0x%.8x\n", result[1]);
666 out += sprintf(out, "0x%.8x\n", result[2]);
667 out += sprintf(out, "0x%.8x\n", result[3]);
668
669 return out - buf;
670}
671
672/**
673 * pdcs_diagnostic_read - Stable Storage Diagnostic register output.
674 * @entry: An allocated and populated subsytem struct. We don't use it tho.
675 * @buf: The output buffer to write to.
676 *
677 * I have NFC how to interpret the content of that register ;-).
678 */
679static ssize_t
680pdcs_diagnostic_read(struct subsystem *entry, char *buf)
681{
682 char *out = buf;
683 u32 result;
684
685 if (!entry || !buf)
686 return -EINVAL;
687
688 /* get diagnostic */
689 if (pdc_stable_read(PDCS_ADDR_DIAG, &result, sizeof(result)) != PDC_OK)
690 return -EIO;
691
692 out += sprintf(out, "0x%.4x\n", (result >> 16));
633 693
634 return out - buf; 694 return out - buf;
635} 695}
@@ -645,7 +705,7 @@ static ssize_t
645pdcs_fastsize_read(struct subsystem *entry, char *buf) 705pdcs_fastsize_read(struct subsystem *entry, char *buf)
646{ 706{
647 char *out = buf; 707 char *out = buf;
648 __u32 result; 708 u32 result;
649 709
650 if (!entry || !buf) 710 if (!entry || !buf)
651 return -EINVAL; 711 return -EINVAL;
@@ -664,6 +724,39 @@ pdcs_fastsize_read(struct subsystem *entry, char *buf)
664} 724}
665 725
666/** 726/**
727 * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output.
728 * @entry: An allocated and populated subsytem struct. We don't use it tho.
729 * @buf: The output buffer to write to.
730 *
731 * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available.
732 */
733static ssize_t
734pdcs_osdep2_read(struct subsystem *entry, char *buf)
735{
736 char *out = buf;
737 unsigned long size;
738 unsigned short i;
739 u32 result;
740
741 if (unlikely(pdcs_size <= 224))
742 return -ENODATA;
743
744 size = pdcs_size - 224;
745
746 if (!entry || !buf)
747 return -EINVAL;
748
749 for (i=0; i<size; i+=4) {
750 if (unlikely(pdc_stable_read(PDCS_ADDR_OSD2 + i, &result,
751 sizeof(result)) != PDC_OK))
752 return -EIO;
753 out += sprintf(out, "0x%.8x\n", result);
754 }
755
756 return out - buf;
757}
758
759/**
667 * pdcs_auto_write - This function handles autoboot/search flag modifying. 760 * pdcs_auto_write - This function handles autoboot/search flag modifying.
668 * @entry: An allocated and populated subsytem struct. We don't use it tho. 761 * @entry: An allocated and populated subsytem struct. We don't use it tho.
669 * @buf: The input buffer to read from. 762 * @buf: The input buffer to read from.
@@ -770,13 +863,100 @@ pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
770 return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH); 863 return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH);
771} 864}
772 865
866/**
867 * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input.
868 * @entry: An allocated and populated subsytem struct. We don't use it tho.
869 * @buf: The input buffer to read from.
870 * @count: The number of bytes to be read.
871 *
872 * This can store 16 bytes of OS-Dependent data. We use a byte-by-byte
873 * write approach. It's up to userspace to deal with it when constructing
874 * its input buffer.
875 */
876static ssize_t
877pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count)
878{
879 u8 in[16];
880
881 if (!capable(CAP_SYS_ADMIN))
882 return -EACCES;
883
884 if (!entry || !buf || !count)
885 return -EINVAL;
886
887 if (unlikely(pdcs_osid != 0x0006))
888 return -EPERM;
889
890 if (count > 16)
891 return -EMSGSIZE;
892
893 /* We'll use a local copy of buf */
894 memset(in, 0, 16);
895 memcpy(in, buf, count);
896
897 if (pdc_stable_write(PDCS_ADDR_OSD1, &in, sizeof(in)) != PDC_OK)
898 return -EIO;
899
900 return count;
901}
902
903/**
904 * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input.
905 * @entry: An allocated and populated subsytem struct. We don't use it tho.
906 * @buf: The input buffer to read from.
907 * @count: The number of bytes to be read.
908 *
909 * This can store pdcs_size - 224 bytes of OS-Dependent data. We use a
910 * byte-by-byte write approach. It's up to userspace to deal with it when
911 * constructing its input buffer.
912 */
913static ssize_t
914pdcs_osdep2_write(struct subsystem *entry, const char *buf, size_t count)
915{
916 unsigned long size;
917 unsigned short i;
918 u8 in[4];
919
920 if (!capable(CAP_SYS_ADMIN))
921 return -EACCES;
922
923 if (!entry || !buf || !count)
924 return -EINVAL;
925
926 if (unlikely(pdcs_size <= 224))
927 return -ENOSYS;
928
929 if (unlikely(pdcs_osid != 0x0006))
930 return -EPERM;
931
932 size = pdcs_size - 224;
933
934 if (count > size)
935 return -EMSGSIZE;
936
937 /* We'll use a local copy of buf */
938
939 for (i=0; i<count; i+=4) {
940 memset(in, 0, 4);
941 memcpy(in, buf+i, (count-i < 4) ? count-i : 4);
942 if (unlikely(pdc_stable_write(PDCS_ADDR_OSD2 + i, &in,
943 sizeof(in)) != PDC_OK))
944 return -EIO;
945 }
946
947 return count;
948}
949
773/* The remaining attributes. */ 950/* The remaining attributes. */
774static PDCS_ATTR(size, 0444, pdcs_size_read, NULL); 951static PDCS_ATTR(size, 0444, pdcs_size_read, NULL);
775static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write); 952static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write);
776static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write); 953static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write);
777static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL); 954static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL);
778static PDCS_ATTR(osid, 0400, pdcs_osid_read, NULL); 955static PDCS_ATTR(osid, 0444, pdcs_osid_read, NULL);
956static PDCS_ATTR(osdep1, 0600, pdcs_osdep1_read, pdcs_osdep1_write);
957static PDCS_ATTR(diagnostic, 0400, pdcs_diagnostic_read, NULL);
779static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL); 958static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL);
959static PDCS_ATTR(osdep2, 0600, pdcs_osdep2_read, pdcs_osdep2_write);
780 960
781static struct subsys_attribute *pdcs_subsys_attrs[] = { 961static struct subsys_attribute *pdcs_subsys_attrs[] = {
782 &pdcs_attr_size, 962 &pdcs_attr_size,
@@ -784,7 +964,10 @@ static struct subsys_attribute *pdcs_subsys_attrs[] = {
784 &pdcs_attr_autosearch, 964 &pdcs_attr_autosearch,
785 &pdcs_attr_timer, 965 &pdcs_attr_timer,
786 &pdcs_attr_osid, 966 &pdcs_attr_osid,
967 &pdcs_attr_osdep1,
968 &pdcs_attr_diagnostic,
787 &pdcs_attr_fastsize, 969 &pdcs_attr_fastsize,
970 &pdcs_attr_osdep2,
788 NULL, 971 NULL,
789}; 972};
790 973
@@ -865,6 +1048,7 @@ pdc_stable_init(void)
865{ 1048{
866 struct subsys_attribute *attr; 1049 struct subsys_attribute *attr;
867 int i, rc = 0, error = 0; 1050 int i, rc = 0, error = 0;
1051 u32 result;
868 1052
869 /* find the size of the stable storage */ 1053 /* find the size of the stable storage */
870 if (pdc_stable_get_size(&pdcs_size) != PDC_OK) 1054 if (pdc_stable_get_size(&pdcs_size) != PDC_OK)
@@ -876,6 +1060,13 @@ pdc_stable_init(void)
876 1060
877 printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION); 1061 printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION);
878 1062
1063 /* get OSID */
1064 if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
1065 return -EIO;
1066
1067 /* the actual result is 16 bits away */
1068 pdcs_osid = (u16)(result >> 16);
1069
879 /* For now we'll register the stable subsys within this driver */ 1070 /* For now we'll register the stable subsys within this driver */
880 if ((rc = firmware_register(&stable_subsys))) 1071 if ((rc = firmware_register(&stable_subsys)))
881 goto fail_firmreg; 1072 goto fail_firmreg;
@@ -887,7 +1078,7 @@ pdc_stable_init(void)
887 1078
888 /* register the paths subsys as a subsystem of stable subsys */ 1079 /* register the paths subsys as a subsystem of stable subsys */
889 kset_set_kset_s(&paths_subsys, stable_subsys); 1080 kset_set_kset_s(&paths_subsys, stable_subsys);
890 if ((rc= subsystem_register(&paths_subsys))) 1081 if ((rc = subsystem_register(&paths_subsys)))
891 goto fail_subsysreg; 1082 goto fail_subsysreg;
892 1083
893 /* now we create all "files" for the paths subsys */ 1084 /* now we create all "files" for the paths subsys */