1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * SCLP control program identification sysfs interface 4 * 5 * Copyright IBM Corp. 2001, 2007 6 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 7 * Michael Ernst <mernst@de.ibm.com> 8 */ 9 10 #define KMSG_COMPONENT "sclp_cpi" 11 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 12 13 #include <linux/kernel.h> 14 #include <linux/init.h> 15 #include <linux/stat.h> 16 #include <linux/device.h> 17 #include <linux/string.h> 18 #include <linux/ctype.h> 19 #include <linux/kmod.h> 20 #include <linux/timer.h> 21 #include <linux/err.h> 22 #include <linux/slab.h> 23 #include <linux/completion.h> 24 #include <linux/export.h> 25 #include <asm/ebcdic.h> 26 #include <asm/sclp.h> 27 28 #include "sclp.h" 29 #include "sclp_rw.h" 30 #include "sclp_cpi_sys.h" 31 32 #define CPI_LENGTH_NAME 8 33 #define CPI_LENGTH_LEVEL 16 34 35 static DEFINE_MUTEX(sclp_cpi_mutex); 36 37 struct cpi_evbuf { 38 struct evbuf_header header; 39 u8 id_format; 40 u8 reserved0; 41 u8 system_type[CPI_LENGTH_NAME]; 42 u64 reserved1; 43 u8 system_name[CPI_LENGTH_NAME]; 44 u64 reserved2; 45 u64 system_level; 46 u64 reserved3; 47 u8 sysplex_name[CPI_LENGTH_NAME]; 48 u8 reserved4[16]; 49 } __attribute__((packed)); 50 51 struct cpi_sccb { 52 struct sccb_header header; 53 struct cpi_evbuf cpi_evbuf; 54 } __attribute__((packed)); 55 56 static struct sclp_register sclp_cpi_event = { 57 .send_mask = EVTYP_CTLPROGIDENT_MASK, 58 }; 59 60 static char system_name[CPI_LENGTH_NAME + 1]; 61 static char sysplex_name[CPI_LENGTH_NAME + 1]; 62 static char system_type[CPI_LENGTH_NAME + 1]; 63 static u64 system_level; 64 65 static void set_data(char *field, char *data) 66 { 67 memset(field, ' ', CPI_LENGTH_NAME); 68 memcpy(field, data, strlen(data)); 69 sclp_ascebc_str(field, CPI_LENGTH_NAME); 70 } 71 72 static void cpi_callback(struct sclp_req *req, void *data) 73 { 74 struct completion *completion = data; 75 76 complete(completion); 77 } 78 79 static struct sclp_req *cpi_prepare_req(void) 80 { 81 struct sclp_req *req; 82 struct cpi_sccb *sccb; 83 struct cpi_evbuf *evb; 84 85 req = kzalloc(sizeof(struct sclp_req), GFP_KERNEL); 86 if (!req) 87 return ERR_PTR(-ENOMEM); 88 sccb = (struct cpi_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 89 if (!sccb) { 90 kfree(req); 91 return ERR_PTR(-ENOMEM); 92 } 93 94 /* setup SCCB for Control-Program Identification */ 95 sccb->header.length = sizeof(struct cpi_sccb); 96 sccb->cpi_evbuf.header.length = sizeof(struct cpi_evbuf); 97 sccb->cpi_evbuf.header.type = EVTYP_CTLPROGIDENT; 98 evb = &sccb->cpi_evbuf; 99 100 /* set system type */ 101 set_data(evb->system_type, system_type); 102 103 /* set system name */ 104 set_data(evb->system_name, system_name); 105 106 /* set system level */ 107 evb->system_level = system_level; 108 109 /* set sysplex name */ 110 set_data(evb->sysplex_name, sysplex_name); 111 112 /* prepare request data structure presented to SCLP driver */ 113 req->command = SCLP_CMDW_WRITE_EVENT_DATA; 114 req->sccb = sccb; 115 req->status = SCLP_REQ_FILLED; 116 req->callback = cpi_callback; 117 return req; 118 } 119 120 static void cpi_free_req(struct sclp_req *req) 121 { 122 free_page((unsigned long) req->sccb); 123 kfree(req); 124 } 125 126 static int cpi_req(void) 127 { 128 struct completion completion; 129 struct sclp_req *req; 130 int rc; 131 int response; 132 133 rc = sclp_register(&sclp_cpi_event); 134 if (rc) 135 goto out; 136 if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) { 137 rc = -EOPNOTSUPP; 138 goto out_unregister; 139 } 140 141 req = cpi_prepare_req(); 142 if (IS_ERR(req)) { 143 rc = PTR_ERR(req); 144 goto out_unregister; 145 } 146 147 init_completion(&completion); 148 req->callback_data = &completion; 149 150 /* Add request to sclp queue */ 151 rc = sclp_add_request(req); 152 if (rc) 153 goto out_free_req; 154 155 wait_for_completion(&completion); 156 157 if (req->status != SCLP_REQ_DONE) { 158 pr_warn("request failed (status=0x%02x)\n", req->status); 159 rc = -EIO; 160 goto out_free_req; 161 } 162 163 response = ((struct cpi_sccb *) req->sccb)->header.response_code; 164 if (response != 0x0020) { 165 pr_warn("request failed with response code 0x%x\n", response); 166 rc = -EIO; 167 } 168 169 out_free_req: 170 cpi_free_req(req); 171 172 out_unregister: 173 sclp_unregister(&sclp_cpi_event); 174 175 out: 176 return rc; 177 } 178 179 static int check_string(const char *attr, const char *str) 180 { 181 size_t len; 182 size_t i; 183 184 len = strlen(str); 185 186 if ((len > 0) && (str[len - 1] == '\n')) 187 len--; 188 189 if (len > CPI_LENGTH_NAME) 190 return -EINVAL; 191 192 for (i = 0; i < len ; i++) { 193 if (isalpha(str[i]) || isdigit(str[i]) || 194 strchr("$@# ", str[i])) 195 continue; 196 return -EINVAL; 197 } 198 199 return 0; 200 } 201 202 static void set_string(char *attr, const char *value) 203 { 204 size_t len; 205 size_t i; 206 207 len = strlen(value); 208 209 if ((len > 0) && (value[len - 1] == '\n')) 210 len--; 211 212 for (i = 0; i < CPI_LENGTH_NAME; i++) { 213 if (i < len) 214 attr[i] = toupper(value[i]); 215 else 216 attr[i] = ' '; 217 } 218 } 219 220 static ssize_t system_name_show(struct kobject *kobj, 221 struct kobj_attribute *attr, char *page) 222 { 223 int rc; 224 225 mutex_lock(&sclp_cpi_mutex); 226 rc = snprintf(page, PAGE_SIZE, "%s\n", system_name); 227 mutex_unlock(&sclp_cpi_mutex); 228 return rc; 229 } 230 231 static ssize_t system_name_store(struct kobject *kobj, 232 struct kobj_attribute *attr, 233 const char *buf, 234 size_t len) 235 { 236 int rc; 237 238 rc = check_string("system_name", buf); 239 if (rc) 240 return rc; 241 242 mutex_lock(&sclp_cpi_mutex); 243 set_string(system_name, buf); 244 mutex_unlock(&sclp_cpi_mutex); 245 246 return len; 247 } 248 249 static struct kobj_attribute system_name_attr = 250 __ATTR(system_name, 0644, system_name_show, system_name_store); 251 252 static ssize_t sysplex_name_show(struct kobject *kobj, 253 struct kobj_attribute *attr, char *page) 254 { 255 int rc; 256 257 mutex_lock(&sclp_cpi_mutex); 258 rc = snprintf(page, PAGE_SIZE, "%s\n", sysplex_name); 259 mutex_unlock(&sclp_cpi_mutex); 260 return rc; 261 } 262 263 static ssize_t sysplex_name_store(struct kobject *kobj, 264 struct kobj_attribute *attr, 265 const char *buf, 266 size_t len) 267 { 268 int rc; 269 270 rc = check_string("sysplex_name", buf); 271 if (rc) 272 return rc; 273 274 mutex_lock(&sclp_cpi_mutex); 275 set_string(sysplex_name, buf); 276 mutex_unlock(&sclp_cpi_mutex); 277 278 return len; 279 } 280 281 static struct kobj_attribute sysplex_name_attr = 282 __ATTR(sysplex_name, 0644, sysplex_name_show, sysplex_name_store); 283 284 static ssize_t system_type_show(struct kobject *kobj, 285 struct kobj_attribute *attr, char *page) 286 { 287 int rc; 288 289 mutex_lock(&sclp_cpi_mutex); 290 rc = snprintf(page, PAGE_SIZE, "%s\n", system_type); 291 mutex_unlock(&sclp_cpi_mutex); 292 return rc; 293 } 294 295 static ssize_t system_type_store(struct kobject *kobj, 296 struct kobj_attribute *attr, 297 const char *buf, 298 size_t len) 299 { 300 int rc; 301 302 rc = check_string("system_type", buf); 303 if (rc) 304 return rc; 305 306 mutex_lock(&sclp_cpi_mutex); 307 set_string(system_type, buf); 308 mutex_unlock(&sclp_cpi_mutex); 309 310 return len; 311 } 312 313 static struct kobj_attribute system_type_attr = 314 __ATTR(system_type, 0644, system_type_show, system_type_store); 315 316 static ssize_t system_level_show(struct kobject *kobj, 317 struct kobj_attribute *attr, char *page) 318 { 319 unsigned long long level; 320 321 mutex_lock(&sclp_cpi_mutex); 322 level = system_level; 323 mutex_unlock(&sclp_cpi_mutex); 324 return snprintf(page, PAGE_SIZE, "%#018llx\n", level); 325 } 326 327 static ssize_t system_level_store(struct kobject *kobj, 328 struct kobj_attribute *attr, 329 const char *buf, 330 size_t len) 331 { 332 unsigned long long level; 333 char *endp; 334 335 level = simple_strtoull(buf, &endp, 16); 336 337 if (endp == buf) 338 return -EINVAL; 339 if (*endp == '\n') 340 endp++; 341 if (*endp) 342 return -EINVAL; 343 344 mutex_lock(&sclp_cpi_mutex); 345 system_level = level; 346 mutex_unlock(&sclp_cpi_mutex); 347 return len; 348 } 349 350 static struct kobj_attribute system_level_attr = 351 __ATTR(system_level, 0644, system_level_show, system_level_store); 352 353 static ssize_t set_store(struct kobject *kobj, 354 struct kobj_attribute *attr, 355 const char *buf, size_t len) 356 { 357 int rc; 358 359 mutex_lock(&sclp_cpi_mutex); 360 rc = cpi_req(); 361 mutex_unlock(&sclp_cpi_mutex); 362 if (rc) 363 return rc; 364 365 return len; 366 } 367 368 static struct kobj_attribute set_attr = __ATTR(set, 0200, NULL, set_store); 369 370 static struct attribute *cpi_attrs[] = { 371 &system_name_attr.attr, 372 &sysplex_name_attr.attr, 373 &system_type_attr.attr, 374 &system_level_attr.attr, 375 &set_attr.attr, 376 NULL, 377 }; 378 379 static struct attribute_group cpi_attr_group = { 380 .attrs = cpi_attrs, 381 }; 382 383 static struct kset *cpi_kset; 384 385 int sclp_cpi_set_data(const char *system, const char *sysplex, const char *type, 386 const u64 level) 387 { 388 int rc; 389 390 rc = check_string("system_name", system); 391 if (rc) 392 return rc; 393 rc = check_string("sysplex_name", sysplex); 394 if (rc) 395 return rc; 396 rc = check_string("system_type", type); 397 if (rc) 398 return rc; 399 400 mutex_lock(&sclp_cpi_mutex); 401 set_string(system_name, system); 402 set_string(sysplex_name, sysplex); 403 set_string(system_type, type); 404 system_level = level; 405 406 rc = cpi_req(); 407 mutex_unlock(&sclp_cpi_mutex); 408 409 return rc; 410 } 411 EXPORT_SYMBOL(sclp_cpi_set_data); 412 413 static int __init cpi_init(void) 414 { 415 int rc; 416 417 cpi_kset = kset_create_and_add("cpi", NULL, firmware_kobj); 418 if (!cpi_kset) 419 return -ENOMEM; 420 421 rc = sysfs_create_group(&cpi_kset->kobj, &cpi_attr_group); 422 if (rc) 423 kset_unregister(cpi_kset); 424 425 return rc; 426 } 427 428 __initcall(cpi_init); 429