1 /* Copyright 2014-2015 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * imitations under the License.
15 */
16
17 #define _GNU_SOURCE
18
19 #include <assert.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <getopt.h>
23 #include <sys/mman.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <stdbool.h>
33 #include <stdarg.h>
34 #include <time.h>
35 #include <poll.h>
36 #include <dirent.h>
37
38 #include <endian.h>
39
40 #include <sys/ioctl.h>
41 #include <sys/time.h>
42 #include <sys/socket.h>
43 #include <sys/un.h>
44
45 #include <linux/ipmi.h>
46 #include <linux/limits.h>
47
48 #include <asm/opal-prd.h>
49
50 #include <opal-api.h>
51 #include <types.h>
52
53 #include <ccan/list/list.h>
54
55 #include "opal-prd.h"
56 #include "hostboot-interface.h"
57 #include "module.h"
58 #include "pnor.h"
59 #include "i2c.h"
60
61 struct prd_range {
62 const char *name;
63 uint64_t physaddr;
64 uint64_t size;
65 void *buf;
66 bool multiple;
67 uint32_t instance;
68 };
69
70 struct prd_msgq_item {
71 struct list_node list;
72 struct opal_prd_msg msg;
73 };
74
75 struct opal_prd_ctx {
76 int fd;
77 int socket;
78 struct opal_prd_info info;
79 struct prd_range *ranges;
80 int n_ranges;
81 bool fw_range_instances;
82 long page_size;
83 void *code_addr;
84 size_t code_size;
85 bool debug;
86 struct pnor pnor;
87 char *hbrt_file_name;
88 bool use_syslog;
89 bool expert_mode;
90 struct list_head msgq;
91 struct opal_prd_msg *msg;
92 size_t msg_alloc_len;
93 void (*vlog)(int, const char *, va_list);
94 };
95
96 enum control_msg_type {
97 CONTROL_MSG_ENABLE_OCCS = 0x00,
98 CONTROL_MSG_DISABLE_OCCS = 0x01,
99 CONTROL_MSG_TEMP_OCC_RESET = 0x02,
100 CONTROL_MSG_TEMP_OCC_ERROR = 0x03,
101 CONTROL_MSG_ATTR_OVERRIDE = 0x04,
102 CONTROL_MSG_HTMGT_PASSTHRU = 0x05,
103 CONTROL_MSG_RUN_CMD = 0x30,
104 };
105
106 struct control_msg {
107 enum control_msg_type type;
108 int response;
109 union {
110 struct {
111 unsigned int argc;
112 } run_cmd;
113 struct {
114 uint64_t chip;
115 } occ_reset;
116 struct {
117 uint64_t chip;
118 } occ_error;
119 };
120 unsigned int data_len;
121 unsigned char data[];
122
123 };
124
125 #define MAX_CONTROL_MSG_BUF 4096
126
127 static struct opal_prd_ctx *ctx;
128
129 static const char *opal_prd_devnode = "/dev/opal-prd";
130 static const char *opal_prd_socket = "/run/opal-prd-control";
131 static const char *hbrt_code_region_name = "ibm,hbrt-code-image";
132 static const int opal_prd_version = 1;
133 static uint64_t opal_prd_ipoll = 0xf000000000000000;
134
135 static const int max_msgq_len = 16;
136
137 static const char *ipmi_devnode = "/dev/ipmi0";
138 static const int ipmi_timeout_ms = 5000;
139
140 static const char *devicetree_base =
141 "/sys/firmware/devicetree/base";
142
143 /* Memory error handling */
144 static const char *mem_offline_soft =
145 "/sys/devices/system/memory/soft_offline_page";
146 static const char *mem_offline_hard =
147 "/sys/devices/system/memory/hard_offline_page";
148
149 #define ADDR_STRING_SZ 20 /* Hold %16lx */
150
151 /* This is the "real" HBRT call table for calling into HBRT as
152 * provided by it. It will be used by the assembly thunk
153 */
154 struct runtime_interfaces *hservice_runtime;
155 struct runtime_interfaces hservice_runtime_fixed;
156
157 /* This is the callback table provided by assembly code */
158 extern struct host_interfaces hinterface;
159
160 /* Create opd to call hostservice init */
161 struct func_desc {
162 void *addr;
163 void *toc;
164 } hbrt_entry;
165
166 static int read_prd_msg(struct opal_prd_ctx *ctx);
167
find_range(const char * name,uint32_t instance)168 static struct prd_range *find_range(const char *name, uint32_t instance)
169 {
170 struct prd_range *range;
171 unsigned int i;
172
173 for (i = 0; i < ctx->n_ranges; i++) {
174 range = &ctx->ranges[i];
175
176 if (strcmp(range->name, name))
177 continue;
178
179 if (range->multiple && range->instance != instance)
180 continue;
181
182 return range;
183 }
184
185 return NULL;
186 }
187
pr_log_stdio(int priority,const char * fmt,va_list ap)188 static void pr_log_stdio(int priority, const char *fmt, va_list ap)
189 {
190 if (!ctx->debug && priority >= LOG_DEBUG)
191 return;
192
193 vprintf(fmt, ap);
194 printf("\n");
195 }
196
197 /* standard logging prefixes:
198 * HBRT: Messages from hostboot runtime code
199 * FW: Interactions with OPAL firmware
200 * IMAGE: HBRT image loading
201 * MEM: Memory failure interface
202 * SCOM: Chip SCOM interface
203 * IPMI: IPMI interface
204 * PNOR: PNOR interface
205 * I2C: i2c interface
206 * PM: PM/OCC interface
207 * CTRL: User-triggered control events
208 * KMOD: Kernel module functions
209 */
210
pr_log(int priority,const char * fmt,...)211 void pr_log(int priority, const char *fmt, ...)
212 {
213 va_list ap;
214
215 va_start(ap, fmt);
216 ctx->vlog(priority, fmt, ap);
217 va_end(ap);
218 }
219
pr_log_nocall(const char * name)220 static void pr_log_nocall(const char *name)
221 {
222 pr_log(LOG_WARNING, "HBRT: Call %s not provided", name);
223 }
224
hexdump(const uint8_t * data,uint32_t len)225 static void hexdump(const uint8_t *data, uint32_t len)
226 {
227 int i;
228
229 for (i = 0; i < len; i++) {
230 if (i % 16 == 0)
231 printf("\n");
232 else if(i % 4 == 0)
233 printf(" ");
234
235 printf("%02x", data[i]);
236 }
237
238 printf("\n");
239 }
240
pr_log_daemon_init(void)241 static void pr_log_daemon_init(void)
242 {
243 if (ctx->use_syslog) {
244 openlog("opal-prd", LOG_NDELAY, LOG_DAEMON);
245 ctx->vlog = vsyslog;
246 }
247 }
248
249 /* Check service processor type */
is_fsp_system(void)250 static bool is_fsp_system(void)
251 {
252 char *path;
253 int rc;
254
255 rc = asprintf(&path, "%s/fsps", devicetree_base);
256 if (rc < 0) {
257 pr_log(LOG_ERR, "FW: error creating '/fsps' path %m");
258 return false;
259 }
260
261 return access(path, F_OK) ? false : true;
262 }
263
264 /**
265 * ABI check that we can't perform at build-time: we want to ensure that the
266 * layout of struct host_interfaces matches that defined in the thunk.
267 */
check_abi(void)268 static void check_abi(void)
269 {
270 extern unsigned char __hinterface_start, __hinterface_pad,
271 __hinterface_end;
272
273 /* ensure our struct size matches the thunk definition */
274 assert((&__hinterface_end - &__hinterface_start)
275 == sizeof(struct host_interfaces));
276
277 /* ensure the padding layout is as expected */
278 assert((void *)&__hinterface_start == (void *)&hinterface);
279 assert((void *)&__hinterface_pad == (void *)&hinterface.reserved);
280 }
281
282 /* HBRT init wrappers */
283 extern struct runtime_interfaces *call_hbrt_init(struct host_interfaces *);
284
285 /* hservice Call wrappers */
286
287 extern void call_cxxtestExecute(void *);
288 extern int call_handle_attns(uint64_t i_proc,
289 uint64_t i_ipollStatus,
290 uint64_t i_ipollMask);
291 extern void call_process_occ_error (uint64_t i_chipId);
292 extern int call_enable_attns(void);
293 extern int call_enable_occ_actuation(bool i_occActivation);
294 extern void call_process_occ_reset(uint64_t i_chipId);
295 extern int call_mfg_htmgt_pass_thru(uint16_t i_cmdLength, uint8_t *i_cmdData,
296 uint16_t *o_rspLength, uint8_t *o_rspData);
297 extern int call_apply_attr_override(uint8_t *i_data, size_t size);
298 extern int call_run_command(int argc, const char **argv, char **o_outString);
299 extern int call_sbe_message_passing(uint32_t i_chipId);
300 extern uint64_t call_get_ipoll_events(void);
301 extern int call_firmware_notify(uint64_t len, void *data);
302 extern int call_reset_pm_complex(uint64_t chip);
303
hservice_puts(const char * str)304 void hservice_puts(const char *str)
305 {
306 int priority = LOG_INFO;
307
308 /* Interpret the 2-character ERR_MRK/FAIL_MRK/WARN_MRK prefixes that
309 * may be present on HBRT log messages, and bump the log priority as
310 * appropriate.
311 */
312 if (strlen(str) >= 2 && str[1] == '>') {
313 switch (str[0]) {
314 case 'E':
315 case 'F':
316 priority = LOG_ERR;
317 break;
318 case 'W':
319 priority = LOG_WARNING;
320 break;
321 }
322 }
323
324 pr_log(priority, "HBRT: %s", str);
325 }
326
hservice_assert(void)327 void hservice_assert(void)
328 {
329 pr_log(LOG_ERR, "HBRT: Failed assertion! exiting.");
330 exit(EXIT_FAILURE);
331 }
332
hservice_malloc(size_t size)333 void *hservice_malloc(size_t size)
334 {
335 return malloc(size);
336 }
337
hservice_free(void * ptr)338 void hservice_free(void *ptr)
339 {
340 free(ptr);
341 }
342
hservice_realloc(void * ptr,size_t size)343 void *hservice_realloc(void *ptr, size_t size)
344 {
345 return realloc(ptr, size);
346 }
347
hservice_scom_read(uint64_t chip_id,uint64_t addr,void * buf)348 int hservice_scom_read(uint64_t chip_id, uint64_t addr, void *buf)
349 {
350 int rc;
351 struct opal_prd_scom scom;
352
353 scom.chip = chip_id;
354 scom.addr = addr;
355
356 rc = ioctl(ctx->fd, OPAL_PRD_SCOM_READ, &scom);
357 if (rc) {
358 pr_log(LOG_ERR, "SCOM: ioctl read(chip 0x%lx, addr 0x%lx) "
359 "failed: %m", chip_id, addr);
360 return 0;
361 }
362 rc = (int)scom.rc;
363
364 pr_debug("SCOM: read: chip 0x%lx, addr 0x%lx, val 0x%lx, rc %d",
365 chip_id, addr, scom.data, rc);
366
367 *(uint64_t *)buf = htobe64(scom.data);
368
369 return rc;
370 }
371
hservice_scom_write(uint64_t chip_id,uint64_t addr,const void * buf)372 int hservice_scom_write(uint64_t chip_id, uint64_t addr,
373 const void *buf)
374 {
375 int rc;
376 struct opal_prd_scom scom;
377
378 scom.chip = chip_id;
379 scom.addr = addr;
380 scom.data = be64toh(*(uint64_t *)buf);
381
382 rc = ioctl(ctx->fd, OPAL_PRD_SCOM_WRITE, &scom);
383 if (rc) {
384 pr_log(LOG_ERR, "SCOM: ioctl write(chip 0x%lx, addr 0x%lx) "
385 "failed: %m", chip_id, addr);
386 return 0;
387 }
388 rc = (int)scom.rc;
389
390 pr_debug("SCOM: write: chip 0x%lx, addr 0x%lx, val 0x%lx, rc %d",
391 chip_id, addr, scom.data, rc);
392
393 return rc;
394 }
395
hservice_get_reserved_mem(const char * name,uint32_t instance)396 uint64_t hservice_get_reserved_mem(const char *name, uint32_t instance)
397 {
398 struct prd_range *range;
399
400 pr_debug("IMAGE: hservice_get_reserved_mem: %s, %d", name, instance);
401
402 range = find_range(name, instance);
403 if (!range) {
404 pr_log(LOG_WARNING, "IMAGE: get_reserved_mem: "
405 "no such range %s", name);
406 return 0;
407 }
408
409 if (!range->buf) {
410 uint64_t align_physaddr, offset;
411
412 pr_debug("IMAGE: Mapping 0x%016lx 0x%08lx %s[%d]",
413 range->physaddr, range->size,
414 range->name, range->instance);
415
416 align_physaddr = range->physaddr & ~(ctx->page_size-1);
417 offset = range->physaddr & (ctx->page_size-1);
418 range->buf = mmap(NULL, range->size, PROT_WRITE | PROT_READ,
419 MAP_SHARED, ctx->fd, align_physaddr);
420
421 if (range->buf == MAP_FAILED)
422 pr_log(LOG_ERR,
423 "IMAGE: mmap of %s[%d](0x%016lx) failed: %m",
424 name, instance, range->physaddr);
425 else
426 range->buf += offset;
427 }
428
429 if (range->buf == MAP_FAILED) {
430 pr_log(LOG_WARNING,
431 "IMAGE: get_reserved_mem: %s[%d] has no vaddr",
432 name, instance);
433 return 0;
434 }
435
436 pr_debug(
437 "IMAGE: hservice_get_reserved_mem: %s[%d](0x%016lx) address %p",
438 name, range->instance, range->physaddr,
439 range->buf);
440
441 return (uint64_t)range->buf;
442 }
443
hservice_nanosleep(uint64_t i_seconds,uint64_t i_nano_seconds)444 void hservice_nanosleep(uint64_t i_seconds, uint64_t i_nano_seconds)
445 {
446 const struct timespec ns = {
447 .tv_sec = i_seconds,
448 .tv_nsec = i_nano_seconds
449 };
450
451 nanosleep(&ns, NULL);
452 }
453
hservice_set_page_execute(void * addr)454 int hservice_set_page_execute(void *addr)
455 {
456 /* HBRT calls this on the pages that are already being executed,
457 * nothing to do here */
458 return -1;
459 }
460
hservice_clock_gettime(clockid_t i_clkId,struct timespec * o_tp)461 int hservice_clock_gettime(clockid_t i_clkId, struct timespec *o_tp)
462 {
463 struct timespec tmp;
464 int rc;
465
466 rc = clock_gettime(i_clkId, &tmp);
467 if (rc)
468 return rc;
469
470 o_tp->tv_sec = htobe64(tmp.tv_sec);
471 o_tp->tv_nsec = htobe64(tmp.tv_nsec);
472
473 return 0;
474 }
475
hservice_pnor_read(uint32_t i_proc,const char * i_partitionName,uint64_t i_offset,void * o_data,size_t i_sizeBytes)476 int hservice_pnor_read(uint32_t i_proc, const char* i_partitionName,
477 uint64_t i_offset, void* o_data, size_t i_sizeBytes)
478 {
479 return pnor_operation(&ctx->pnor, i_partitionName, i_offset, o_data,
480 i_sizeBytes, PNOR_OP_READ);
481 }
482
hservice_pnor_write(uint32_t i_proc,const char * i_partitionName,uint64_t i_offset,void * o_data,size_t i_sizeBytes)483 int hservice_pnor_write(uint32_t i_proc, const char* i_partitionName,
484 uint64_t i_offset, void* o_data, size_t i_sizeBytes)
485 {
486 return pnor_operation(&ctx->pnor, i_partitionName, i_offset, o_data,
487 i_sizeBytes, PNOR_OP_WRITE);
488 }
489
hservice_i2c_read(uint64_t i_master,uint16_t i_devAddr,uint32_t i_offsetSize,uint32_t i_offset,uint32_t i_length,void * o_data)490 int hservice_i2c_read(uint64_t i_master, uint16_t i_devAddr,
491 uint32_t i_offsetSize, uint32_t i_offset,
492 uint32_t i_length, void* o_data)
493 {
494 uint32_t chip_id;
495 uint8_t engine, port;
496
497 chip_id = (i_master & HBRT_I2C_MASTER_CHIP_MASK) >>
498 HBRT_I2C_MASTER_CHIP_SHIFT;
499 engine = (i_master & HBRT_I2C_MASTER_ENGINE_MASK) >>
500 HBRT_I2C_MASTER_ENGINE_SHIFT;
501 port = (i_master & HBRT_I2C_MASTER_PORT_MASK) >>
502 HBRT_I2C_MASTER_PORT_SHIFT;
503 return i2c_read(chip_id, engine, port, i_devAddr, i_offsetSize,
504 i_offset, i_length, o_data);
505 }
506
hservice_i2c_write(uint64_t i_master,uint16_t i_devAddr,uint32_t i_offsetSize,uint32_t i_offset,uint32_t i_length,void * i_data)507 int hservice_i2c_write(uint64_t i_master, uint16_t i_devAddr,
508 uint32_t i_offsetSize, uint32_t i_offset,
509 uint32_t i_length, void* i_data)
510 {
511 uint32_t chip_id;
512 uint8_t engine, port;
513
514 chip_id = (i_master & HBRT_I2C_MASTER_CHIP_MASK) >>
515 HBRT_I2C_MASTER_CHIP_SHIFT;
516 engine = (i_master & HBRT_I2C_MASTER_ENGINE_MASK) >>
517 HBRT_I2C_MASTER_ENGINE_SHIFT;
518 port = (i_master & HBRT_I2C_MASTER_PORT_MASK) >>
519 HBRT_I2C_MASTER_PORT_SHIFT;
520 return i2c_write(chip_id, engine, port, i_devAddr, i_offsetSize,
521 i_offset, i_length, i_data);
522 }
523
ipmi_init(struct opal_prd_ctx * ctx)524 static void ipmi_init(struct opal_prd_ctx *ctx)
525 {
526 insert_module("ipmi_devintf");
527 }
528
ipmi_send(int fd,uint8_t netfn,uint8_t cmd,long seq,uint8_t * buf,size_t len)529 static int ipmi_send(int fd, uint8_t netfn, uint8_t cmd, long seq,
530 uint8_t *buf, size_t len)
531 {
532 struct ipmi_system_interface_addr addr;
533 struct ipmi_req req;
534 int rc;
535
536 memset(&addr, 0, sizeof(addr));
537 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
538 addr.channel = IPMI_BMC_CHANNEL;
539
540 memset(&req, 0, sizeof(req));
541 req.addr = (unsigned char *)&addr;
542 req.addr_len = sizeof(addr);
543
544 req.msgid = seq;
545 req.msg.netfn = netfn;
546 req.msg.cmd = cmd;
547 req.msg.data = buf;
548 req.msg.data_len = len;
549
550 rc = ioctl(fd, IPMICTL_SEND_COMMAND, &req);
551 if (rc < 0)
552 return -1;
553
554 return 0;
555 }
556
ipmi_recv(int fd,uint8_t * netfn,uint8_t * cmd,long * seq,uint8_t * buf,size_t * len)557 static int ipmi_recv(int fd, uint8_t *netfn, uint8_t *cmd, long *seq,
558 uint8_t *buf, size_t *len)
559 {
560 struct ipmi_recv recv;
561 struct ipmi_addr addr;
562 int rc;
563
564 recv.addr = (unsigned char *)&addr;
565 recv.addr_len = sizeof(addr);
566 recv.msg.data = buf;
567 recv.msg.data_len = *len;
568
569 rc = ioctl(fd, IPMICTL_RECEIVE_MSG_TRUNC, &recv);
570 if (rc < 0 && errno != EMSGSIZE) {
571 pr_log(LOG_WARNING, "IPMI: recv (%zd bytes) failed: %m", *len);
572 return -1;
573 } else if (rc < 0 && errno == EMSGSIZE) {
574 pr_log(LOG_NOTICE, "IPMI: truncated message (netfn %d, cmd %d, "
575 "size %zd), continuing anyway",
576 recv.msg.netfn, recv.msg.cmd, *len);
577 }
578
579 *netfn = recv.msg.netfn;
580 *cmd = recv.msg.cmd;
581 *seq = recv.msgid;
582 *len = recv.msg.data_len;
583
584 return 0;
585 }
586
hservice_ipmi_msg(uint8_t netfn,uint8_t cmd,void * tx_buf,size_t tx_size,void * rx_buf,size_t * rx_size)587 int hservice_ipmi_msg(uint8_t netfn, uint8_t cmd,
588 void *tx_buf, size_t tx_size,
589 void *rx_buf, size_t *rx_size)
590 {
591 struct timeval start, now, delta;
592 struct pollfd pollfds[1];
593 static long seq;
594 size_t size;
595 int rc, fd;
596
597 size = be64toh(*rx_size);
598
599 fd = open(ipmi_devnode, O_RDWR);
600 if (fd < 0) {
601 pr_log(LOG_WARNING, "IPMI: Failed to open IPMI device %s: %m",
602 ipmi_devnode);
603 return -1;
604 }
605
606 seq++;
607 pr_debug("IPMI: sending %zd bytes (netfn 0x%02x, cmd 0x%02x)",
608 tx_size, netfn, cmd);
609
610 rc = ipmi_send(fd, netfn, cmd, seq, tx_buf, tx_size);
611 if (rc) {
612 pr_log(LOG_WARNING, "IPMI: send failed");
613 goto out;
614 }
615
616 gettimeofday(&start, NULL);
617
618 pollfds[0].fd = fd;
619 pollfds[0].events = POLLIN;
620
621 for (;;) {
622 long rx_seq;
623 int timeout;
624
625 gettimeofday(&now, NULL);
626 timersub(&now, &start, &delta);
627 timeout = ipmi_timeout_ms - ((delta.tv_sec * 1000) +
628 (delta.tv_usec / 1000));
629 if (timeout < 0)
630 timeout = 0;
631
632 rc = poll(pollfds, 1, timeout);
633 if (rc < 0) {
634 pr_log(LOG_ERR, "IPMI: poll(%s) failed: %m",
635 ipmi_devnode);
636 break;
637 }
638
639 if (rc == 0) {
640 pr_log(LOG_WARNING, "IPMI: response timeout (>%dms)",
641 ipmi_timeout_ms);
642 rc = -1;
643 break;
644 }
645
646 rc = ipmi_recv(fd, &netfn, &cmd, &rx_seq, rx_buf, &size);
647 if (rc)
648 break;
649
650 if (seq != rx_seq) {
651 pr_log(LOG_NOTICE, "IPMI: out-of-sequence reply: %ld, "
652 "expected %ld. Dropping message.",
653 rx_seq, seq);
654 continue;
655 }
656
657 pr_debug("IPMI: received %zd bytes", tx_size);
658 *rx_size = be64toh(size);
659 rc = 0;
660 break;
661 }
662
663 out:
664 close(fd);
665 return rc;
666 }
667
hservice_memory_error(uint64_t i_start_addr,uint64_t i_endAddr,enum MemoryError_t i_errorType)668 int hservice_memory_error(uint64_t i_start_addr, uint64_t i_endAddr,
669 enum MemoryError_t i_errorType)
670 {
671 const char *sysfsfile, *typestr;
672 char buf[ADDR_STRING_SZ];
673 int memfd, rc, n;
674 uint64_t addr;
675
676 switch(i_errorType) {
677 case MEMORY_ERROR_CE:
678 sysfsfile = mem_offline_soft;
679 typestr = "correctable";
680 break;
681 case MEMORY_ERROR_UE:
682 sysfsfile = mem_offline_hard;
683 typestr = "uncorrectable";
684 break;
685 default:
686 pr_log(LOG_WARNING, "MEM: Invalid memory error type %d",
687 i_errorType);
688 return -1;
689 }
690
691 pr_log(LOG_ERR, "MEM: Memory error: range %016lx-%016lx, type: %s",
692 i_start_addr, i_endAddr, typestr);
693
694
695 memfd = open(sysfsfile, O_WRONLY);
696 if (memfd < 0) {
697 pr_log(LOG_CRIT, "MEM: Failed to offline memory! "
698 "Unable to open sysfs node %s: %m", sysfsfile);
699 return -1;
700 }
701
702 for (addr = i_start_addr; addr <= i_endAddr; addr += ctx->page_size) {
703 n = snprintf(buf, ADDR_STRING_SZ, "0x%lx", addr);
704 rc = write(memfd, buf, n);
705 if (rc != n) {
706 pr_log(LOG_CRIT, "MEM: Failed to offline memory! "
707 "page addr: %016lx type: %d: %m",
708 addr, i_errorType);
709 return rc;
710 }
711 }
712
713 return 0;
714 }
715
hservice_get_interface_capabilities(uint64_t set)716 uint64_t hservice_get_interface_capabilities(uint64_t set)
717 {
718 if (set == HBRT_CAPS_SET1_OPAL)
719 return HBRT_CAPS_OPAL_HAS_XSCOM_RC;
720
721 return 0;
722 }
723
hservice_firmware_request(uint64_t req_len,void * req,uint64_t * resp_lenp,void * resp)724 uint64_t hservice_firmware_request(uint64_t req_len, void *req,
725 uint64_t *resp_lenp, void *resp)
726 {
727 struct opal_prd_msg *msg = ctx->msg;
728 uint64_t resp_len;
729 size_t size;
730 int rc, n;
731
732 resp_len = be64_to_cpu(*resp_lenp);
733
734 pr_log(LOG_DEBUG,
735 "HBRT: firmware request: %lu bytes req, %lu bytes resp",
736 req_len, resp_len);
737
738 /* sanity check for potential overflows */
739 if (req_len > 0xffff || resp_len > 0xffff)
740 return -1;
741
742 size = sizeof(msg->hdr) + sizeof(msg->token) +
743 sizeof(msg->fw_req) + req_len;
744
745 /* we need the entire message to fit within the 2-byte size field */
746 if (size > 0xffff)
747 return -1;
748
749 /* variable sized message, so we may need to expand our buffer */
750 if (size > ctx->msg_alloc_len) {
751 msg = realloc(ctx->msg, size);
752 if (!msg) {
753 pr_log(LOG_ERR,
754 "FW: failed to expand message buffer: %m");
755 return -1;
756 }
757 ctx->msg = msg;
758 ctx->msg_alloc_len = size;
759 }
760
761 memset(msg, 0, size);
762
763 /* construct request message... */
764 msg->hdr.type = OPAL_PRD_MSG_TYPE_FIRMWARE_REQUEST;
765 msg->hdr.size = htobe16(size);
766 msg->fw_req.req_len = htobe64(req_len);
767 msg->fw_req.resp_len = htobe64(resp_len);
768 memcpy(msg->fw_req.data, req, req_len);
769
770 hexdump((void *)msg, size);
771
772 /* ... and send to firmware */
773 rc = write(ctx->fd, msg, size);
774 if (rc != size) {
775 pr_log(LOG_WARNING,
776 "FW: Failed to send FIRMWARE_REQUEST message: %m");
777 return -1;
778 }
779
780 /* We have an "inner" poll loop here, as we want to ensure that the
781 * next entry into HBRT is the return from this function. So, only
782 * read from the prd fd, and queue anything that isn't a response
783 * to this request
784 */
785 n = 0;
786 for (;;) {
787 struct prd_msgq_item *item;
788
789 rc = read_prd_msg(ctx);
790 if (rc)
791 return -1;
792
793 msg = ctx->msg;
794 if (msg->hdr.type == OPAL_PRD_MSG_TYPE_FIRMWARE_RESPONSE) {
795 size = be64toh(msg->fw_resp.len);
796 if (size > resp_len)
797 return -1;
798
799 /* success! a valid response that fits into HBRT's
800 * resp buffer */
801 memcpy(resp, msg->fw_resp.data, size);
802 *resp_lenp = htobe64(size);
803 return 0;
804 }
805
806 /* not a response? queue up for later consumption */
807 if (++n > max_msgq_len) {
808 pr_log(LOG_ERR,
809 "FW: too many messages queued (%d) while "
810 "waiting for FIRMWARE_RESPONSE", n);
811 return -1;
812 }
813 size = be16toh(msg->hdr.size);
814 item = malloc(sizeof(*item) + size);
815 memcpy(&item->msg, msg, size);
816 list_add_tail(&ctx->msgq, &item->list);
817 }
818 }
819
hservices_init(struct opal_prd_ctx * ctx,void * code)820 int hservices_init(struct opal_prd_ctx *ctx, void *code)
821 {
822 uint64_t *s, *d;
823 int i, sz;
824
825 pr_debug("IMAGE: code address: %p", code);
826
827 /* We enter at 0x100 into the image. */
828 /* Load func desc in BE since we reverse it in thunk */
829
830 hbrt_entry.addr = (void *)htobe64((unsigned long)code + 0x100);
831 hbrt_entry.toc = 0; /* No toc for init entry point */
832
833 if (memcmp(code, "HBRTVERS", 8) != 0) {
834 pr_log(LOG_ERR, "IMAGE: Bad signature for "
835 "ibm,hbrt-code-image! exiting");
836 return -1;
837 }
838
839 pr_debug("IMAGE: calling ibm,hbrt_init()");
840 hservice_runtime = call_hbrt_init(&hinterface);
841 if (!hservice_runtime) {
842 pr_log(LOG_ERR, "IMAGE: hbrt_init failed, exiting");
843 return -1;
844 }
845
846 pr_log(LOG_NOTICE, "IMAGE: hbrt_init complete, version %016lx",
847 hservice_runtime->interface_version);
848
849 sz = sizeof(struct runtime_interfaces)/sizeof(uint64_t);
850 s = (uint64_t *)hservice_runtime;
851 d = (uint64_t *)&hservice_runtime_fixed;
852 /* Byte swap the function pointers */
853 for (i = 0; i < sz; i++)
854 d[i] = be64toh(s[i]);
855
856 return 0;
857 }
858
fixup_hinterface_table(void)859 static void fixup_hinterface_table(void)
860 {
861 uint64_t *t64;
862 unsigned int i, sz;
863
864 /* Swap interface version */
865 hinterface.interface_version =
866 htobe64(hinterface.interface_version);
867
868 /* Swap OPDs */
869 sz = sizeof(struct host_interfaces) / sizeof(uint64_t);
870 t64 = (uint64_t *)&hinterface;
871 for (i = 1; i < sz; i++) {
872 uint64_t *opd = (uint64_t *)t64[i];
873 if (!opd)
874 continue;
875 t64[i] = htobe64(t64[i]);
876 opd[0] = htobe64(opd[0]);
877 opd[1] = htobe64(opd[1]);
878 opd[2] = htobe64(opd[2]);
879 }
880 }
881
map_hbrt_file(struct opal_prd_ctx * ctx,const char * name)882 static int map_hbrt_file(struct opal_prd_ctx *ctx, const char *name)
883 {
884 struct stat statbuf;
885 int fd, rc;
886 void *buf;
887
888 fd = open(name, O_RDONLY);
889 if (fd < 0) {
890 pr_log(LOG_ERR, "IMAGE: HBRT file open(%s) failed: %m", name);
891 return -1;
892 }
893
894 rc = fstat(fd, &statbuf);
895 if (rc < 0) {
896 pr_log(LOG_ERR, "IMAGE: HBRT file fstat(%s) failed: %m", name);
897 close(fd);
898 return -1;
899 }
900
901 buf = mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE | PROT_EXEC,
902 MAP_PRIVATE, fd, 0);
903 close(fd);
904
905 if (buf == MAP_FAILED) {
906 pr_log(LOG_ERR, "IMAGE: HBRT file mmap(%s, 0x%zx) failed: %m",
907 name, statbuf.st_size);
908 return -1;
909 }
910
911 ctx->code_addr = buf;
912 ctx->code_size = statbuf.st_size;
913 return -0;
914 }
915
map_hbrt_physmem(struct opal_prd_ctx * ctx,const char * name)916 static int map_hbrt_physmem(struct opal_prd_ctx *ctx, const char *name)
917 {
918 struct prd_range *range;
919 void *buf;
920
921 range = find_range(name, 0);
922 if (!range) {
923 pr_log(LOG_ERR, "IMAGE: can't find code region %s", name);
924 return -1;
925 }
926
927 buf = mmap(NULL, range->size, PROT_READ | PROT_WRITE | PROT_EXEC,
928 MAP_PRIVATE, ctx->fd, range->physaddr);
929 if (buf == MAP_FAILED) {
930 pr_log(LOG_ERR, "IMAGE: mmap(range:%s, "
931 "phys:0x%016lx, size:0x%016lx) failed: %m",
932 name, range->physaddr, range->size);
933 return -1;
934 }
935
936 ctx->code_addr = buf;
937 ctx->code_size = range->size;
938 return 0;
939 }
940
dump_hbrt_map(struct opal_prd_ctx * ctx)941 static void dump_hbrt_map(struct opal_prd_ctx *ctx)
942 {
943 const char *dump_name = "hbrt.bin";
944 int fd, rc;
945
946 if (!ctx->debug)
947 return;
948
949 fd = open(dump_name, O_WRONLY | O_CREAT, 0644);
950 if (fd < 0) {
951 pr_log(LOG_NOTICE, "IMAGE: couldn't debug image %s for writing",
952 dump_name);
953 return;
954 }
955
956 rc = ftruncate(fd, 0);
957 if (rc < 0) {
958 pr_log(LOG_NOTICE, "IMAGE: couldn't truncate image %s for writing",
959 dump_name);
960 return;
961 }
962 rc = write(fd, ctx->code_addr, ctx->code_size);
963 close(fd);
964
965 if (rc != ctx->code_size)
966 pr_log(LOG_NOTICE, "IMAGE: write to %s failed: %m", dump_name);
967 else
968 pr_debug("IMAGE: dumped HBRT binary to %s", dump_name);
969 }
970
open_and_read(const char * path,void ** bufp,int * lenp)971 static int open_and_read(const char *path, void **bufp, int *lenp)
972 {
973 struct stat statbuf;
974 int fd, rc, bytes;
975 void *buf;
976
977 fd = open(path, O_RDONLY);
978 if (fd < 0)
979 return -1;
980
981 rc = fstat(fd, &statbuf);
982 if (rc) {
983 close(fd);
984 return -1;
985 }
986
987 buf = malloc(statbuf.st_size);
988
989 for (rc = bytes = 0; bytes < statbuf.st_size; bytes += rc) {
990 rc = read(fd, buf + bytes, statbuf.st_size - bytes);
991 if (rc < 0) {
992 if (errno == EINTR)
993 continue;
994 break;
995 } else if (rc == 0)
996 break;
997 }
998
999 if (bytes == statbuf.st_size)
1000 rc = 0;
1001
1002 if (rc == 0) {
1003 if (lenp)
1004 *lenp = bytes;
1005 if (bufp)
1006 *bufp = buf;
1007 } else {
1008 free(buf);
1009 }
1010
1011 close(fd);
1012
1013 return rc == 0 ? 0 : -1;
1014 }
1015
prd_init_one_range(struct opal_prd_ctx * ctx,const char * path,struct dirent * dirent)1016 static int prd_init_one_range(struct opal_prd_ctx *ctx, const char *path,
1017 struct dirent *dirent)
1018 {
1019 char *label_path, *reg_path, *instance_path;
1020 struct prd_range *range;
1021 int label_len, len, rc;
1022 __be64 *reg;
1023 char *label;
1024 void *buf;
1025
1026 rc = asprintf(&label_path, "%s/%s/ibm,prd-label", path, dirent->d_name);
1027 if (rc < 0) {
1028 pr_log(LOG_ERR, "FW: error creating 'ibm,prd-label' path "
1029 "node: %m");
1030 return -1;
1031 }
1032 rc = asprintf(&instance_path, "%s/%s/ibm,prd-instance",
1033 path, dirent->d_name);
1034 if (rc < 0) {
1035 pr_log(LOG_ERR, "FW: error creating 'ibm,prd-instance' path "
1036 "node: %m");
1037 return -1;
1038 }
1039 rc = asprintf(®_path, "%s/%s/reg", path, dirent->d_name);
1040 if (rc < 0) {
1041 pr_log(LOG_ERR, "FW: error creating 'reg' path "
1042 " node: %m");
1043 return -1;
1044 }
1045
1046 reg = NULL;
1047 label = NULL;
1048 rc = -1;
1049
1050 rc = open_and_read(label_path, &buf, &label_len);
1051 if (rc)
1052 goto out_free;
1053
1054 label = buf;
1055
1056 if (label[label_len-1] != '\0')
1057 pr_log(LOG_INFO, "FW: node %s has invalid ibm,prd-label - "
1058 "not nul-terminated",
1059 dirent->d_name);
1060
1061 rc = open_and_read(reg_path, &buf, &len);
1062 if (rc)
1063 goto out_free;
1064
1065 reg = buf;
1066
1067 if (len != 2 * sizeof(*reg)) {
1068 pr_log(LOG_ERR, "FW: node %s has invalid 'reg' size: %d",
1069 dirent->d_name, len);
1070 goto out_free;
1071 }
1072
1073
1074 ctx->ranges = realloc(ctx->ranges, ++ctx->n_ranges * sizeof(*range));
1075 range = &ctx->ranges[ctx->n_ranges - 1];
1076 range->name = strndup(label, label_len);
1077 range->physaddr = be64toh(reg[0]);
1078 range->size = be64toh(reg[1]);
1079 range->buf = NULL;
1080 range->multiple = false;
1081 range->instance = 0;
1082
1083 /* optional instance */
1084 rc = open_and_read(instance_path, &buf, &len);
1085 if (!rc && len == sizeof(uint32_t)) {
1086 range->multiple = true;
1087 range->instance = be32toh(*(uint32_t *)buf);
1088 ctx->fw_range_instances = true;
1089 }
1090 rc = 0;
1091
1092 out_free:
1093 free(reg);
1094 free(label);
1095 free(instance_path);
1096 free(reg_path);
1097 free(label_path);
1098 return rc;
1099 }
1100
compare_ranges(const void * ap,const void * bp)1101 static int compare_ranges(const void *ap, const void *bp)
1102 {
1103 const struct prd_range *a = ap, *b = bp;
1104 int rc;
1105
1106 rc = strcmp(a->name, b->name);
1107 if (rc)
1108 return rc;
1109
1110 if (a->physaddr < b->physaddr)
1111 return -1;
1112 else if (a->physaddr > b->physaddr)
1113 return 1;
1114
1115 return 0;
1116 }
1117
assign_range_instances(struct opal_prd_ctx * ctx)1118 static void assign_range_instances(struct opal_prd_ctx *ctx)
1119 {
1120 int i;
1121
1122 if (!ctx->n_ranges)
1123 return;
1124
1125 ctx->ranges[0].multiple = false;
1126 ctx->ranges[0].instance = 0;
1127
1128 for (i = 1; i < ctx->n_ranges; i++) {
1129 struct prd_range *cur, *prev;
1130
1131 cur = &ctx->ranges[i];
1132 prev = &ctx->ranges[i-1];
1133
1134 if (!strcmp(cur->name, prev->name)) {
1135 prev->multiple = true;
1136 cur->multiple = true;
1137 cur->instance = prev->instance + 1;
1138 } else {
1139 cur->multiple = false;
1140 cur->instance = 0;
1141 }
1142 }
1143 }
1144
print_ranges(struct opal_prd_ctx * ctx)1145 static void print_ranges(struct opal_prd_ctx *ctx)
1146 {
1147 int i;
1148
1149 if (ctx->n_ranges == 0)
1150 pr_log(LOG_INFO, "FW: No PRD ranges");
1151
1152 pr_log(LOG_DEBUG, "FW: %d PRD ranges, instances assigned by %s",
1153 ctx->n_ranges,
1154 ctx->fw_range_instances ? "firmware" : "userspace");
1155
1156 for (i = 0; i < ctx->n_ranges; i++) {
1157 struct prd_range *range = &ctx->ranges[i];
1158 char instance_str[20];
1159
1160 if (range->multiple)
1161 snprintf(instance_str, sizeof(instance_str),
1162 " [%d]", range->instance);
1163 else
1164 instance_str[0] = '\0';
1165
1166 pr_log(LOG_DEBUG, "FW: %016lx-%016lx %s%s", range->physaddr,
1167 range->physaddr + range->size - 1,
1168 range->name,
1169 instance_str);
1170 }
1171 }
1172
prd_init_ranges(struct opal_prd_ctx * ctx)1173 static int prd_init_ranges(struct opal_prd_ctx *ctx)
1174 {
1175 struct dirent *dirent;
1176 char *path;
1177 DIR *dir;
1178 int rc;
1179
1180 rc = asprintf(&path, "%s/reserved-memory", devicetree_base);
1181 if (rc < 0) {
1182 pr_log(LOG_ERR, "FW: error creating 'reserved-memory' path "
1183 "node: %m");
1184 return -1;
1185 }
1186
1187 rc = -1;
1188
1189 dir = opendir(path);
1190 if (!dir) {
1191 pr_log(LOG_ERR, "FW: can't open reserved-memory device-tree "
1192 "node: %m");
1193 goto out_free;
1194 }
1195
1196 for (;;) {
1197 dirent = readdir(dir);
1198 if (!dirent)
1199 break;
1200
1201 prd_init_one_range(ctx, path, dirent);
1202 }
1203
1204 rc = 0;
1205 /* sort ranges and assign instance numbers for duplicates (if the
1206 * firmware doesn't number instances for us) */
1207 qsort(ctx->ranges, ctx->n_ranges, sizeof(struct prd_range),
1208 compare_ranges);
1209
1210 if (!ctx->fw_range_instances)
1211 assign_range_instances(ctx);
1212
1213 print_ranges(ctx);
1214
1215 out_free:
1216 free(path);
1217 closedir(dir);
1218 return rc;
1219 }
1220
find_string(const char * buffer,size_t len,const char * s)1221 bool find_string(const char *buffer, size_t len, const char *s)
1222 {
1223 const char *c, *end;
1224
1225 if (!buffer)
1226 return false;
1227 c = buffer;
1228 end = c + len;
1229
1230 while (c < end) {
1231 if (!strcasecmp(s, c))
1232 return true;
1233 c += strlen(c) + 1;
1234 }
1235 return false;
1236 }
1237
is_prd_supported(void)1238 static int is_prd_supported(void)
1239 {
1240 char *path;
1241 int rc;
1242 int len;
1243 char *buf;
1244
1245 rc = asprintf(&path, "%s/ibm,opal/diagnostics/compatible",
1246 devicetree_base);
1247 if (rc < 0) {
1248 pr_log(LOG_ERR, "FW: error creating 'compatible' node path: %m");
1249 return -1;
1250 }
1251
1252 rc = open_and_read(path, (void *) &buf, &len);
1253 if (rc)
1254 goto out_free;
1255
1256 if (buf[len - 1] != '\0')
1257 pr_log(LOG_INFO, "FW: node %s is not nul-terminated", path);
1258
1259 rc = find_string(buf, len, "ibm,opal-prd") ? 0 : -1;
1260
1261 free(buf);
1262 out_free:
1263 free(path);
1264 return rc;
1265 }
1266
prd_init(struct opal_prd_ctx * ctx)1267 static int prd_init(struct opal_prd_ctx *ctx)
1268 {
1269 int rc;
1270
1271 ctx->page_size = sysconf(_SC_PAGE_SIZE);
1272
1273 /* set up the device, and do our get_info ioctl */
1274 ctx->fd = open(opal_prd_devnode, O_RDWR);
1275 if (ctx->fd < 0) {
1276 pr_log(LOG_ERR, "FW: Can't open PRD device %s: %m",
1277 opal_prd_devnode);
1278 return -1;
1279 }
1280
1281 rc = ioctl(ctx->fd, OPAL_PRD_GET_INFO, &ctx->info);
1282 if (rc) {
1283 pr_log(LOG_ERR, "FW: Can't query PRD information: %m");
1284 return -1;
1285 }
1286
1287 rc = prd_init_ranges(ctx);
1288 if (rc) {
1289 pr_log(LOG_ERR, "FW: can't parse PRD memory information");
1290 return -1;
1291 }
1292
1293 return 0;
1294 }
1295
handle_msg_attn(struct opal_prd_ctx * ctx,struct opal_prd_msg * msg)1296 static int handle_msg_attn(struct opal_prd_ctx *ctx, struct opal_prd_msg *msg)
1297 {
1298 uint64_t proc, ipoll_mask, ipoll_status;
1299 int rc;
1300
1301 proc = be64toh(msg->attn.proc);
1302 ipoll_status = be64toh(msg->attn.ipoll_status);
1303 ipoll_mask = be64toh(msg->attn.ipoll_mask);
1304
1305 if (!hservice_runtime->handle_attns) {
1306 pr_log_nocall("handle_attns");
1307 return -1;
1308 }
1309
1310 rc = call_handle_attns(proc, ipoll_status, ipoll_mask);
1311 if (rc) {
1312 pr_log(LOG_ERR, "HBRT: handle_attns(%lx,%lx,%lx) failed, rc %d",
1313 proc, ipoll_status, ipoll_mask, rc);
1314 return -1;
1315 }
1316
1317 /* send the response */
1318 msg->hdr.type = OPAL_PRD_MSG_TYPE_ATTN_ACK;
1319 msg->hdr.size = htobe16(sizeof(*msg));
1320 msg->attn_ack.proc = htobe64(proc);
1321 msg->attn_ack.ipoll_ack = htobe64(ipoll_status);
1322 rc = write(ctx->fd, msg, sizeof(*msg));
1323
1324 if (rc != sizeof(*msg)) {
1325 pr_log(LOG_WARNING, "FW: Failed to send ATTN_ACK message: %m");
1326 return -1;
1327 }
1328
1329 return 0;
1330 }
1331
handle_msg_occ_error(struct opal_prd_ctx * ctx,struct opal_prd_msg * msg)1332 static int handle_msg_occ_error(struct opal_prd_ctx *ctx,
1333 struct opal_prd_msg *msg)
1334 {
1335 uint32_t proc;
1336
1337 proc = be64toh(msg->occ_error.chip);
1338
1339 pr_debug("FW: firmware signaled OCC error for proc 0x%x", proc);
1340
1341 if (!hservice_runtime->process_occ_error) {
1342 pr_log_nocall("process_occ_error");
1343 return -1;
1344 }
1345
1346 call_process_occ_error(proc);
1347 return 0;
1348 }
1349
pm_complex_reset(uint64_t chip)1350 static int pm_complex_reset(uint64_t chip)
1351 {
1352 int rc;
1353
1354 /*
1355 * FSP system -> reset_pm_complex
1356 * BMC system -> process_occ_reset
1357 */
1358 if (is_fsp_system()) {
1359 if (!hservice_runtime->reset_pm_complex) {
1360 pr_log_nocall("reset_pm_complex");
1361 return -1;
1362 }
1363
1364 pr_debug("PM: calling pm_complex_reset(%ld)", chip);
1365 rc = call_reset_pm_complex(chip);
1366 } else {
1367 if (!hservice_runtime->process_occ_reset) {
1368 pr_log_nocall("process_occ_reset");
1369 return -1;
1370 }
1371
1372 pr_debug("PM: calling process_occ_reset(%ld)", chip);
1373 call_process_occ_reset(chip);
1374 rc = 0;
1375 }
1376
1377 return rc;
1378 }
1379
handle_msg_occ_reset(struct opal_prd_ctx * ctx,struct opal_prd_msg * msg)1380 static int handle_msg_occ_reset(struct opal_prd_ctx *ctx,
1381 struct opal_prd_msg *msg)
1382 {
1383 uint32_t proc;
1384 int rc;
1385
1386 proc = be64toh(msg->occ_reset.chip);
1387
1388 pr_debug("FW: firmware requested OCC reset for proc 0x%x", proc);
1389
1390 rc = pm_complex_reset(proc);
1391
1392 return rc;
1393 }
1394
handle_msg_firmware_notify(struct opal_prd_ctx * ctx,struct opal_prd_msg * msg)1395 static int handle_msg_firmware_notify(struct opal_prd_ctx *ctx,
1396 struct opal_prd_msg *msg)
1397 {
1398 uint64_t len;
1399 void *buf;
1400
1401 len = be64toh(msg->fw_notify.len);
1402 buf = msg->fw_notify.data;
1403
1404 pr_debug("FW: firmware notification, %ld bytes", len);
1405
1406 if (!hservice_runtime->firmware_notify) {
1407 pr_log_nocall("firmware_notify");
1408 return -1;
1409 }
1410
1411 call_firmware_notify(len, buf);
1412
1413 return 0;
1414 }
1415
handle_msg_sbe_passthrough(struct opal_prd_ctx * ctx,struct opal_prd_msg * msg)1416 static int handle_msg_sbe_passthrough(struct opal_prd_ctx *ctx,
1417 struct opal_prd_msg *msg)
1418 {
1419 uint32_t proc;
1420 int rc;
1421
1422 proc = be64toh(msg->sbe_passthrough.chip);
1423
1424 pr_debug("FW: firmware sent SBE pass through command for proc 0x%x\n",
1425 proc);
1426
1427 if (!hservice_runtime->sbe_message_passing) {
1428 pr_log_nocall("sbe_message_passing");
1429 return -1;
1430 }
1431
1432 rc = call_sbe_message_passing(proc);
1433 return rc;
1434 }
1435
handle_prd_msg(struct opal_prd_ctx * ctx,struct opal_prd_msg * msg)1436 static int handle_prd_msg(struct opal_prd_ctx *ctx, struct opal_prd_msg *msg)
1437 {
1438 int rc = -1;
1439
1440 switch (msg->hdr.type) {
1441 case OPAL_PRD_MSG_TYPE_ATTN:
1442 rc = handle_msg_attn(ctx, msg);
1443 break;
1444 case OPAL_PRD_MSG_TYPE_OCC_RESET:
1445 rc = handle_msg_occ_reset(ctx, msg);
1446 break;
1447 case OPAL_PRD_MSG_TYPE_OCC_ERROR:
1448 rc = handle_msg_occ_error(ctx, msg);
1449 break;
1450 case OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY:
1451 rc = handle_msg_firmware_notify(ctx, msg);
1452 break;
1453 case OPAL_PRD_MSG_TYPE_SBE_PASSTHROUGH:
1454 rc = handle_msg_sbe_passthrough(ctx, msg);
1455 break;
1456 default:
1457 pr_log(LOG_WARNING, "Invalid incoming message type 0x%x",
1458 msg->hdr.type);
1459 }
1460
1461 return rc;
1462 }
1463
1464 #define list_for_each_pop(h, i, type, member) \
1465 for (i = list_pop((h), type, member); \
1466 i; \
1467 i = list_pop((h), type, member))
1468
1469
process_msgq(struct opal_prd_ctx * ctx)1470 static int process_msgq(struct opal_prd_ctx *ctx)
1471 {
1472 struct prd_msgq_item *item;
1473
1474 list_for_each_pop(&ctx->msgq, item, struct prd_msgq_item, list) {
1475 handle_prd_msg(ctx, &item->msg);
1476 free(item);
1477 }
1478
1479 return 0;
1480 }
1481
read_prd_msg(struct opal_prd_ctx * ctx)1482 static int read_prd_msg(struct opal_prd_ctx *ctx)
1483 {
1484 struct opal_prd_msg *msg;
1485 int size;
1486 int rc;
1487
1488 msg = ctx->msg;
1489
1490 rc = read(ctx->fd, msg, ctx->msg_alloc_len);
1491 if (rc < 0 && errno == EAGAIN)
1492 return -1;
1493
1494 /* we need at least enough for the message header... */
1495 if (rc < 0) {
1496 pr_log(LOG_WARNING, "FW: error reading from firmware: %m");
1497 return -1;
1498 }
1499
1500 if (rc < sizeof(msg->hdr)) {
1501 pr_log(LOG_WARNING, "FW: short message read from firmware");
1502 return -1;
1503 }
1504
1505 /* ... and for the reported message size to be sane */
1506 size = htobe16(msg->hdr.size);
1507 if (size < sizeof(msg->hdr)) {
1508 pr_log(LOG_ERR, "FW: Mismatched message size "
1509 "between opal-prd and firmware "
1510 "(%d from FW, %zd expected)",
1511 size, sizeof(msg->hdr));
1512 return -1;
1513 }
1514
1515 /* expand our message buffer if necessary... */
1516 if (size > ctx->msg_alloc_len) {
1517 msg = realloc(ctx->msg, size);
1518 if (!msg) {
1519 pr_log(LOG_ERR,
1520 "FW: Can't expand PRD message buffer: %m");
1521 return -1;
1522 }
1523 ctx->msg = msg;
1524 ctx->msg_alloc_len = size;
1525 }
1526
1527 /* ... and complete the read */
1528 if (size > rc) {
1529 size_t pos;
1530
1531 for (pos = rc; pos < size;) {
1532 rc = read(ctx->fd, msg + pos, size - pos);
1533
1534 if (rc < 0 && errno == EAGAIN)
1535 continue;
1536
1537 if (rc <= 0) {
1538 pr_log(LOG_WARNING,
1539 "FW: error reading from firmware: %m");
1540 return -1;
1541 }
1542
1543 pos += rc;
1544 }
1545 }
1546
1547 return 0;
1548 }
1549
handle_prd_control_occ_error(struct control_msg * send_msg,struct control_msg * recv_msg)1550 static void handle_prd_control_occ_error(struct control_msg *send_msg,
1551 struct control_msg *recv_msg)
1552 {
1553 uint64_t chip;
1554
1555 if (!hservice_runtime->process_occ_error) {
1556 pr_log_nocall("process_occ_error");
1557 return;
1558 }
1559
1560 chip = recv_msg->occ_error.chip;
1561
1562 pr_debug("CTRL: calling process_occ_error(%lu)", chip);
1563 call_process_occ_error(chip);
1564
1565 send_msg->data_len = 0;
1566 send_msg->response = 0;
1567 }
1568
handle_prd_control_occ_reset(struct control_msg * send_msg,struct control_msg * msg)1569 static void handle_prd_control_occ_reset(struct control_msg *send_msg,
1570 struct control_msg *msg)
1571 {
1572 struct opal_prd_msg omsg;
1573 uint64_t chip;
1574 int rc;
1575
1576 /* notify OPAL of the impending reset */
1577 memset(&omsg, 0, sizeof(omsg));
1578 omsg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_RESET_NOTIFY;
1579 omsg.hdr.size = htobe16(sizeof(omsg));
1580 rc = write(ctx->fd, &omsg, sizeof(omsg));
1581 if (rc != sizeof(omsg))
1582 pr_log(LOG_WARNING, "FW: Failed to send OCC_RESET message: %m");
1583
1584 chip = msg->occ_reset.chip;
1585
1586 /* do reset */
1587 pr_debug("CTRL: Calling OCC reset on chip %ld", chip);
1588 pm_complex_reset(chip);
1589
1590 send_msg->data_len = 0;
1591 send_msg->response = 0;
1592 }
1593
handle_prd_control_occ_actuation(struct control_msg * msg,bool enable)1594 static void handle_prd_control_occ_actuation(struct control_msg *msg,
1595 bool enable)
1596 {
1597 if (!hservice_runtime->enable_occ_actuation) {
1598 pr_log_nocall("enable_occ_actuation");
1599 return;
1600 }
1601
1602 pr_debug("CTRL: calling enable_occ_actuation(%s)",
1603 enable ? "true" : "false");
1604 msg->data_len = 0;
1605 msg->response = call_enable_occ_actuation(enable);
1606 }
1607
handle_prd_control_attr_override(struct control_msg * send_msg,struct control_msg * recv_msg)1608 static void handle_prd_control_attr_override(struct control_msg *send_msg,
1609 struct control_msg *recv_msg)
1610 {
1611 if (!hservice_runtime->apply_attr_override) {
1612 pr_log_nocall("apply_attr_override");
1613 return;
1614 }
1615
1616 pr_debug("CTRL: calling apply_attr_override");
1617 send_msg->response = call_apply_attr_override(
1618 recv_msg->data, recv_msg->data_len);
1619 send_msg->data_len = 0;
1620 }
1621
handle_prd_control_htmgt_passthru(struct control_msg * send_msg,struct control_msg * recv_msg)1622 static void handle_prd_control_htmgt_passthru(struct control_msg *send_msg,
1623 struct control_msg *recv_msg)
1624 {
1625 uint16_t rsp_len;
1626
1627 if (!hservice_runtime->mfg_htmgt_pass_thru) {
1628 pr_log_nocall("mfg_htmgt_pass_thru");
1629 return;
1630 }
1631
1632 pr_debug("CTRL: calling mfg_htmgt_pass_thru");
1633 send_msg->response = call_mfg_htmgt_pass_thru(recv_msg->data_len,
1634 recv_msg->data, &rsp_len,
1635 send_msg->data);
1636 send_msg->data_len = be16toh(rsp_len);
1637 if (send_msg->data_len > MAX_CONTROL_MSG_BUF) {
1638 pr_log(LOG_ERR, "CTRL: response buffer overrun, data len: %d",
1639 send_msg->data_len);
1640 send_msg->data_len = MAX_CONTROL_MSG_BUF;
1641 }
1642 }
1643
handle_prd_control_run_cmd(struct control_msg * send_msg,struct control_msg * recv_msg)1644 static void handle_prd_control_run_cmd(struct control_msg *send_msg,
1645 struct control_msg *recv_msg)
1646 {
1647 char *runcmd_output, *s;
1648 const char **argv;
1649 int i, argc;
1650 size_t size;
1651
1652 if (!hservice_runtime->run_command) {
1653 pr_log_nocall("run_command");
1654 return;
1655 }
1656
1657 argc = recv_msg->run_cmd.argc;
1658 pr_debug("CTRL: run_command, argc:%d\n", argc);
1659
1660 argv = malloc(argc * sizeof(*argv));
1661 if (!argv) {
1662 pr_log(LOG_ERR, "CTRL: argv buffer malloc failed: %m");
1663 return;
1664 }
1665
1666 s = (char *)recv_msg->data;
1667 size = 0;
1668 for (i = 0; i < argc; i++) {
1669 argv[i] = (char *)htobe64((uint64_t)&s[size]);
1670 size += (strlen(&s[size]) + 1);
1671 }
1672
1673 /* Call HBRT */
1674 send_msg->response = call_run_command(argc, argv, &runcmd_output);
1675 runcmd_output = (char *)be64toh((uint64_t)runcmd_output);
1676 free(argv);
1677
1678 s = (char *)send_msg->data;
1679 if (runcmd_output) {
1680 size = strlen(runcmd_output);
1681 if (size >= MAX_CONTROL_MSG_BUF) {
1682 pr_log(LOG_WARNING, "CTRL: output message truncated");
1683 runcmd_output[MAX_CONTROL_MSG_BUF] = '\0';
1684 size = MAX_CONTROL_MSG_BUF;
1685 }
1686
1687 strcpy(s, runcmd_output);
1688 send_msg->data_len = size + 1;
1689 free(runcmd_output);
1690 } else {
1691 strcpy(s, "Null");
1692 send_msg->data_len = strlen("Null") + 1;
1693 }
1694 }
1695
handle_prd_control(struct opal_prd_ctx * ctx,int fd)1696 static void handle_prd_control(struct opal_prd_ctx *ctx, int fd)
1697 {
1698 struct control_msg msg, *recv_msg, *send_msg;
1699 bool enabled = false;
1700 int rc, size;
1701
1702 /* Default reply, in the error path */
1703 send_msg = &msg;
1704
1705 /* Peek into the socket to ascertain the size of the available data */
1706 rc = recv(fd, &msg, sizeof(msg), MSG_PEEK);
1707 if (rc != sizeof(msg)) {
1708 pr_log(LOG_WARNING, "CTRL: failed to receive control "
1709 "message: %m");
1710 msg.response = -1;
1711 msg.data_len = 0;
1712 goto out_send;
1713 }
1714
1715 size = sizeof(*recv_msg) + msg.data_len;
1716
1717 /* Default reply, in the error path */
1718 msg.data_len = 0;
1719 msg.response = -1;
1720
1721 recv_msg = malloc(size);
1722 if (!recv_msg) {
1723 pr_log(LOG_ERR, "CTRL: message buffer malloc failed: %m");
1724 goto out_send;
1725 }
1726
1727 rc = recv(fd, recv_msg, size, MSG_TRUNC);
1728 if (rc != size) {
1729 pr_log(LOG_WARNING, "CTRL: failed to receive control "
1730 "message: %m");
1731 goto out_free_recv;
1732 }
1733
1734 send_msg = malloc(sizeof(*send_msg) + MAX_CONTROL_MSG_BUF);
1735 if (!send_msg) {
1736 pr_log(LOG_ERR, "CTRL: message buffer malloc failed: %m");
1737 send_msg = &msg;
1738 goto out_free_recv;
1739 }
1740
1741 send_msg->type = recv_msg->type;
1742 send_msg->response = -1;
1743 switch (recv_msg->type) {
1744 case CONTROL_MSG_ENABLE_OCCS:
1745 enabled = true;
1746 /* fall through */
1747 case CONTROL_MSG_DISABLE_OCCS:
1748 handle_prd_control_occ_actuation(send_msg, enabled);
1749 break;
1750 case CONTROL_MSG_TEMP_OCC_RESET:
1751 handle_prd_control_occ_reset(send_msg, recv_msg);
1752 break;
1753 case CONTROL_MSG_TEMP_OCC_ERROR:
1754 handle_prd_control_occ_error(send_msg, recv_msg);
1755 break;
1756 case CONTROL_MSG_ATTR_OVERRIDE:
1757 handle_prd_control_attr_override(send_msg, recv_msg);
1758 break;
1759 case CONTROL_MSG_HTMGT_PASSTHRU:
1760 handle_prd_control_htmgt_passthru(send_msg, recv_msg);
1761 break;
1762 case CONTROL_MSG_RUN_CMD:
1763 handle_prd_control_run_cmd(send_msg, recv_msg);
1764 break;
1765 default:
1766 pr_log(LOG_WARNING, "CTRL: Unknown control message action %d",
1767 recv_msg->type);
1768 send_msg->data_len = 0;
1769 break;
1770 }
1771
1772 out_free_recv:
1773 free(recv_msg);
1774 out_send:
1775 size = sizeof(*send_msg) + send_msg->data_len;
1776 rc = send(fd, send_msg, size, MSG_DONTWAIT | MSG_NOSIGNAL);
1777 if (rc && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EPIPE))
1778 pr_debug("CTRL: control send() returned %d, ignoring failure",
1779 rc);
1780 else if (rc != size)
1781 pr_log(LOG_NOTICE, "CTRL: Failed to send control response: %m");
1782
1783 if (send_msg != &msg)
1784 free(send_msg);
1785 }
1786
run_attn_loop(struct opal_prd_ctx * ctx)1787 static int run_attn_loop(struct opal_prd_ctx *ctx)
1788 {
1789 struct pollfd pollfds[2];
1790 struct opal_prd_msg msg;
1791 int rc, fd;
1792
1793 if (hservice_runtime->enable_attns) {
1794 pr_debug("HBRT: calling enable_attns");
1795 rc = call_enable_attns();
1796 if (rc) {
1797 pr_log(LOG_ERR, "HBRT: enable_attns() failed, "
1798 "aborting");
1799 return -1;
1800 }
1801 }
1802
1803 if (hservice_runtime->get_ipoll_events) {
1804 pr_debug("HBRT: calling get_ipoll_events");
1805 opal_prd_ipoll = call_get_ipoll_events();
1806 }
1807
1808 pr_debug("HBRT: enabling IPOLL events 0x%016lx", opal_prd_ipoll);
1809
1810 /* send init message, to unmask interrupts */
1811 msg.hdr.type = OPAL_PRD_MSG_TYPE_INIT;
1812 msg.hdr.size = htobe16(sizeof(msg));
1813 msg.init.version = htobe64(opal_prd_version);
1814 msg.init.ipoll = htobe64(opal_prd_ipoll);
1815
1816 pr_debug("FW: writing init message");
1817 rc = write(ctx->fd, &msg, sizeof(msg));
1818 if (rc != sizeof(msg)) {
1819 pr_log(LOG_ERR, "FW: Init message failed: %m. Aborting.");
1820 return -1;
1821 }
1822
1823 pollfds[0].fd = ctx->fd;
1824 pollfds[0].events = POLLIN | POLLERR;
1825 pollfds[1].fd = ctx->socket;
1826 pollfds[1].events = POLLIN | POLLERR;
1827
1828 for (;;) {
1829 /* run through any pending messages */
1830 process_msgq(ctx);
1831
1832 rc = poll(pollfds, 2, -1);
1833 if (rc < 0) {
1834 pr_log(LOG_ERR, "FW: event poll failed: %m");
1835 exit(EXIT_FAILURE);
1836 }
1837
1838 if (!rc)
1839 continue;
1840
1841 if (pollfds[0].revents & POLLIN) {
1842 rc = read_prd_msg(ctx);
1843 if (!rc)
1844 handle_prd_msg(ctx, ctx->msg);
1845 }
1846
1847 if (pollfds[1].revents & POLLIN) {
1848 fd = accept(ctx->socket, NULL, NULL);
1849 if (fd < 0) {
1850 pr_log(LOG_NOTICE, "CTRL: accept failed: %m");
1851 continue;
1852 }
1853 handle_prd_control(ctx, fd);
1854 close(fd);
1855 }
1856 }
1857
1858 return 0;
1859 }
1860
init_control_socket(struct opal_prd_ctx * ctx)1861 static int init_control_socket(struct opal_prd_ctx *ctx)
1862 {
1863 struct sockaddr_un addr;
1864 int fd, rc;
1865
1866 unlink(opal_prd_socket);
1867
1868 addr.sun_family = AF_UNIX;
1869 strcpy(addr.sun_path, opal_prd_socket);
1870
1871 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
1872 if (fd < 0) {
1873 pr_log(LOG_WARNING, "CTRL: Can't open control socket %s: %m",
1874 opal_prd_socket);
1875 return -1;
1876 }
1877
1878 rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
1879 if (rc) {
1880 pr_log(LOG_WARNING, "CTRL: Can't bind control socket %s: %m",
1881 opal_prd_socket);
1882 close(fd);
1883 return -1;
1884 }
1885
1886 rc = listen(fd, 0);
1887 if (rc) {
1888 pr_log(LOG_WARNING, "CTRL: Can't listen on "
1889 "control socket %s: %m", opal_prd_socket);
1890 close(fd);
1891 return -1;
1892 }
1893
1894 pr_log(LOG_INFO, "CTRL: Listening on control socket %s",
1895 opal_prd_socket);
1896
1897 ctx->socket = fd;
1898 return 0;
1899 }
1900
1901
run_prd_daemon(struct opal_prd_ctx * ctx)1902 static int run_prd_daemon(struct opal_prd_ctx *ctx)
1903 {
1904 int rc;
1905
1906 /* log to syslog */
1907 pr_log_daemon_init();
1908
1909 pr_debug("CTRL: Starting PRD daemon\n");
1910
1911 ctx->fd = -1;
1912 ctx->socket = -1;
1913
1914 /* set up our message buffer */
1915 ctx->msg_alloc_len = sizeof(*ctx->msg);
1916 ctx->msg = malloc(ctx->msg_alloc_len);
1917 if (!ctx->msg) {
1918 pr_log(LOG_ERR, "FW: Can't allocate PRD message buffer: %m");
1919 return -1;
1920 }
1921
1922
1923 list_head_init(&ctx->msgq);
1924
1925 i2c_init();
1926
1927 #ifdef DEBUG_I2C
1928 {
1929 uint8_t foo[128];
1930 int i;
1931
1932 rc = i2c_read(0, 1, 2, 0x50, 2, 0x10, 128, foo);
1933 pr_debug("I2C: read rc: %d", rc);
1934 for (i = 0; i < sizeof(foo); i += 8) {
1935 pr_debug("I2C: %02x %02x %02x %02x %02x %02x %02x %02x",
1936 foo[i + 0], foo[i + 1], foo[i + 2], foo[i + 3],
1937 foo[i + 4], foo[i + 5], foo[i + 6], foo[i + 7]);
1938 }
1939 }
1940 #endif
1941 rc = init_control_socket(ctx);
1942 if (rc) {
1943 pr_log(LOG_WARNING, "CTRL: Error initialising PRD control: %m");
1944 goto out_close;
1945 }
1946
1947
1948 rc = prd_init(ctx);
1949 if (rc) {
1950 pr_log(LOG_ERR, "FW: Error initialising PRD channel");
1951 goto out_close;
1952 }
1953
1954 if (ctx->hbrt_file_name) {
1955 rc = map_hbrt_file(ctx, ctx->hbrt_file_name);
1956 if (rc) {
1957 pr_log(LOG_ERR, "IMAGE: Can't access hbrt file %s",
1958 ctx->hbrt_file_name);
1959 goto out_close;
1960 }
1961 } else {
1962 rc = map_hbrt_physmem(ctx, hbrt_code_region_name);
1963 if (rc) {
1964 pr_log(LOG_ERR, "IMAGE: Can't access hbrt "
1965 "physical memory");
1966 goto out_close;
1967 }
1968 dump_hbrt_map(ctx);
1969 }
1970
1971 pr_debug("IMAGE: hbrt map at %p, size 0x%zx",
1972 ctx->code_addr, ctx->code_size);
1973
1974 fixup_hinterface_table();
1975
1976 if (pnor_available(&ctx->pnor)) {
1977 rc = pnor_init(&ctx->pnor);
1978 if (rc) {
1979 pr_log(LOG_ERR, "PNOR: Failed to open pnor: %m");
1980 goto out_close;
1981 }
1982 } else {
1983 /* Disable PNOR function pointers */
1984 hinterface.pnor_read = NULL;
1985 hinterface.pnor_write = NULL;
1986 }
1987
1988 ipmi_init(ctx);
1989
1990 pr_debug("HBRT: calling hservices_init");
1991 rc = hservices_init(ctx, ctx->code_addr);
1992 if (rc) {
1993 pr_log(LOG_ERR, "HBRT: Can't initialise HBRT");
1994 goto out_close;
1995 }
1996 pr_debug("HBRT: hservices_init done");
1997
1998 /* Test a scom */
1999 if (ctx->debug) {
2000 uint64_t val;
2001 pr_debug("SCOM: trying scom read");
2002 fflush(stdout);
2003 hservice_scom_read(0x00, 0xf000f, &val);
2004 pr_debug("SCOM: f00f: %lx", be64toh(val));
2005 }
2006
2007 run_attn_loop(ctx);
2008 rc = 0;
2009
2010 out_close:
2011 pr_debug("CTRL: stopping PRD daemon\n");
2012 pnor_close(&ctx->pnor);
2013 if (ctx->fd != -1)
2014 close(ctx->fd);
2015 if (ctx->socket != -1)
2016 close(ctx->socket);
2017 if (ctx->msg)
2018 free(ctx->msg);
2019 return rc;
2020 }
2021
send_prd_control(struct control_msg * send_msg,struct control_msg ** recv_msg)2022 static int send_prd_control(struct control_msg *send_msg,
2023 struct control_msg **recv_msg)
2024 {
2025 struct sockaddr_un addr;
2026 struct control_msg *msg;
2027 int sd, rc, size;
2028
2029 sd = socket(AF_UNIX, SOCK_STREAM, 0);
2030 if (!sd) {
2031 pr_log(LOG_ERR, "CTRL: Failed to create control socket: %m");
2032 return -1;
2033 }
2034
2035 addr.sun_family = AF_UNIX;
2036 strcpy(addr.sun_path, opal_prd_socket);
2037
2038 rc = connect(sd, (struct sockaddr *)&addr, sizeof(addr));
2039 if (rc) {
2040 pr_log(LOG_ERR, "CTRL: Failed to connect to prd daemon: %m");
2041 goto out_close;
2042 }
2043
2044 size = sizeof(*send_msg) + send_msg->data_len;
2045 rc = send(sd, send_msg, size, 0);
2046 if (rc != size) {
2047 pr_log(LOG_ERR, "CTRL: Failed to send control message: %m");
2048 rc = -1;
2049 goto out_close;
2050 }
2051
2052 size = sizeof(*msg) + MAX_CONTROL_MSG_BUF;
2053 msg = malloc(size);
2054 if (!msg) {
2055 pr_log(LOG_ERR, "CTRL: msg buffer malloc failed: %m");
2056 rc = -1;
2057 goto out_close;
2058 }
2059
2060 *recv_msg = msg;
2061
2062 /* wait for our reply */
2063 rc = recv(sd, msg, size, 0);
2064 if (rc < 0) {
2065 pr_log(LOG_ERR, "CTRL: Failed to receive control message: %m");
2066 goto out_close;
2067
2068 } else if (rc != (sizeof(*msg) + msg->data_len)) {
2069 pr_log(LOG_WARNING, "CTRL: Short read from control socket");
2070 rc = -1;
2071 goto out_close;
2072 }
2073
2074 rc = msg->response;
2075
2076 out_close:
2077 close(sd);
2078 return rc;
2079 }
2080
send_occ_control(struct opal_prd_ctx * ctx,int argc,char * argv[])2081 static int send_occ_control(struct opal_prd_ctx *ctx, int argc, char *argv[])
2082 {
2083 struct control_msg send_msg, *recv_msg = NULL;
2084 unsigned long chip = 0;
2085 const char *op;
2086 int rc;
2087
2088 assert(argc >= 1);
2089 op = argv[0];
2090
2091 /* some commands accept a 'chip' argument, so parse it here */
2092 if (argc > 1) {
2093 char *arg, *end;
2094 arg = argv[1];
2095 chip = strtoul(arg, &end, 0);
2096 if (end == arg) {
2097 pr_log(LOG_ERR, "CTRL: invalid argument %s", arg);
2098 return -1;
2099 }
2100 }
2101
2102 memset(&send_msg, 0, sizeof(send_msg));
2103
2104 if (!strcmp(op, "enable"))
2105 send_msg.type = CONTROL_MSG_ENABLE_OCCS;
2106 else if (!strcmp(op, "disable"))
2107 send_msg.type = CONTROL_MSG_DISABLE_OCCS;
2108
2109 else if (!strcmp(op, "reset")) {
2110 send_msg.type = CONTROL_MSG_TEMP_OCC_RESET;
2111 send_msg.occ_reset.chip = (uint64_t)chip;
2112
2113 } else if (!strcmp(op, "process-error")) {
2114 send_msg.type = CONTROL_MSG_TEMP_OCC_ERROR;
2115 send_msg.occ_error.chip = (uint64_t)chip;
2116 } else {
2117 pr_log(LOG_ERR, "CTRL: Invalid OCC action '%s'", op);
2118 return -1;
2119 }
2120
2121 rc = send_prd_control(&send_msg, &recv_msg);
2122 if (recv_msg) {
2123 if (recv_msg->response || ctx->debug)
2124 pr_debug("CTRL: OCC action %s returned status %d", op,
2125 recv_msg->response);
2126 free(recv_msg);
2127 }
2128
2129 return rc;
2130 }
2131
send_attr_override(struct opal_prd_ctx * ctx,uint32_t argc,char * argv[])2132 static int send_attr_override(struct opal_prd_ctx *ctx, uint32_t argc,
2133 char *argv[])
2134 {
2135 struct control_msg *send_msg, *recv_msg = NULL;
2136 struct stat statbuf;
2137 size_t sz;
2138 FILE *fd;
2139 int rc;
2140
2141 rc = stat(argv[0], &statbuf);
2142 if (rc) {
2143 pr_log(LOG_ERR, "CTRL: stat() failed on the file: %m");
2144 return -1;
2145 }
2146
2147 send_msg = malloc(sizeof(*send_msg) + statbuf.st_size);
2148 if (!send_msg) {
2149 pr_log(LOG_ERR, "CTRL: msg buffer malloc failed: %m");
2150 return -1;
2151 }
2152
2153 send_msg->type = CONTROL_MSG_ATTR_OVERRIDE;
2154 send_msg->data_len = statbuf.st_size;
2155
2156 fd = fopen(argv[0], "r");
2157 if (!fd) {
2158 pr_log(LOG_NOTICE, "CTRL: can't open %s: %m", argv[0]);
2159 rc = -1;
2160 goto out_free;
2161 }
2162
2163 sz = fread(send_msg->data, 1, send_msg->data_len, fd);
2164 fclose(fd);
2165 if (sz != statbuf.st_size) {
2166 pr_log(LOG_ERR, "CTRL: short read from the file");
2167 rc = -1;
2168 goto out_free;
2169 }
2170
2171 rc = send_prd_control(send_msg, &recv_msg);
2172 if (recv_msg) {
2173 if (recv_msg->response || ctx->debug)
2174 pr_debug("CTRL: attribute override returned status %d",
2175 recv_msg->response);
2176 free(recv_msg);
2177 }
2178
2179 out_free:
2180 free(send_msg);
2181 return rc;
2182 }
2183
send_htmgt_passthru(struct opal_prd_ctx * ctx,int argc,char * argv[])2184 static int send_htmgt_passthru(struct opal_prd_ctx *ctx, int argc, char *argv[])
2185 {
2186 struct control_msg *send_msg, *recv_msg = NULL;
2187 int rc, i;
2188
2189 if (!ctx->expert_mode) {
2190 pr_log(LOG_WARNING, "CTRL: need to be in expert mode");
2191 return -1;
2192 }
2193
2194 send_msg = malloc(sizeof(*send_msg) + argc);
2195 if (!send_msg) {
2196 pr_log(LOG_ERR, "CTRL: message buffer malloc failed: %m");
2197 return -1;
2198 }
2199
2200 send_msg->type = CONTROL_MSG_HTMGT_PASSTHRU;
2201 send_msg->data_len = argc;
2202
2203 if (ctx->debug)
2204 pr_debug("CTRL: HTMGT passthru arguments:");
2205
2206 for (i = 0; i < argc; i++) {
2207 if (ctx->debug)
2208 pr_debug("argv[%d] = %s", i, argv[i]);
2209
2210 sscanf(argv[i], "%hhx", &send_msg->data[i]);
2211 }
2212
2213 rc = send_prd_control(send_msg, &recv_msg);
2214 free(send_msg);
2215
2216 if (recv_msg) {
2217 if (recv_msg->response || ctx->debug)
2218 pr_debug("CTRL: HTMGT passthru returned status %d",
2219 recv_msg->response);
2220 if (recv_msg->response == 0 && recv_msg->data_len)
2221 hexdump(recv_msg->data, recv_msg->data_len);
2222
2223 free(recv_msg);
2224 }
2225
2226 return rc;
2227 }
2228
send_run_command(struct opal_prd_ctx * ctx,int argc,char * argv[])2229 static int send_run_command(struct opal_prd_ctx *ctx, int argc, char *argv[])
2230 {
2231 struct control_msg *send_msg, *recv_msg = NULL;
2232 uint32_t size = 0;
2233 int rc, i;
2234 char *s;
2235
2236 if (!ctx->expert_mode) {
2237 pr_log(LOG_WARNING, "CTRL: need to be in expert mode");
2238 return -1;
2239 }
2240
2241 if (ctx->debug) {
2242 pr_debug("CTRL: run command arguments:");
2243 for (i=0; i < argc; i++)
2244 pr_debug("argv[%d] = %s", i, argv[i]);
2245 }
2246
2247 for (i = 0; i < argc; i++)
2248 size += (strlen(argv[i]) + 1);
2249
2250 send_msg = malloc(sizeof(*send_msg) + size);
2251 if (!send_msg) {
2252 pr_log(LOG_ERR, "CTRL: msg buffer malloc failed: %m");
2253 return -1;
2254 }
2255
2256 /* Setup message */
2257 send_msg->type = CONTROL_MSG_RUN_CMD;
2258 send_msg->run_cmd.argc = argc;
2259 send_msg->data_len = size;
2260 s = (char *)send_msg->data;
2261 for (i = 0; i < argc; i++) {
2262 strcpy(s, argv[i]);
2263 s = s + strlen(argv[i]) + 1;
2264 }
2265
2266 rc = send_prd_control(send_msg, &recv_msg);
2267 free(send_msg);
2268 if (recv_msg) {
2269 if (!rc)
2270 pr_log(LOG_INFO, "Received: %s", recv_msg->data);
2271
2272 if (recv_msg->response || ctx->debug)
2273 pr_debug("CTRL: run command returned status %d",
2274 recv_msg->response);
2275 free(recv_msg);
2276 }
2277
2278 return rc;
2279 }
2280
usage(const char * progname)2281 static void usage(const char *progname)
2282 {
2283 printf("Usage:\n");
2284 printf("\t%s [--debug] [--file <hbrt-image>] [--pnor <device>]\n",
2285 progname);
2286 printf("\t%s occ <enable|disable|reset [chip]>\n", progname);
2287 printf("\t%s pm-complex reset [chip]>\n", progname);
2288 printf("\t%s htmgt-passthru <bytes...>\n", progname);
2289 printf("\t%s override <FILE>\n", progname);
2290 printf("\t%s run [arg 0] [arg 1]..[arg n]\n", progname);
2291 printf("\n");
2292 printf("Options:\n"
2293 "\t--debug verbose logging for debug information\n"
2294 "\t--pnor DEVICE use PNOR MTD device\n"
2295 "\t--file FILE use FILE for hostboot runtime code (instead of code\n"
2296 "\t exported by firmware)\n"
2297 "\t--stdio log to stdio, instead of syslog\n");
2298 }
2299
print_version(void)2300 static void print_version(void)
2301 {
2302 extern const char version[];
2303 printf("opal-prd %s\n", version);
2304 }
2305
2306 static struct option opal_diag_options[] = {
2307 {"file", required_argument, NULL, 'f'},
2308 {"pnor", required_argument, NULL, 'p'},
2309 {"debug", no_argument, NULL, 'd'},
2310 {"help", no_argument, NULL, 'h'},
2311 {"version", no_argument, NULL, 'v'},
2312 {"stdio", no_argument, NULL, 's'},
2313 {"expert-mode", no_argument, NULL, 'e'},
2314 { 0 },
2315 };
2316
2317 enum action {
2318 ACTION_RUN_DAEMON,
2319 ACTION_OCC_CONTROL,
2320 ACTION_ATTR_OVERRIDE,
2321 ACTION_HTMGT_PASSTHRU,
2322 ACTION_RUN_COMMAND,
2323 };
2324
parse_action(const char * str,enum action * action)2325 static int parse_action(const char *str, enum action *action)
2326 {
2327 int rc;
2328
2329 if (!strcmp(str, "occ")) {
2330 *action = ACTION_OCC_CONTROL;
2331 rc = 0;
2332
2333 if (is_fsp_system()) {
2334 pr_log(LOG_ERR, "CTRL: occ commands are not "
2335 "supported on this system");
2336 rc = -1;
2337 }
2338 } else if (!strcmp(str, "pm-complex")) {
2339 *action = ACTION_OCC_CONTROL;
2340 rc = 0;
2341
2342 if (!is_fsp_system()) {
2343 pr_log(LOG_ERR, "CTRL: pm-complex commands are not "
2344 "supported on this system");
2345 rc = -1;
2346 }
2347 } else if (!strcmp(str, "daemon")) {
2348 *action = ACTION_RUN_DAEMON;
2349 rc = 0;
2350 } else if (!strcmp(str, "override")) {
2351 *action = ACTION_ATTR_OVERRIDE;
2352 rc = 0;
2353 } else if (!strcmp(str, "htmgt-passthru")) {
2354 *action = ACTION_HTMGT_PASSTHRU;
2355 rc = 0;
2356 } else if (!strcmp(str, "run")) {
2357 *action = ACTION_RUN_COMMAND;
2358 return 0;
2359 } else {
2360 pr_log(LOG_ERR, "CTRL: unknown argument '%s'", str);
2361 rc = -1;
2362 }
2363
2364 return rc;
2365 }
2366
main(int argc,char * argv[])2367 int main(int argc, char *argv[])
2368 {
2369 struct opal_prd_ctx _ctx;
2370 enum action action;
2371 int rc;
2372
2373 check_abi();
2374
2375 ctx = &_ctx;
2376 memset(ctx, 0, sizeof(*ctx));
2377 ctx->vlog = pr_log_stdio;
2378 ctx->use_syslog = true;
2379
2380 /* Parse options */
2381 for (;;) {
2382 int c;
2383
2384 c = getopt_long(argc, argv, "f:p:dhse", opal_diag_options, NULL);
2385 if (c == -1)
2386 break;
2387
2388 switch (c) {
2389 case 'f':
2390 ctx->hbrt_file_name = optarg;
2391 break;
2392 case 'd':
2393 ctx->debug = true;
2394 break;
2395 case 'p':
2396 ctx->pnor.path = strndup(optarg, PATH_MAX);
2397 break;
2398 case 's':
2399 ctx->use_syslog = false;
2400 break;
2401 case 'h':
2402 usage(argv[0]);
2403 return EXIT_SUCCESS;
2404 case 'e':
2405 ctx->expert_mode = true;
2406 break;
2407 case 'v':
2408 print_version();
2409 return EXIT_SUCCESS;
2410 case '?':
2411 default:
2412 usage(argv[0]);
2413 return EXIT_FAILURE;
2414 }
2415 }
2416
2417 if (optind < argc) {
2418 rc = parse_action(argv[optind], &action);
2419 if (rc)
2420 return EXIT_FAILURE;
2421 optind++;
2422 } else {
2423 action = ACTION_RUN_DAEMON;
2424 }
2425
2426 if (is_prd_supported() < 0) {
2427 pr_log(LOG_ERR, "CTRL: PowerNV OPAL runtime diagnostic "
2428 "is not supported on this system");
2429 return -1;
2430 }
2431
2432 switch (action) {
2433 case ACTION_RUN_DAEMON:
2434 rc = run_prd_daemon(ctx);
2435 break;
2436 case ACTION_OCC_CONTROL:
2437 if (optind >= argc) {
2438 pr_log(LOG_ERR, "CTRL: occ command requires "
2439 "an argument");
2440 return EXIT_FAILURE;
2441 }
2442
2443 rc = send_occ_control(ctx, argc - optind, &argv[optind]);
2444 break;
2445 case ACTION_ATTR_OVERRIDE:
2446 if (optind >= argc) {
2447 pr_log(LOG_ERR, "CTRL: attribute override command "
2448 "requires an argument");
2449 return EXIT_FAILURE;
2450 }
2451
2452 rc = send_attr_override(ctx, argc - optind, &argv[optind]);
2453 break;
2454 case ACTION_HTMGT_PASSTHRU:
2455 if (optind >= argc) {
2456 pr_log(LOG_ERR, "CTRL: htmgt passthru requires at least "
2457 "one argument");
2458 return EXIT_FAILURE;
2459 }
2460
2461 rc = send_htmgt_passthru(ctx, argc - optind, &argv[optind]);
2462 break;
2463 case ACTION_RUN_COMMAND:
2464 if (optind >= argc) {
2465 pr_log(LOG_ERR, "CTRL: run command requires "
2466 "argument(s)");
2467 return EXIT_FAILURE;
2468 }
2469
2470 rc = send_run_command(ctx, argc - optind, &argv[optind]);
2471 break;
2472 default:
2473 break;
2474 }
2475
2476 return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
2477 }
2478