aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/rtas.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
-rw-r--r--arch/powerpc/kernel/rtas.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 4cf674d7d5ae..8cd5ed049b5d 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -993,32 +993,36 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,
993 (struct rtas_ext_event_log_v6 *)log->buffer; 993 (struct rtas_ext_event_log_v6 *)log->buffer;
994 struct pseries_errorlog *sect; 994 struct pseries_errorlog *sect;
995 unsigned char *p, *log_end; 995 unsigned char *p, *log_end;
996 uint32_t ext_log_length = rtas_error_extended_log_length(log);
997 uint8_t log_format = rtas_ext_event_log_format(ext_log);
998 uint32_t company_id = rtas_ext_event_company_id(ext_log);
996 999
997 /* Check that we understand the format */ 1000 /* Check that we understand the format */
998 if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) || 1001 if (ext_log_length < sizeof(struct rtas_ext_event_log_v6) ||
999 ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG || 1002 log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG ||
1000 ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM) 1003 company_id != RTAS_V6EXT_COMPANY_ID_IBM)
1001 return NULL; 1004 return NULL;
1002 1005
1003 log_end = log->buffer + log->extended_log_length; 1006 log_end = log->buffer + ext_log_length;
1004 p = ext_log->vendor_log; 1007 p = ext_log->vendor_log;
1005 1008
1006 while (p < log_end) { 1009 while (p < log_end) {
1007 sect = (struct pseries_errorlog *)p; 1010 sect = (struct pseries_errorlog *)p;
1008 if (sect->id == section_id) 1011 if (pseries_errorlog_id(sect) == section_id)
1009 return sect; 1012 return sect;
1010 p += sect->length; 1013 p += pseries_errorlog_length(sect);
1011 } 1014 }
1012 1015
1013 return NULL; 1016 return NULL;
1014} 1017}
1015 1018
1019/* We assume to be passed big endian arguments */
1016asmlinkage int ppc_rtas(struct rtas_args __user *uargs) 1020asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
1017{ 1021{
1018 struct rtas_args args; 1022 struct rtas_args args;
1019 unsigned long flags; 1023 unsigned long flags;
1020 char *buff_copy, *errbuf = NULL; 1024 char *buff_copy, *errbuf = NULL;
1021 int nargs; 1025 int nargs, nret, token;
1022 int rc; 1026 int rc;
1023 1027
1024 if (!capable(CAP_SYS_ADMIN)) 1028 if (!capable(CAP_SYS_ADMIN))
@@ -1027,10 +1031,13 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
1027 if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0) 1031 if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
1028 return -EFAULT; 1032 return -EFAULT;
1029 1033
1030 nargs = args.nargs; 1034 nargs = be32_to_cpu(args.nargs);
1035 nret = be32_to_cpu(args.nret);
1036 token = be32_to_cpu(args.token);
1037
1031 if (nargs > ARRAY_SIZE(args.args) 1038 if (nargs > ARRAY_SIZE(args.args)
1032 || args.nret > ARRAY_SIZE(args.args) 1039 || nret > ARRAY_SIZE(args.args)
1033 || nargs + args.nret > ARRAY_SIZE(args.args)) 1040 || nargs + nret > ARRAY_SIZE(args.args))
1034 return -EINVAL; 1041 return -EINVAL;
1035 1042
1036 /* Copy in args. */ 1043 /* Copy in args. */
@@ -1038,14 +1045,14 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
1038 nargs * sizeof(rtas_arg_t)) != 0) 1045 nargs * sizeof(rtas_arg_t)) != 0)
1039 return -EFAULT; 1046 return -EFAULT;
1040 1047
1041 if (args.token == RTAS_UNKNOWN_SERVICE) 1048 if (token == RTAS_UNKNOWN_SERVICE)
1042 return -EINVAL; 1049 return -EINVAL;
1043 1050
1044 args.rets = &args.args[nargs]; 1051 args.rets = &args.args[nargs];
1045 memset(args.rets, 0, args.nret * sizeof(rtas_arg_t)); 1052 memset(args.rets, 0, nret * sizeof(rtas_arg_t));
1046 1053
1047 /* Need to handle ibm,suspend_me call specially */ 1054 /* Need to handle ibm,suspend_me call specially */
1048 if (args.token == ibm_suspend_me_token) { 1055 if (token == ibm_suspend_me_token) {
1049 rc = rtas_ibm_suspend_me(&args); 1056 rc = rtas_ibm_suspend_me(&args);
1050 if (rc) 1057 if (rc)
1051 return rc; 1058 return rc;
@@ -1062,7 +1069,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
1062 1069
1063 /* A -1 return code indicates that the last command couldn't 1070 /* A -1 return code indicates that the last command couldn't
1064 be completed due to a hardware error. */ 1071 be completed due to a hardware error. */
1065 if (args.rets[0] == -1) 1072 if (be32_to_cpu(args.rets[0]) == -1)
1066 errbuf = __fetch_rtas_last_error(buff_copy); 1073 errbuf = __fetch_rtas_last_error(buff_copy);
1067 1074
1068 unlock_rtas(flags); 1075 unlock_rtas(flags);
@@ -1077,7 +1084,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
1077 /* Copy out args. */ 1084 /* Copy out args. */
1078 if (copy_to_user(uargs->args + nargs, 1085 if (copy_to_user(uargs->args + nargs,
1079 args.args + nargs, 1086 args.args + nargs,
1080 args.nret * sizeof(rtas_arg_t)) != 0) 1087 nret * sizeof(rtas_arg_t)) != 0)
1081 return -EFAULT; 1088 return -EFAULT;
1082 1089
1083 return 0; 1090 return 0;