1
/* Copyright 2013-2014 IBM Corp.
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
7
* http://www.apache.org/licenses/LICENSE-2.0
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
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
20
#include <fsp-sysparam.h>
23
#include <ccan/endian/endian.h>
28
#include "fsp-codeupdate.h"
32
FLASH_STATE_INVALID, /* IPL side marker lid is invalid */
44
static enum flash_state flash_state = FLASH_STATE_INVALID;
45
static enum lid_fetch_side lid_fetch_side = FETCH_BOTH_SIDE;
48
static struct opal_sg_list *image_data;
49
static uint32_t tce_start;
50
static void *lid_data;
51
static char validate_buf[VALIDATE_BUF_SIZE];
54
static struct lock flash_lock = LOCK_UNLOCKED;
57
static struct fw_image_vpd fw_vpd[2];
59
/* Code update related sys parameters */
60
static uint32_t ipl_side;
61
static uint32_t hmc_managed;
62
static uint32_t update_policy;
63
static uint32_t in_flight_params;
65
/* If non-NULL, this gets called just before rebooting */
66
int (*fsp_flash_term_hook)(void);
68
DEFINE_LOG_ENTRY(OPAL_RC_CU_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_CODEUPDATE,
69
OPAL_PLATFORM_FIRMWARE,
70
OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, OPAL_NA);
72
DEFINE_LOG_ENTRY(OPAL_RC_CU_FLASH, OPAL_PLATFORM_ERR_EVT, OPAL_CODEUPDATE,
73
OPAL_PLATFORM_FIRMWARE,
74
OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, OPAL_NA);
76
DEFINE_LOG_ENTRY(OPAL_RC_CU_SG_LIST, OPAL_PLATFORM_ERR_EVT, OPAL_CODEUPDATE,
77
OPAL_PLATFORM_FIRMWARE,
78
OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, OPAL_NA);
80
DEFINE_LOG_ENTRY(OPAL_RC_CU_COMMIT, OPAL_PLATFORM_ERR_EVT, OPAL_CODEUPDATE,
81
OPAL_PLATFORM_FIRMWARE,
82
OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, OPAL_NA);
84
DEFINE_LOG_ENTRY(OPAL_RC_CU_MSG, OPAL_PLATFORM_ERR_EVT, OPAL_CODEUPDATE,
85
OPAL_PLATFORM_FIRMWARE,
86
OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, OPAL_NA);
88
DEFINE_LOG_ENTRY(OPAL_RC_CU_NOTIFY, OPAL_PLATFORM_ERR_EVT, OPAL_CODEUPDATE,
89
OPAL_PLATFORM_FIRMWARE,
90
OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, OPAL_NA);
92
DEFINE_LOG_ENTRY(OPAL_RC_CU_MARKER_LID, OPAL_PLATFORM_ERR_EVT, OPAL_CODEUPDATE,
93
OPAL_PLATFORM_FIRMWARE,
94
OPAL_PREDICTIVE_ERR_FAULT_RECTIFY_REBOOT, OPAL_NA);
96
static inline void code_update_tce_map(uint32_t tce_offset,
97
void *buffer, uint32_t size)
99
uint32_t tlen = ALIGN_UP(size, TCE_PSIZE);
101
fsp_tce_map(PSI_DMA_CODE_UPD + tce_offset, buffer, tlen);
104
static inline void code_update_tce_unmap(uint32_t size)
106
fsp_tce_unmap(PSI_DMA_CODE_UPD, size);
109
static inline void set_def_fw_version(uint32_t side)
111
strncpy(fw_vpd[side].mi_keyword, FW_VERSION_UNKNOWN, MI_KEYWORD_SIZE);
112
strncpy(fw_vpd[side].ext_fw_id, FW_VERSION_UNKNOWN, ML_KEYWORD_SIZE);
118
static void get_ipl_side(void)
120
struct dt_node *iplp;
121
const char *side = NULL;
123
iplp = dt_find_by_path(dt_root, "ipl-params/ipl-params");
125
side = dt_prop_get_def(iplp, "cec-ipl-side", NULL);
126
prlog(PR_NOTICE, "CUPD: IPL SIDE = %s\n", side);
128
if (!side || !strcmp(side, "temp"))
129
ipl_side = FW_IPL_SIDE_TEMP;
131
ipl_side = FW_IPL_SIDE_PERM;
136
* Helper routines to retrieve code update related
137
* system parameters from FSP.
140
static void inc_in_flight_param(void)
147
static void dec_in_flight_param(void)
150
assert(in_flight_params > 0);
155
static void got_code_update_policy(uint32_t param_id __unused, int err_len,
159
log_simple_error(&e_info(OPAL_RC_CU_INIT), "CUPD: Error "
160
"retrieving code update policy: %d\n", err_len);
162
prlog(PR_NOTICE, "CUPD: Code update policy from FSP: %d\n",
165
dec_in_flight_param();
168
static void get_code_update_policy(void)
172
inc_in_flight_param();
173
rc = fsp_get_sys_param(SYS_PARAM_FLASH_POLICY, &update_policy, 4,
174
got_code_update_policy, NULL);
176
log_simple_error(&e_info(OPAL_RC_CU_INIT),
177
"CUPD: Error %d queueing param request\n", rc);
178
dec_in_flight_param();
182
static void got_platform_hmc_managed(uint32_t param_id __unused, int err_len,
186
log_simple_error(&e_info(OPAL_RC_CU_INIT), "CUPD: Error "
187
"retrieving hmc managed status: %d\n", err_len);
189
prlog(PR_NOTICE, "CUPD: HMC managed status from FSP: %d\n",
192
dec_in_flight_param();
195
static void get_platform_hmc_managed(void)
199
inc_in_flight_param();
200
rc = fsp_get_sys_param(SYS_PARAM_HMC_MANAGED, &hmc_managed, 4,
201
got_platform_hmc_managed, NULL);
203
log_simple_error(&e_info(OPAL_RC_CU_INIT),
204
"CUPD: Error %d queueing param request\n", rc);
205
dec_in_flight_param();
209
static int64_t code_update_check_state(void)
211
switch(flash_state) {
212
case FLASH_STATE_ABSENT:
213
return OPAL_HARDWARE;
214
case FLASH_STATE_INVALID:
215
case FLASH_STATE_ABORT:
216
return OPAL_INTERNAL_ERROR;
217
case FLASH_STATE_READING:
226
* Get common marker LID additional data section
228
static void *get_adf_sec_data(struct com_marker_adf_sec *adf_sec,
231
struct com_marker_adf_header *adf_header;
234
adf_header = (void *)adf_sec->adf_data;
235
for (i = 0; i < be32_to_cpu(adf_sec->adf_cnt); i++) {
236
if (be32_to_cpu(adf_header->name) == name)
239
adf_header = (void *)adf_header + be32_to_cpu(adf_header->size);
245
* Parse common marker LID to get FW version details
248
* At present, we are parsing "Service Pack Nomenclature ADF"
249
* section only. If we are adding FW IP support, then we have
250
* to parse "Firmware IP Protection ADF" as well.
252
static void parse_marker_lid(uint32_t side)
254
struct com_marker_header *header;
255
struct com_marker_mi_section *mi_sec;
256
struct com_marker_adf_sec *adf_sec;
257
struct com_marker_adf_sp *adf_sp;
259
header = (void *)lid_data;
262
mi_sec = (void *)header + be32_to_cpu(header->MI_offset);
264
* If Marker LID is invalid, then FSP will return a Marker
265
* LID with ASCII zeros for the entire MI keyword.
267
if (mi_sec->mi_keyword[0] == '0')
270
strncpy(fw_vpd[side].mi_keyword, mi_sec->mi_keyword, MI_KEYWORD_SIZE);
271
fw_vpd[side].mi_keyword[MI_KEYWORD_SIZE - 1] = '\0';
272
prlog(PR_NOTICE, "CUPD: %s side MI Keyword = %s\n",
273
side == 0x00 ? "P" : "T", fw_vpd[side].mi_keyword);
276
adf_sec = (void *)header + be32_to_cpu(mi_sec->adf_offset);
277
adf_sp = get_adf_sec_data(adf_sec, ADF_NAME_SP);
281
strncpy(fw_vpd[side].ext_fw_id,
282
(void *)adf_sp + be32_to_cpu(adf_sp->sp_name_offset),
284
fw_vpd[side].ext_fw_id[ML_KEYWORD_SIZE - 1] = '\0';
285
prlog(PR_NOTICE, "CUPD: %s side ML Keyword = %s\n",
286
side == 0x00 ? "P" : "T", fw_vpd[side].ext_fw_id);
289
static void validate_com_marker_lid(void)
291
if (!strncmp(fw_vpd[ipl_side].mi_keyword, FW_VERSION_UNKNOWN,
292
sizeof(FW_VERSION_UNKNOWN))) {
293
log_simple_error(&e_info(OPAL_RC_CU_MARKER_LID),
294
"CUPD: IPL side Marker LID is not valid\n");
295
flash_state = FLASH_STATE_INVALID;
299
flash_state = FLASH_STATE_READ;
302
static void fetch_lid_data_complete(struct fsp_msg *msg)
305
size_t length, chunk;
306
uint32_t lid_id, offset;
308
uint8_t flags, status;
311
status = (msg->resp->word1 >> 8) & 0xff;
312
flags = (msg->data.words[0] >> 16) & 0xff;
313
id = msg->data.words[0] & 0xffff;
314
lid_id = msg->data.words[1];
315
offset = msg->resp->data.words[1];
316
length = msg->resp->data.words[2];
318
prlog(PR_NOTICE, "CUPD: Marker LID id : size : status = "
319
"0x%x : 0x%x : 0x%x\n",
320
msg->data.words[1], msg->resp->data.words[2], status);
325
case FSP_STATUS_SUCCESS: /* Read complete, parse VPD */
326
parse_marker_lid(lid_id == P_COM_MARKER_LID_ID ? 0 : 1);
328
case FSP_STATUS_MORE_DATA: /* More data left */
330
chunk = MARKER_LID_SIZE - offset;
332
buffer = (void *)PSI_DMA_CODE_UPD + offset;
333
rc = fsp_fetch_data_queue(flags, id, lid_id,
334
offset, buffer, &chunk,
335
fetch_lid_data_complete);
337
/* If queue msg fails, then continue with marker LID
338
* validation hoping that we have at least boot side
341
if (rc == OPAL_SUCCESS)
345
default: /* Fetch LID call failed */
349
/* If required, fetch T side marker LID */
350
if (lid_id == P_COM_MARKER_LID_ID &&
351
lid_fetch_side == FETCH_BOTH_SIDE) {
352
length = MARKER_LID_SIZE;
353
rc = fsp_fetch_data_queue(flags, id, T_COM_MARKER_LID_ID,
354
0, (void *)PSI_DMA_CODE_UPD,
355
&length, fetch_lid_data_complete);
357
/* If queue msg fails, then continue with marker LID
358
* validation hoping that we have at least boot side
361
if (rc == OPAL_SUCCESS)
367
/* Validate marker LID data */
368
validate_com_marker_lid();
370
code_update_tce_unmap(MARKER_LID_SIZE);
375
static void fetch_com_marker_lid(void)
377
size_t length = MARKER_LID_SIZE;
381
/* Read in progress? */
382
rc = code_update_check_state();
383
if (rc == OPAL_HARDWARE || rc == OPAL_BUSY)
386
if (lid_fetch_side == FETCH_T_SIDE_ONLY) {
387
lid_id = T_COM_MARKER_LID_ID;
388
set_def_fw_version(FW_IPL_SIDE_TEMP);
389
} else if (lid_fetch_side == FETCH_P_SIDE_ONLY) {
390
lid_id = P_COM_MARKER_LID_ID;
391
set_def_fw_version(FW_IPL_SIDE_PERM);
393
lid_id = P_COM_MARKER_LID_ID;
394
set_def_fw_version(FW_IPL_SIDE_PERM);
395
set_def_fw_version(FW_IPL_SIDE_TEMP);
398
code_update_tce_map(0, lid_data, length);
399
rc = fsp_fetch_data_queue(0x00, 0x05, lid_id, 0,
400
(void *)PSI_DMA_CODE_UPD, &length,
401
fetch_lid_data_complete);
403
flash_state = FLASH_STATE_READING;
405
flash_state = FLASH_STATE_INVALID;
409
* Add MI and ML keyword details into DT
411
#define FW_VER_SIZE 64
412
static void add_opal_firmware_version(void)
414
struct dt_node *dt_fw;
415
char buffer[FW_VER_SIZE];
418
dt_fw = dt_find_by_path(dt_root, "ibm,opal/firmware");
423
offset = snprintf(buffer, FW_VER_SIZE, "MI %s %s",
424
fw_vpd[FW_IPL_SIDE_TEMP].mi_keyword,
425
fw_vpd[FW_IPL_SIDE_PERM].mi_keyword);
426
if (ipl_side == FW_IPL_SIDE_TEMP)
427
snprintf(buffer + offset, FW_VER_SIZE - offset,
428
" %s", fw_vpd[FW_IPL_SIDE_TEMP].mi_keyword);
430
snprintf(buffer + offset, FW_VER_SIZE - offset,
431
" %s", fw_vpd[FW_IPL_SIDE_PERM].mi_keyword);
433
dt_add_property(dt_fw, "mi-version", buffer, strlen(buffer));
436
offset = snprintf(buffer, FW_VER_SIZE, "ML %s %s",
437
fw_vpd[FW_IPL_SIDE_TEMP].ext_fw_id,
438
fw_vpd[FW_IPL_SIDE_PERM].ext_fw_id);
439
if (ipl_side == FW_IPL_SIDE_TEMP)
440
snprintf(buffer + offset, FW_VER_SIZE - offset,
441
" %s", fw_vpd[FW_IPL_SIDE_TEMP].ext_fw_id);
443
snprintf(buffer + offset, FW_VER_SIZE - offset,
444
" %s", fw_vpd[FW_IPL_SIDE_PERM].ext_fw_id);
446
dt_add_property(dt_fw, "ml-version", buffer, strlen(buffer));
450
* This is called right before starting the payload (Linux) to
451
* ensure the common marker LID read and parsing has happened
452
* before we transfer control.
454
void fsp_code_update_wait_vpd(bool is_boot)
461
prlog(PR_NOTICE, "CUPD: Waiting read marker LID"
462
" and in flight parsm completion...\n");
466
if (!(flash_state == FLASH_STATE_READING || in_flight_params))
476
prlog(PR_DEBUG, "CUPD: fsp_code_update_wait_vpd %d\n", waited);
479
add_opal_firmware_version();
482
static int code_update_start(void)
486
uint16_t comp = 0x00; /* All components */
487
uint8_t side = OPAL_COMMIT_TMP_SIDE; /* Temporary side */
489
msg = fsp_mkmsg(FSP_CMD_FLASH_START, 1, side << 16 | comp);
491
log_simple_error(&e_info(OPAL_RC_CU_MSG),
492
"CUPD: CMD_FLASH_START message allocation failed !\n");
493
return OPAL_INTERNAL_ERROR;
495
if (fsp_sync_msg(msg, false)) {
497
return OPAL_INTERNAL_ERROR;
499
rc = (msg->resp->word1 >> 8) & 0xff;
504
static int code_update_write_lid(uint32_t lid_id, uint32_t size)
509
msg = fsp_mkmsg(FSP_CMD_FLASH_WRITE, 5, lid_id,
510
n_pairs, 0, tce_start, size);
512
log_simple_error(&e_info(OPAL_RC_CU_MSG),
513
"CUPD: CMD_FLASH_WRITE message allocation failed !\n");
514
return OPAL_INTERNAL_ERROR;
516
if (fsp_sync_msg(msg, false)) {
518
return OPAL_INTERNAL_ERROR;
520
rc = (msg->resp->word1 >> 8) & 0xff;
525
static int code_update_del_lid(uint32_t lid_id)
530
msg = fsp_mkmsg(FSP_CMD_FLASH_DEL, 1, lid_id);
532
log_simple_error(&e_info(OPAL_RC_CU_MSG),
533
"CUPD: CMD_FLASH_DEL message allocation failed !\n");
534
return OPAL_INTERNAL_ERROR;
536
if (fsp_sync_msg(msg, false)) {
538
return OPAL_INTERNAL_ERROR;
540
rc = (msg->resp->word1 >> 8) & 0xff;
545
static int code_update_complete(uint32_t cmd)
550
msg = fsp_mkmsg(cmd, 0);
552
log_simple_error(&e_info(OPAL_RC_CU_MSG),
553
"CUPD: CUPD COMPLETE message allocation failed !\n");
554
return OPAL_INTERNAL_ERROR;
556
if (fsp_sync_msg(msg, false)) {
558
return OPAL_INTERNAL_ERROR;
560
rc = (msg->resp->word1 >> 8) & 0xff;
565
static int code_update_swap_side(void)
570
msg = fsp_mkmsg(FSP_CMD_FLASH_SWAP, 0);
572
log_simple_error(&e_info(OPAL_RC_CU_MSG),
573
"CUPD: CMD_FLASH_SWAP message allocation failed !\n");
574
return OPAL_INTERNAL_ERROR;
577
if (fsp_sync_msg(msg, false)) {
579
return OPAL_INTERNAL_ERROR;
581
rc = (msg->resp->word1 >> 8) & 0xff;
586
static int code_update_set_ipl_side(void)
589
uint8_t side = FW_IPL_SIDE_TEMP; /* Next IPL side */
592
msg = fsp_mkmsg(FSP_CMD_SET_IPL_SIDE, 1, side << 16);
594
log_simple_error(&e_info(OPAL_RC_CU_MSG),
595
"CUPD: CMD_SET_IPL_SIDE message allocation failed!\n");
596
return OPAL_INTERNAL_ERROR;
598
if (fsp_sync_msg(msg, false)) {
600
log_simple_error(&e_info(OPAL_RC_CU_MSG),
601
"CUPD: Setting next IPL side failed!\n");
602
return OPAL_INTERNAL_ERROR;
604
rc = (msg->resp->word1 >> 8) & 0xff;
609
static void code_update_commit_complete(struct fsp_msg *msg)
614
rc = (msg->resp->word1 >> 8) & 0xff;
615
type = (msg->word1 >> 8) & 0xff;
618
log_simple_error(&e_info(OPAL_RC_CU_COMMIT),
619
"CUPD: Code update commit failed, err 0x%x\n", rc);
623
/* Reset cached VPD data */
626
/* Find commit type */
628
lid_fetch_side = FETCH_P_SIDE_ONLY;
629
} else if (type == 0x02)
630
lid_fetch_side = FETCH_T_SIDE_ONLY;
632
lid_fetch_side = FETCH_BOTH_SIDE;
634
fetch_com_marker_lid();
639
static int code_update_commit(uint32_t cmd)
643
msg = fsp_mkmsg(cmd, 0);
645
log_simple_error(&e_info(OPAL_RC_CU_MSG),
646
"CUPD: COMMIT message allocation failed !\n");
647
return OPAL_INTERNAL_ERROR;
649
if (fsp_queue_msg(msg, code_update_commit_complete)) {
650
log_simple_error(&e_info(OPAL_RC_CU_COMMIT),
651
"CUPD: Failed to queue code update commit message\n");
653
return OPAL_INTERNAL_ERROR;
659
* Inband code update is allowed?
661
static int64_t validate_inband_policy(void)
664
* If the code update policy is out-of-band, but the system
665
* is not HMC-managed, then inband update is allowed.
667
if (hmc_managed != PLATFORM_HMC_MANAGED)
669
if (update_policy == INBAND_UPDATE_ALLOWED)
676
* Validate magic Number
678
static int64_t validate_magic_num(uint16_t magic)
680
if (magic != IMAGE_MAGIC_NUMBER)
686
* Compare MI keyword to make sure candidate image
687
* is valid for this platform.
689
static int64_t validate_image_version(struct update_image_header *header,
692
struct fw_image_vpd vpd;
693
int t_valid = 0, p_valid = 0, cton_ver = -1, ptot_ver = -1;
695
/* Valid flash image level? */
696
if (strncmp(fw_vpd[0].mi_keyword, FW_VERSION_UNKNOWN,
697
sizeof(FW_VERSION_UNKNOWN)) != 0)
700
if (strncmp(fw_vpd[1].mi_keyword, FW_VERSION_UNKNOWN,
701
sizeof(FW_VERSION_UNKNOWN)) != 0)
704
/* Validate with IPL side image */
705
vpd = fw_vpd[ipl_side];
707
/* Validate platform identifier (first two char of MI keyword) */
708
if (strncmp(vpd.mi_keyword, header->mi_keyword_data, 2) != 0) {
709
*result = VALIDATE_INVALID_IMG;
713
/* Don't flash different FW series (like P7 image on P8) */
714
if (vpd.mi_keyword[2] != header->mi_keyword_data[2]) {
715
*result = VALIDATE_INVALID_IMG;
719
/* Get current to new version difference */
720
cton_ver = strncmp(vpd.mi_keyword + 3, header->mi_keyword_data + 3, 6);
722
/* Get P to T version difference */
723
if (t_valid && p_valid)
724
ptot_ver = strncmp(fw_vpd[0].mi_keyword + 3,
725
fw_vpd[1].mi_keyword + 3, 6);
727
/* Update validation result */
728
if (ipl_side == FW_IPL_SIDE_TEMP) {
729
if (!ptot_ver && cton_ver > 0) /* downgrade T side */
730
*result = VALIDATE_TMP_UPDATE_DL;
731
else if (!ptot_ver && cton_ver <= 0) /* upgrade T side */
732
*result = VALIDATE_TMP_UPDATE;
733
else if (cton_ver > 0) /* Implied commit & downgrade T side */
734
*result = VALIDATE_TMP_COMMIT_DL;
735
else /* Implied commit & upgrade T side */
736
*result = VALIDATE_TMP_COMMIT;
738
if (!t_valid) /* Current unknown */
739
*result = VALIDATE_CUR_UNKNOWN;
740
else if (cton_ver > 0) /* downgrade FW version */
741
*result = VALIDATE_TMP_UPDATE_DL;
742
else /* upgrade FW version */
743
*result = VALIDATE_TMP_UPDATE;
749
* Validate candidate image
751
static int validate_candidate_image(uint64_t buffer,
752
uint32_t size, uint32_t *result)
754
struct update_image_header *header;
755
int rc = OPAL_PARAMETER;
757
if (size < VALIDATE_BUF_SIZE)
760
rc = code_update_check_state();
761
if (rc != OPAL_SUCCESS)
764
if (validate_inband_policy() != 0) {
765
*result = VALIDATE_FLASH_AUTH;
770
memcpy(validate_buf, (void *)buffer, VALIDATE_BUF_SIZE);
771
header = (struct update_image_header *)validate_buf;
773
if (validate_magic_num(be32_to_cpu(header->magic)) != 0) {
774
*result = VALIDATE_INVALID_IMG;
778
rc = validate_image_version(header, result);
783
static int validate_out_buf_mi_data(void *buffer, int offset, uint32_t result)
785
struct update_image_header *header = (void *)validate_buf;
787
/* Current T & P side MI data */
788
offset += snprintf(buffer + offset, VALIDATE_BUF_SIZE - offset,
790
fw_vpd[1].mi_keyword, fw_vpd[0].mi_keyword);
792
/* New T & P side MI data */
793
offset += snprintf(buffer + offset, VALIDATE_BUF_SIZE - offset,
794
"MI %s", header->mi_keyword_data);
795
if (result == VALIDATE_TMP_COMMIT_DL ||
796
result == VALIDATE_TMP_COMMIT)
797
offset += snprintf(buffer + offset,
798
VALIDATE_BUF_SIZE - offset,
799
" %s\n", fw_vpd[1].mi_keyword);
801
offset += snprintf(buffer + offset,
802
VALIDATE_BUF_SIZE - offset,
803
" %s\n", fw_vpd[0].mi_keyword);
807
static int validate_out_buf_ml_data(void *buffer, int offset, uint32_t result)
809
struct update_image_header *header = (void *)validate_buf;
810
/* Candidate image ML data */
811
char *ext_fw_id = (void *)header->data;
813
/* Current T & P side ML data */
814
offset += snprintf(buffer + offset, VALIDATE_BUF_SIZE - offset,
816
fw_vpd[1].ext_fw_id, fw_vpd[0].ext_fw_id);
818
/* New T & P side ML data */
819
offset += snprintf(buffer + offset, VALIDATE_BUF_SIZE - offset,
821
if (result == VALIDATE_TMP_COMMIT_DL ||
822
result == VALIDATE_TMP_COMMIT)
823
offset += snprintf(buffer + offset,
824
VALIDATE_BUF_SIZE - offset,
825
" %s\n", fw_vpd[1].ext_fw_id);
827
offset += snprintf(buffer + offset,
828
VALIDATE_BUF_SIZE - offset,
829
" %s\n", fw_vpd[0].ext_fw_id);
835
* Copy LID data to TCE buffer
837
static int get_lid_data(struct opal_sg_list *list,
838
int lid_size, int lid_offset)
840
struct opal_sg_list *sg;
841
struct opal_sg_entry *entry;
842
int length, num_entries, i, buf_pos = 0;
843
int map_act, map_size;
846
/* Reset TCE start address */
849
for (sg = list; sg; sg = (struct opal_sg_list*)be64_to_cpu(sg->next)) {
850
length = (be64_to_cpu(sg->length) & ~(SG_LIST_VERSION << 56)) - 16;
851
num_entries = length / sizeof(struct opal_sg_entry);
852
if (num_entries <= 0)
855
for (i = 0; i < num_entries; i++) {
856
entry = &sg->entry[i];
859
* Continue until we get data block which
862
if (lid_offset > be64_to_cpu(entry->length)) {
863
lid_offset -= be64_to_cpu(entry->length);
868
* SG list entry size can be more than 4k.
869
* Map only required pages, instead of
870
* mapping entire entry.
872
map_act = be64_to_cpu(entry->length);
873
map_size = be64_to_cpu(entry->length);
875
/* First TCE mapping */
877
tce_start = PSI_DMA_CODE_UPD +
878
(lid_offset & 0xfff);
879
map_act = be64_to_cpu(entry->length) - lid_offset;
880
lid_offset &= ~0xfff;
881
map_size = be64_to_cpu(entry->length) - lid_offset;
884
/* Check pending LID size to map */
885
if (lid_size <= map_act) {
886
/* (map_size - map_act) gives page
887
* start to tce offset difference.
888
* This is required when LID size
891
map_size = (map_size - map_act) + lid_size;
895
/* Ajust remaining size to map */
899
code_update_tce_map(buf_pos,
900
(void*)(be64_to_cpu(entry->data)
904
/* Reset LID offset count */
915
* If IPL side is T, then swap P & T sides to add
918
static int validate_ipl_side(void)
920
if (ipl_side == FW_IPL_SIDE_PERM)
922
return code_update_swap_side();
925
static int64_t fsp_opal_validate_flash(uint64_t buffer,
926
uint32_t *size, uint32_t *result)
933
rc = validate_candidate_image(buffer, *size, result);
934
/* Fill output buffer
937
* MI<sp>current-T-image<sp>current-P-image<0x0A>
938
* MI<sp>new-T-image<sp>new-P-image<0x0A>
939
* ML<sp>current-T-image<sp>current-P-image<0x0A>
940
* ML<sp>new-T-image<sp>new-P-image<0x0A>
942
if (!rc && (*result != VALIDATE_FLASH_AUTH &&
943
*result != VALIDATE_INVALID_IMG)) {
944
/* Clear output buffer */
945
memset((void *)buffer, 0, VALIDATE_BUF_SIZE);
947
offset = validate_out_buf_mi_data((void *)buffer, 0, *result);
948
offset += validate_out_buf_ml_data((void *)buffer,
957
/* Commit/Reject T side image */
958
static int64_t fsp_opal_manage_flash(uint8_t op)
964
rc = code_update_check_state();
967
if (rc != OPAL_SUCCESS)
970
if (op != OPAL_REJECT_TMP_SIDE && op != OPAL_COMMIT_TMP_SIDE)
971
return OPAL_PARAMETER;
973
if ((op == OPAL_COMMIT_TMP_SIDE && ipl_side == FW_IPL_SIDE_PERM) ||
974
(op == OPAL_REJECT_TMP_SIDE && ipl_side == FW_IPL_SIDE_TEMP))
975
return OPAL_ACTIVE_SIDE_ERR;
977
if (op == OPAL_COMMIT_TMP_SIDE)
978
cmd = FSP_CMD_FLASH_NORMAL;
980
cmd = FSP_CMD_FLASH_REMOVE;
982
return code_update_commit(cmd);
985
static int fsp_flash_firmware(void)
987
struct update_image_header *header;
988
struct lid_index_entry *idx_entry;
989
struct opal_sg_list *list;
990
struct opal_sg_entry *entry;
993
/* Make sure no outstanding LID read is in progress */
994
rc = code_update_check_state();
996
fsp_code_update_wait_vpd(false);
1002
entry = &list->entry[0];
1003
header = (struct update_image_header *)be64_to_cpu(entry->data);
1004
idx_entry = (void *)header + be16_to_cpu(header->lid_index_offset);
1007
* At present we depend on FSP to validate CRC for
1008
* individual LIDs. Calculate and validate individual
1012
if (validate_ipl_side() != 0) {
1013
log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
1014
"Rename (Swap T and P) failed!\n");
1018
/* Set next IPL side */
1019
if (code_update_set_ipl_side() != 0) {
1020
log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
1021
"Setting next IPL side failed!\n");
1025
/* Start code update process */
1026
if (code_update_start() != 0) {
1027
log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
1028
"Code update start failed!\n");
1033
* Delete T side LIDs before writing.
1036
* - Applicable for FWv >= 760.
1037
* - Current Code Update design is to ignore
1038
* any delete lid failure, and continue with
1041
rc = code_update_del_lid(DEL_UPD_SIDE_LIDS);
1044
prlog(PR_TRACE, "CUPD: Failed to delete LIDs (%d). This is okay, continuing..", rc);
1046
for (i = 0; i < be16_to_cpu(header->number_lids); i++) {
1047
if (be32_to_cpu(idx_entry->size) > LID_MAX_SIZE) {
1048
log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: LID"
1049
" (0x%x) size 0x%x is > max LID size (0x%x).\n",
1050
be32_to_cpu(idx_entry->id),
1051
be32_to_cpu(idx_entry->size), LID_MAX_SIZE);
1055
rc = get_lid_data(list, be32_to_cpu(idx_entry->size),
1056
be32_to_cpu(idx_entry->offset));
1058
log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
1059
"Failed to parse LID from firmware image."
1060
" (rc : %d).\n", rc);
1064
rc = code_update_write_lid(be32_to_cpu(idx_entry->id),
1065
be32_to_cpu(idx_entry->size));
1067
log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
1068
"Failed to write LID to FSP. (rc : %d).\n", rc);
1073
code_update_tce_unmap(PSI_DMA_CODE_UPD_SIZE);
1075
/* Next LID index */
1076
idx_entry = (void *)idx_entry + sizeof(struct lid_index_entry);
1079
/* Code update completed */
1080
rc = code_update_complete(FSP_CMD_FLASH_COMPLETE);
1085
rc = code_update_complete(FSP_CMD_FLASH_ABORT);
1087
log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
1088
"Code update abort command failed. (rc : %d).", rc);
1094
static int64_t validate_sglist(struct opal_sg_list *list)
1096
struct opal_sg_list *sg;
1097
struct opal_sg_entry *prev_entry, *entry;
1098
int length, num_entries, i;
1101
for (sg = list; sg; sg = (struct opal_sg_list*)be64_to_cpu(sg->next)) {
1102
length = (be64_to_cpu(sg->length) & ~(SG_LIST_VERSION << 56)) - 16;
1103
num_entries = length / sizeof(struct opal_sg_entry);
1104
if (num_entries <= 0)
1107
for (i = 0; i < num_entries; i++) {
1108
entry = &sg->entry[i];
1110
/* All entries must be aligned */
1111
if (((uint64_t)be64_to_cpu(entry->data)) & 0xfff)
1112
return OPAL_PARAMETER;
1114
/* All non-terminal entries size must be aligned */
1115
if (prev_entry && (prev_entry->length & 0xfff))
1116
return OPAL_PARAMETER;
1121
return OPAL_SUCCESS;
1124
static int64_t fsp_opal_update_flash(struct opal_sg_list *list)
1126
struct opal_sg_entry *entry;
1127
int length, num_entries, result = 0, rc = OPAL_PARAMETER;
1129
/* Ensure that the sg list honors our alignment requirements */
1130
rc = validate_sglist(list);
1132
log_simple_error(&e_info(OPAL_RC_CU_SG_LIST),
1133
"CUPD: sglist fails alignment requirements\n");
1138
if (!list) { /* Cancel update request */
1139
fsp_flash_term_hook = NULL;
1144
length = (be64_to_cpu(list->length) & ~(SG_LIST_VERSION << 56)) - 16;
1145
num_entries = length / sizeof(struct opal_sg_entry);
1146
if (num_entries <= 0)
1149
/* Validate image header */
1150
entry = &list->entry[0];
1151
rc = validate_candidate_image((uint64_t)be64_to_cpu(entry->data),
1152
VALIDATE_BUF_SIZE, &result);
1153
if (!rc && (result != VALIDATE_FLASH_AUTH &&
1154
result != VALIDATE_INVALID_IMG)) {
1156
fsp_flash_term_hook = fsp_flash_firmware;
1160
/* Adjust return code */
1161
if (result == VALIDATE_FLASH_AUTH)
1162
rc = OPAL_FLASH_NO_AUTH;
1163
else if (result == VALIDATE_INVALID_IMG)
1164
rc = OPAL_INVALID_IMAGE;
1167
unlock(&flash_lock);
1172
* Code Update notifications
1174
* Note: At present we just ACK these notifications.
1175
* Reset cached VPD data if we are going to support
1176
* concurrent image maint in future.
1178
static bool code_update_notify(uint32_t cmd_sub_mod, struct fsp_msg *msg)
1183
switch(cmd_sub_mod) {
1184
case FSP_CMD_FLASH_CACHE:
1185
cmd = FSP_CMD_FLASH_CACHE_RSP;
1186
prlog(PR_NOTICE, "CUPD: Update LID cache event [data = 0x%x]\n",
1187
msg->data.words[0]);
1189
case FSP_CMD_FLASH_OUTC:
1190
case FSP_CMD_FLASH_OUTR:
1191
case FSP_CMD_FLASH_OUTS:
1192
cmd = FSP_CMD_FLASH_OUT_RSP;
1193
prlog(PR_NOTICE, "CUPD: Out of band commit notify "
1194
"[Type = 0x%x]\n", (msg->word1 >> 8) & 0xff);
1197
log_simple_error(&e_info(OPAL_RC_CU_NOTIFY), "CUPD: Unknown "
1198
"notification [cmd = 0x%x]\n", cmd_sub_mod);
1202
rc = fsp_queue_msg(fsp_mkmsg(cmd, 0), fsp_freemsg);
1204
log_simple_error(&e_info(OPAL_RC_CU_NOTIFY), "CUPD: Failed to "
1205
"queue code update notification response :%d\n", rc);
1211
* Handle FSP R/R event.
1214
* If FSP R/R happens during code update, then entire system reboots
1215
* and comes up with P side image (and T side image will be invalid).
1216
* Hence we don't need to handle R/R during code update.
1218
* Also if FSP R/R happens in init path (while retrieving in_flight_params)
1219
* then system fails to continue booting (because we have not yet loaded
1220
* all required data/LID from FSP). Hence we don't need to handle R/R
1221
* for system params.
1223
static bool fsp_code_update_rr(uint32_t cmd_sub_mod,
1224
struct fsp_msg *msg __unused)
1226
switch (cmd_sub_mod) {
1227
case FSP_RESET_START:
1230
if (code_update_check_state() == OPAL_BUSY)
1231
flash_state = FLASH_STATE_ABORT;
1233
unlock(&flash_lock);
1235
case FSP_RELOAD_COMPLETE:
1238
/* Lets try to parse marker LID again, if we failed
1239
* to parse marker LID last time.
1241
if (code_update_check_state() == OPAL_INTERNAL_ERROR)
1242
fetch_com_marker_lid();
1244
unlock(&flash_lock);
1250
static struct fsp_client fsp_cupd_client_rr = {
1251
.message = fsp_code_update_rr,
1254
static struct fsp_client fsp_get_notify = {
1255
.message = code_update_notify,
1258
void fsp_code_update_init(void)
1260
if (!fsp_present()) {
1261
flash_state = FLASH_STATE_ABSENT;
1265
/* OPAL interface */
1266
opal_register(OPAL_FLASH_VALIDATE, fsp_opal_validate_flash, 3);
1267
opal_register(OPAL_FLASH_MANAGE, fsp_opal_manage_flash, 1);
1268
opal_register(OPAL_FLASH_UPDATE, fsp_opal_update_flash, 1);
1270
/* register Code Update Class D3 */
1271
fsp_register_client(&fsp_get_notify, FSP_MCLASS_CODE_UPDATE);
1272
/* Register for Class AA (FSP R/R) */
1273
fsp_register_client(&fsp_cupd_client_rr, FSP_MCLASS_RR_EVENT);
1276
fsp_flash_term_hook = NULL;
1278
/* Fetch various code update related sys parameters */
1280
get_code_update_policy();
1281
get_platform_hmc_managed();
1283
/* Fetch common marker LID */
1284
lid_data = memalign(TCE_PSIZE, MARKER_LID_SIZE);
1286
log_simple_error(&e_info(OPAL_RC_CU_INIT),
1287
"CUPD: Failed to allocate memory for marker LID\n");
1288
flash_state = FLASH_STATE_ABSENT;
1291
fetch_com_marker_lid();