diff options
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
-rw-r--r-- | arch/powerpc/kernel/rtas.c | 37 |
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 */ | ||
1016 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | 1020 | asmlinkage 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; |