~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/skiboot/hw/fsp/fsp-codeupdate.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2013-2014 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
 * limitations under the License.
 
15
 */
 
16
 
 
17
 
 
18
#include <skiboot.h>
 
19
#include <fsp.h>
 
20
#include <fsp-sysparam.h>
 
21
#include <lock.h>
 
22
#include <device.h>
 
23
#include <ccan/endian/endian.h>
 
24
#include <errorlog.h>
 
25
#include <opal-api.h>
 
26
#include <timebase.h>
 
27
 
 
28
#include "fsp-codeupdate.h"
 
29
 
 
30
enum flash_state {
 
31
        FLASH_STATE_ABSENT,
 
32
        FLASH_STATE_INVALID, /* IPL side marker lid is invalid */
 
33
        FLASH_STATE_READING,
 
34
        FLASH_STATE_READ,
 
35
        FLASH_STATE_ABORT,
 
36
};
 
37
 
 
38
enum lid_fetch_side {
 
39
        FETCH_T_SIDE_ONLY,
 
40
        FETCH_P_SIDE_ONLY,
 
41
        FETCH_BOTH_SIDE,
 
42
};
 
43
 
 
44
static enum flash_state flash_state = FLASH_STATE_INVALID;
 
45
static enum lid_fetch_side lid_fetch_side = FETCH_BOTH_SIDE;
 
46
 
 
47
/* Image buffers */
 
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];
 
52
 
 
53
/* TCE buffer lock */
 
54
static struct lock flash_lock = LOCK_UNLOCKED;
 
55
 
 
56
/* FW VPD data */
 
57
static struct fw_image_vpd fw_vpd[2];
 
58
 
 
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;
 
64
 
 
65
/* If non-NULL, this gets called just before rebooting */
 
66
int (*fsp_flash_term_hook)(void);
 
67
 
 
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);
 
71
 
 
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);
 
75
 
 
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);
 
79
 
 
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);
 
83
 
 
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);
 
87
 
 
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);
 
91
 
 
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);
 
95
 
 
96
static inline void code_update_tce_map(uint32_t tce_offset,
 
97
                                       void *buffer, uint32_t size)
 
98
{
 
99
        uint32_t tlen = ALIGN_UP(size, TCE_PSIZE);
 
100
 
 
101
        fsp_tce_map(PSI_DMA_CODE_UPD + tce_offset, buffer, tlen);
 
102
}
 
103
 
 
104
static inline void code_update_tce_unmap(uint32_t size)
 
105
{
 
106
        fsp_tce_unmap(PSI_DMA_CODE_UPD, size);
 
107
}
 
108
 
 
109
static inline void set_def_fw_version(uint32_t side)
 
110
{
 
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);
 
113
}
 
114
 
 
115
/*
 
116
 * Get IPL side
 
117
 */
 
118
static void get_ipl_side(void)
 
119
{
 
120
        struct dt_node *iplp;
 
121
        const char *side = NULL;
 
122
 
 
123
        iplp = dt_find_by_path(dt_root, "ipl-params/ipl-params");
 
124
        if (iplp)
 
125
                side = dt_prop_get_def(iplp, "cec-ipl-side", NULL);
 
126
        prlog(PR_NOTICE, "CUPD: IPL SIDE = %s\n", side);
 
127
 
 
128
        if (!side || !strcmp(side, "temp"))
 
129
                ipl_side = FW_IPL_SIDE_TEMP;
 
130
        else
 
131
                ipl_side = FW_IPL_SIDE_PERM;
 
132
}
 
133
 
 
134
 
 
135
/*
 
136
 * Helper routines to retrieve code update related
 
137
 * system parameters from FSP.
 
138
 */
 
139
 
 
140
static void inc_in_flight_param(void)
 
141
{
 
142
        lock(&flash_lock);
 
143
        in_flight_params++;
 
144
        unlock(&flash_lock);
 
145
}
 
146
 
 
147
static void dec_in_flight_param(void)
 
148
{
 
149
        lock(&flash_lock);
 
150
        assert(in_flight_params > 0);
 
151
        in_flight_params--;
 
152
        unlock(&flash_lock);
 
153
}
 
154
 
 
155
static void got_code_update_policy(uint32_t param_id __unused, int err_len,
 
156
                                   void *data __unused)
 
157
{
 
158
        if (err_len != 4) {
 
159
                log_simple_error(&e_info(OPAL_RC_CU_INIT), "CUPD: Error "
 
160
                        "retrieving code update policy: %d\n", err_len);
 
161
        } else
 
162
                prlog(PR_NOTICE, "CUPD: Code update policy from FSP: %d\n",
 
163
                      update_policy);
 
164
 
 
165
        dec_in_flight_param();
 
166
}
 
167
 
 
168
static void get_code_update_policy(void)
 
169
{
 
170
        int rc;
 
171
 
 
172
        inc_in_flight_param();
 
173
        rc = fsp_get_sys_param(SYS_PARAM_FLASH_POLICY, &update_policy, 4,
 
174
                               got_code_update_policy, NULL);
 
175
        if (rc) {
 
176
                log_simple_error(&e_info(OPAL_RC_CU_INIT),
 
177
                        "CUPD: Error %d queueing param request\n", rc);
 
178
                dec_in_flight_param();
 
179
        }
 
180
}
 
181
 
 
182
static void got_platform_hmc_managed(uint32_t param_id __unused, int err_len,
 
183
                                     void *data __unused)
 
184
{
 
185
        if (err_len != 4) {
 
186
                log_simple_error(&e_info(OPAL_RC_CU_INIT), "CUPD: Error "
 
187
                        "retrieving hmc managed status: %d\n", err_len);
 
188
        } else
 
189
                prlog(PR_NOTICE, "CUPD: HMC managed status from FSP: %d\n",
 
190
                      hmc_managed);
 
191
 
 
192
        dec_in_flight_param();
 
193
}
 
194
 
 
195
static void get_platform_hmc_managed(void)
 
196
{
 
197
        int rc;
 
198
 
 
199
        inc_in_flight_param();
 
200
        rc = fsp_get_sys_param(SYS_PARAM_HMC_MANAGED, &hmc_managed, 4,
 
201
                               got_platform_hmc_managed, NULL);
 
202
        if (rc) {
 
203
                log_simple_error(&e_info(OPAL_RC_CU_INIT),
 
204
                        "CUPD: Error %d queueing param request\n", rc);
 
205
                dec_in_flight_param();
 
206
        }
 
207
}
 
208
 
 
209
static int64_t code_update_check_state(void)
 
210
{
 
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:
 
218
                return OPAL_BUSY;
 
219
        default:
 
220
                break;
 
221
        }
 
222
        return OPAL_SUCCESS;
 
223
}
 
224
 
 
225
/*
 
226
 * Get common marker LID additional data section
 
227
 */
 
228
static void *get_adf_sec_data(struct com_marker_adf_sec *adf_sec,
 
229
                              uint32_t name)
 
230
{
 
231
        struct com_marker_adf_header *adf_header;
 
232
        int i;
 
233
 
 
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)
 
237
                        return adf_header;
 
238
 
 
239
                adf_header = (void *)adf_header + be32_to_cpu(adf_header->size);
 
240
        }
 
241
        return NULL;
 
242
}
 
243
 
 
244
/*
 
245
 * Parse common marker LID to get FW version details
 
246
 *
 
247
 * Note:
 
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.
 
251
 */
 
252
static void parse_marker_lid(uint32_t side)
 
253
{
 
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;
 
258
 
 
259
        header = (void *)lid_data;
 
260
 
 
261
        /* Get MI details */
 
262
        mi_sec = (void *)header + be32_to_cpu(header->MI_offset);
 
263
        /*
 
264
         * If Marker LID is invalid, then FSP will return a Marker
 
265
         * LID with ASCII zeros for the entire MI keyword.
 
266
         */
 
267
        if (mi_sec->mi_keyword[0] == '0')
 
268
                return;
 
269
 
 
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);
 
274
 
 
275
        /* Get ML details */
 
276
        adf_sec = (void *)header + be32_to_cpu(mi_sec->adf_offset);
 
277
        adf_sp = get_adf_sec_data(adf_sec, ADF_NAME_SP);
 
278
        if (!adf_sp)
 
279
                return;
 
280
 
 
281
        strncpy(fw_vpd[side].ext_fw_id,
 
282
                (void *)adf_sp + be32_to_cpu(adf_sp->sp_name_offset),
 
283
                ML_KEYWORD_SIZE);
 
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);
 
287
}
 
288
 
 
289
static void validate_com_marker_lid(void)
 
290
{
 
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;
 
296
                return;
 
297
        }
 
298
 
 
299
        flash_state = FLASH_STATE_READ;
 
300
}
 
301
 
 
302
static void fetch_lid_data_complete(struct fsp_msg *msg)
 
303
{
 
304
        void *buffer;
 
305
        size_t length, chunk;
 
306
        uint32_t lid_id, offset;
 
307
        uint16_t id;
 
308
        uint8_t flags, status;
 
309
        int rc;
 
310
 
 
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];
 
317
 
 
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);
 
321
 
 
322
        fsp_freemsg(msg);
 
323
 
 
324
        switch (status) {
 
325
        case FSP_STATUS_SUCCESS: /* Read complete, parse VPD */
 
326
                parse_marker_lid(lid_id == P_COM_MARKER_LID_ID ? 0 : 1);
 
327
                break;
 
328
        case FSP_STATUS_MORE_DATA: /* More data left */
 
329
                offset += length;
 
330
                chunk = MARKER_LID_SIZE - offset;
 
331
                if (chunk > 0) {
 
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);
 
336
 
 
337
                        /* If queue msg fails, then continue with marker LID
 
338
                         * validation hoping that we have at least boot side
 
339
                         * information.
 
340
                         */
 
341
                        if (rc == OPAL_SUCCESS)
 
342
                                return;
 
343
                }
 
344
                break;
 
345
        default:        /* Fetch LID call failed */
 
346
                break;
 
347
        }
 
348
 
 
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);
 
356
 
 
357
                /* If queue msg fails, then continue with marker LID
 
358
                 * validation hoping that we have at least boot side
 
359
                 * information.
 
360
                 */
 
361
                if (rc == OPAL_SUCCESS)
 
362
                        return;
 
363
        }
 
364
 
 
365
        lock(&flash_lock);
 
366
 
 
367
        /* Validate marker LID data */
 
368
        validate_com_marker_lid();
 
369
        /* TCE unmap */
 
370
        code_update_tce_unmap(MARKER_LID_SIZE);
 
371
 
 
372
        unlock(&flash_lock);
 
373
}
 
374
 
 
375
static void fetch_com_marker_lid(void)
 
376
{
 
377
        size_t length = MARKER_LID_SIZE;
 
378
        uint32_t lid_id;
 
379
        int rc;
 
380
 
 
381
        /* Read in progress? */
 
382
        rc = code_update_check_state();
 
383
        if (rc == OPAL_HARDWARE || rc == OPAL_BUSY)
 
384
                return;
 
385
 
 
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);
 
392
        } else {
 
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);
 
396
        }
 
397
 
 
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);
 
402
        if (!rc)
 
403
                flash_state = FLASH_STATE_READING;
 
404
        else
 
405
                flash_state = FLASH_STATE_INVALID;
 
406
}
 
407
 
 
408
/*
 
409
 * Add MI and ML keyword details into DT
 
410
 */
 
411
#define FW_VER_SIZE     64
 
412
static void add_opal_firmware_version(void)
 
413
{
 
414
        struct dt_node *dt_fw;
 
415
        char buffer[FW_VER_SIZE];
 
416
        int offset;
 
417
 
 
418
        dt_fw = dt_find_by_path(dt_root, "ibm,opal/firmware");
 
419
        if (!dt_fw)
 
420
                return;
 
421
 
 
422
        /* MI version */
 
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);
 
429
        else
 
430
                snprintf(buffer + offset, FW_VER_SIZE - offset,
 
431
                         " %s", fw_vpd[FW_IPL_SIDE_PERM].mi_keyword);
 
432
 
 
433
        dt_add_property(dt_fw, "mi-version", buffer, strlen(buffer));
 
434
 
 
435
        /* ML version */
 
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);
 
442
        else
 
443
                snprintf(buffer + offset, FW_VER_SIZE - offset,
 
444
                         " %s", fw_vpd[FW_IPL_SIDE_PERM].ext_fw_id);
 
445
 
 
446
        dt_add_property(dt_fw, "ml-version", buffer, strlen(buffer));
 
447
}
 
448
 
 
449
/*
 
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.
 
453
 */
 
454
void fsp_code_update_wait_vpd(bool is_boot)
 
455
{
 
456
        int waited = 0;
 
457
 
 
458
        if (!fsp_present())
 
459
                return;
 
460
 
 
461
        prlog(PR_NOTICE, "CUPD: Waiting read marker LID"
 
462
              " and in flight parsm completion...\n");
 
463
 
 
464
        lock(&flash_lock);
 
465
        while(true) {
 
466
                if (!(flash_state == FLASH_STATE_READING || in_flight_params))
 
467
                        break;
 
468
                unlock(&flash_lock);
 
469
                time_wait_ms(5);
 
470
                waited+=5;
 
471
                lock(&flash_lock);
 
472
        }
 
473
        unlock(&flash_lock);
 
474
 
 
475
        if (waited)
 
476
                prlog(PR_DEBUG, "CUPD: fsp_code_update_wait_vpd %d\n", waited);
 
477
 
 
478
        if (is_boot)
 
479
                add_opal_firmware_version();
 
480
}
 
481
 
 
482
static int code_update_start(void)
 
483
{
 
484
        struct fsp_msg *msg;
 
485
        int rc;
 
486
        uint16_t comp = 0x00;   /* All components */
 
487
        uint8_t side = OPAL_COMMIT_TMP_SIDE;    /* Temporary side */
 
488
 
 
489
        msg = fsp_mkmsg(FSP_CMD_FLASH_START, 1, side << 16 | comp);
 
490
        if (!msg) {
 
491
                log_simple_error(&e_info(OPAL_RC_CU_MSG),
 
492
                        "CUPD: CMD_FLASH_START message allocation failed !\n");
 
493
                return OPAL_INTERNAL_ERROR;
 
494
        }
 
495
        if (fsp_sync_msg(msg, false)) {
 
496
                fsp_freemsg(msg);
 
497
                return OPAL_INTERNAL_ERROR;
 
498
        }
 
499
        rc = (msg->resp->word1 >> 8) & 0xff;
 
500
        fsp_freemsg(msg);
 
501
        return rc;
 
502
}
 
503
 
 
504
static int code_update_write_lid(uint32_t lid_id, uint32_t size)
 
505
{
 
506
        struct fsp_msg *msg;
 
507
        int rc, n_pairs = 1;
 
508
 
 
509
        msg = fsp_mkmsg(FSP_CMD_FLASH_WRITE, 5, lid_id,
 
510
                        n_pairs, 0, tce_start, size);
 
511
        if (!msg) {
 
512
                log_simple_error(&e_info(OPAL_RC_CU_MSG),
 
513
                        "CUPD: CMD_FLASH_WRITE message allocation failed !\n");
 
514
                return OPAL_INTERNAL_ERROR;
 
515
        }
 
516
        if (fsp_sync_msg(msg, false)) {
 
517
                fsp_freemsg(msg);
 
518
                return OPAL_INTERNAL_ERROR;
 
519
        }
 
520
        rc = (msg->resp->word1 >> 8) & 0xff;
 
521
        fsp_freemsg(msg);
 
522
        return rc;
 
523
}
 
524
 
 
525
static int code_update_del_lid(uint32_t lid_id)
 
526
{
 
527
        struct fsp_msg *msg;
 
528
        int rc;
 
529
 
 
530
        msg = fsp_mkmsg(FSP_CMD_FLASH_DEL, 1, lid_id);
 
531
        if (!msg) {
 
532
                log_simple_error(&e_info(OPAL_RC_CU_MSG),
 
533
                        "CUPD: CMD_FLASH_DEL message allocation failed !\n");
 
534
                return OPAL_INTERNAL_ERROR;
 
535
        }
 
536
        if (fsp_sync_msg(msg, false)) {
 
537
                fsp_freemsg(msg);
 
538
                return OPAL_INTERNAL_ERROR;
 
539
        }
 
540
        rc = (msg->resp->word1 >> 8) & 0xff;
 
541
        fsp_freemsg(msg);
 
542
        return rc;
 
543
}
 
544
 
 
545
static int code_update_complete(uint32_t cmd)
 
546
{
 
547
        struct fsp_msg *msg;
 
548
        int rc;
 
549
 
 
550
        msg = fsp_mkmsg(cmd, 0);
 
551
        if (!msg) {
 
552
                log_simple_error(&e_info(OPAL_RC_CU_MSG),
 
553
                        "CUPD: CUPD COMPLETE message allocation failed !\n");
 
554
                return OPAL_INTERNAL_ERROR;
 
555
        }
 
556
        if (fsp_sync_msg(msg, false)) {
 
557
                fsp_freemsg(msg);
 
558
                return OPAL_INTERNAL_ERROR;
 
559
        }
 
560
        rc = (msg->resp->word1 >> 8) & 0xff;
 
561
        fsp_freemsg(msg);
 
562
        return rc;
 
563
}
 
564
 
 
565
static int code_update_swap_side(void)
 
566
{
 
567
        struct fsp_msg *msg;
 
568
        int rc;
 
569
 
 
570
        msg = fsp_mkmsg(FSP_CMD_FLASH_SWAP, 0);
 
571
        if (!msg) {
 
572
                log_simple_error(&e_info(OPAL_RC_CU_MSG),
 
573
                        "CUPD: CMD_FLASH_SWAP message allocation failed !\n");
 
574
                return OPAL_INTERNAL_ERROR;
 
575
        }
 
576
 
 
577
        if (fsp_sync_msg(msg, false)) {
 
578
                fsp_freemsg(msg);
 
579
                return OPAL_INTERNAL_ERROR;
 
580
        }
 
581
        rc = (msg->resp->word1 >> 8) & 0xff;
 
582
        fsp_freemsg(msg);
 
583
        return rc;
 
584
}
 
585
 
 
586
static int code_update_set_ipl_side(void)
 
587
{
 
588
        struct fsp_msg *msg;
 
589
        uint8_t side = FW_IPL_SIDE_TEMP; /* Next IPL side */
 
590
        int rc;
 
591
 
 
592
        msg = fsp_mkmsg(FSP_CMD_SET_IPL_SIDE, 1, side << 16);
 
593
        if (!msg) {
 
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;
 
597
        }
 
598
        if (fsp_sync_msg(msg, false)) {
 
599
                fsp_freemsg(msg);
 
600
                log_simple_error(&e_info(OPAL_RC_CU_MSG),
 
601
                        "CUPD: Setting next IPL side failed!\n");
 
602
                return OPAL_INTERNAL_ERROR;
 
603
        }
 
604
        rc = (msg->resp->word1 >> 8) & 0xff;
 
605
        fsp_freemsg(msg);
 
606
        return rc;
 
607
}
 
608
 
 
609
static void code_update_commit_complete(struct fsp_msg *msg)
 
610
{
 
611
        int rc;
 
612
        uint8_t type;
 
613
 
 
614
        rc = (msg->resp->word1 >> 8) & 0xff;
 
615
        type = (msg->word1 >> 8) & 0xff;
 
616
        fsp_freemsg(msg);
 
617
        if (rc) {
 
618
                log_simple_error(&e_info(OPAL_RC_CU_COMMIT),
 
619
                        "CUPD: Code update commit failed, err 0x%x\n", rc);
 
620
                return;
 
621
        }
 
622
 
 
623
        /* Reset cached VPD data */
 
624
        lock(&flash_lock);
 
625
 
 
626
        /* Find commit type */
 
627
        if (type == 0x01) {
 
628
                lid_fetch_side = FETCH_P_SIDE_ONLY;
 
629
        } else if (type == 0x02)
 
630
                lid_fetch_side = FETCH_T_SIDE_ONLY;
 
631
        else
 
632
                lid_fetch_side = FETCH_BOTH_SIDE;
 
633
 
 
634
        fetch_com_marker_lid();
 
635
 
 
636
        unlock(&flash_lock);
 
637
}
 
638
 
 
639
static int code_update_commit(uint32_t cmd)
 
640
{
 
641
        struct fsp_msg *msg;
 
642
 
 
643
        msg = fsp_mkmsg(cmd, 0);
 
644
        if (!msg) {
 
645
                log_simple_error(&e_info(OPAL_RC_CU_MSG),
 
646
                        "CUPD: COMMIT message allocation failed !\n");
 
647
                return OPAL_INTERNAL_ERROR;
 
648
        }
 
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");
 
652
                fsp_freemsg(msg);
 
653
                return OPAL_INTERNAL_ERROR;
 
654
        }
 
655
        return OPAL_SUCCESS;
 
656
}
 
657
 
 
658
/*
 
659
 * Inband code update is allowed?
 
660
 */
 
661
static int64_t validate_inband_policy(void)
 
662
{
 
663
        /* Quirk:
 
664
         *  If the code update policy is out-of-band, but the system
 
665
         *  is not HMC-managed, then inband update is allowed.
 
666
         */
 
667
        if (hmc_managed != PLATFORM_HMC_MANAGED)
 
668
                return 0;
 
669
        if (update_policy == INBAND_UPDATE_ALLOWED)
 
670
                return 0;
 
671
 
 
672
        return -1;
 
673
}
 
674
 
 
675
/*
 
676
 * Validate magic Number
 
677
 */
 
678
static int64_t validate_magic_num(uint16_t magic)
 
679
{
 
680
        if (magic != IMAGE_MAGIC_NUMBER)
 
681
                return -1;
 
682
        return 0;
 
683
}
 
684
 
 
685
/*
 
686
 * Compare MI keyword to make sure candidate image
 
687
 * is valid for this platform.
 
688
 */
 
689
static int64_t validate_image_version(struct update_image_header *header,
 
690
                                      uint32_t *result)
 
691
{
 
692
        struct fw_image_vpd vpd;
 
693
        int t_valid = 0, p_valid = 0, cton_ver = -1, ptot_ver = -1;
 
694
 
 
695
        /* Valid flash image level? */
 
696
        if (strncmp(fw_vpd[0].mi_keyword, FW_VERSION_UNKNOWN,
 
697
                    sizeof(FW_VERSION_UNKNOWN)) != 0)
 
698
                p_valid = 1;
 
699
 
 
700
        if (strncmp(fw_vpd[1].mi_keyword, FW_VERSION_UNKNOWN,
 
701
                    sizeof(FW_VERSION_UNKNOWN)) != 0)
 
702
                t_valid = 1;
 
703
 
 
704
        /* Validate with IPL side image */
 
705
        vpd = fw_vpd[ipl_side];
 
706
 
 
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;
 
710
                return OPAL_SUCCESS;
 
711
        }
 
712
 
 
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;
 
716
                return OPAL_SUCCESS;
 
717
        }
 
718
 
 
719
        /* Get current to new version difference */
 
720
        cton_ver = strncmp(vpd.mi_keyword + 3, header->mi_keyword_data + 3, 6);
 
721
 
 
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);
 
726
 
 
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;
 
737
        } else {
 
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;
 
744
        }
 
745
        return OPAL_SUCCESS;
 
746
}
 
747
 
 
748
/*
 
749
 * Validate candidate image
 
750
 */
 
751
static int validate_candidate_image(uint64_t buffer,
 
752
                                    uint32_t size, uint32_t *result)
 
753
{
 
754
        struct update_image_header *header;
 
755
        int rc = OPAL_PARAMETER;
 
756
 
 
757
        if (size < VALIDATE_BUF_SIZE)
 
758
                goto out;
 
759
 
 
760
        rc = code_update_check_state();
 
761
        if (rc != OPAL_SUCCESS)
 
762
                goto out;
 
763
 
 
764
        if (validate_inband_policy() != 0) {
 
765
                *result = VALIDATE_FLASH_AUTH;
 
766
                rc = OPAL_SUCCESS;
 
767
                goto out;
 
768
        }
 
769
 
 
770
        memcpy(validate_buf, (void *)buffer, VALIDATE_BUF_SIZE);
 
771
        header = (struct update_image_header *)validate_buf;
 
772
 
 
773
        if (validate_magic_num(be32_to_cpu(header->magic)) != 0) {
 
774
                *result = VALIDATE_INVALID_IMG;
 
775
                rc = OPAL_SUCCESS;
 
776
                goto out;
 
777
        }
 
778
        rc = validate_image_version(header, result);
 
779
out:
 
780
        return rc;
 
781
}
 
782
 
 
783
static int validate_out_buf_mi_data(void *buffer, int offset, uint32_t result)
 
784
{
 
785
        struct update_image_header *header = (void *)validate_buf;
 
786
 
 
787
        /* Current T & P side MI data */
 
788
        offset += snprintf(buffer + offset, VALIDATE_BUF_SIZE - offset,
 
789
                           "MI %s %s\n",
 
790
                           fw_vpd[1].mi_keyword, fw_vpd[0].mi_keyword);
 
791
 
 
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);
 
800
        else
 
801
                offset += snprintf(buffer + offset,
 
802
                                   VALIDATE_BUF_SIZE - offset,
 
803
                                   " %s\n", fw_vpd[0].mi_keyword);
 
804
        return offset;
 
805
}
 
806
 
 
807
static int validate_out_buf_ml_data(void *buffer, int offset, uint32_t result)
 
808
{
 
809
        struct update_image_header *header = (void *)validate_buf;
 
810
        /* Candidate image ML data */
 
811
        char *ext_fw_id = (void *)header->data;
 
812
 
 
813
        /* Current T & P side ML data */
 
814
        offset += snprintf(buffer + offset, VALIDATE_BUF_SIZE - offset,
 
815
                           "ML %s %s\n",
 
816
                           fw_vpd[1].ext_fw_id, fw_vpd[0].ext_fw_id);
 
817
 
 
818
        /* New T & P side ML data */
 
819
        offset += snprintf(buffer + offset, VALIDATE_BUF_SIZE - offset,
 
820
                           "ML %s", ext_fw_id);
 
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);
 
826
        else
 
827
                offset += snprintf(buffer + offset,
 
828
                                   VALIDATE_BUF_SIZE - offset,
 
829
                                   " %s\n", fw_vpd[0].ext_fw_id);
 
830
 
 
831
        return offset;
 
832
}
 
833
 
 
834
/*
 
835
 * Copy LID data to TCE buffer
 
836
 */
 
837
static int get_lid_data(struct opal_sg_list *list,
 
838
                        int lid_size, int lid_offset)
 
839
{
 
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;
 
844
        bool last = false;
 
845
 
 
846
        /* Reset TCE start address */
 
847
        tce_start = 0;
 
848
 
 
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)
 
853
                        return -1;
 
854
 
 
855
                for (i = 0; i < num_entries; i++) {
 
856
                        entry = &sg->entry[i];
 
857
 
 
858
                        /*
 
859
                         * Continue until we get data block which
 
860
                         * contains LID data
 
861
                         */
 
862
                        if (lid_offset > be64_to_cpu(entry->length)) {
 
863
                                lid_offset -= be64_to_cpu(entry->length);
 
864
                                continue;
 
865
                        }
 
866
 
 
867
                        /*
 
868
                         * SG list entry size can be more than 4k.
 
869
                         * Map only required pages, instead of
 
870
                         * mapping entire entry.
 
871
                         */
 
872
                        map_act = be64_to_cpu(entry->length);
 
873
                        map_size = be64_to_cpu(entry->length);
 
874
 
 
875
                        /* First TCE mapping */
 
876
                        if (!tce_start) {
 
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;
 
882
                        }
 
883
 
 
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
 
889
                                 * is <= 4k.
 
890
                                 */
 
891
                                map_size = (map_size - map_act) + lid_size;
 
892
                                last = true;
 
893
                        }
 
894
 
 
895
                        /* Ajust remaining size to map */
 
896
                        lid_size -= map_act;
 
897
 
 
898
                        /* TCE mapping */
 
899
                        code_update_tce_map(buf_pos,
 
900
                                            (void*)(be64_to_cpu(entry->data)
 
901
                                                    + lid_offset),
 
902
                                            map_size);
 
903
                        buf_pos += map_size;
 
904
                        /* Reset LID offset count */
 
905
                        lid_offset = 0;
 
906
 
 
907
                        if (last)
 
908
                                return OPAL_SUCCESS;
 
909
                }
 
910
        } /* outer loop */
 
911
        return -1;
 
912
}
 
913
 
 
914
/*
 
915
 * If IPL side is T, then swap P & T sides to add
 
916
 * new fix to T side.
 
917
 */
 
918
static int validate_ipl_side(void)
 
919
{
 
920
        if (ipl_side == FW_IPL_SIDE_PERM)
 
921
                return 0;
 
922
        return code_update_swap_side();
 
923
}
 
924
 
 
925
static int64_t fsp_opal_validate_flash(uint64_t buffer,
 
926
                                       uint32_t *size, uint32_t *result)
 
927
{
 
928
        int64_t rc = 0;
 
929
        int offset;
 
930
 
 
931
        lock(&flash_lock);
 
932
 
 
933
        rc = validate_candidate_image(buffer, *size, result);
 
934
        /* Fill output buffer
 
935
         *
 
936
         * Format:
 
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>
 
941
         */
 
942
        if (!rc && (*result != VALIDATE_FLASH_AUTH &&
 
943
                   *result != VALIDATE_INVALID_IMG)) {
 
944
                /* Clear output buffer */
 
945
                memset((void *)buffer, 0, VALIDATE_BUF_SIZE);
 
946
 
 
947
                offset = validate_out_buf_mi_data((void *)buffer, 0, *result);
 
948
                offset += validate_out_buf_ml_data((void *)buffer,
 
949
                                                   offset, *result);
 
950
                *size = offset;
 
951
        }
 
952
 
 
953
        unlock(&flash_lock);
 
954
        return rc;
 
955
}
 
956
 
 
957
/* Commit/Reject T side image */
 
958
static int64_t fsp_opal_manage_flash(uint8_t op)
 
959
{
 
960
        uint32_t cmd;
 
961
        int rc;
 
962
 
 
963
        lock(&flash_lock);
 
964
        rc = code_update_check_state();
 
965
        unlock(&flash_lock);
 
966
 
 
967
        if (rc != OPAL_SUCCESS)
 
968
                return rc;
 
969
 
 
970
        if (op != OPAL_REJECT_TMP_SIDE && op != OPAL_COMMIT_TMP_SIDE)
 
971
                return OPAL_PARAMETER;
 
972
 
 
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;
 
976
 
 
977
        if (op == OPAL_COMMIT_TMP_SIDE)
 
978
                cmd = FSP_CMD_FLASH_NORMAL;
 
979
        else
 
980
                cmd = FSP_CMD_FLASH_REMOVE;
 
981
 
 
982
        return code_update_commit(cmd);
 
983
}
 
984
 
 
985
static int fsp_flash_firmware(void)
 
986
{
 
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;
 
991
        int rc, i;
 
992
 
 
993
        /* Make sure no outstanding LID read is in progress */
 
994
        rc = code_update_check_state();
 
995
        if (rc == OPAL_BUSY)
 
996
                fsp_code_update_wait_vpd(false);
 
997
 
 
998
        /* Get LID Index */
 
999
        list = image_data;
 
1000
        if (!list)
 
1001
                goto out;
 
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);
 
1005
 
 
1006
        /* FIXME:
 
1007
         *   At present we depend on FSP to validate CRC for
 
1008
         *   individual LIDs. Calculate and validate individual
 
1009
         *   LID CRC here.
 
1010
         */
 
1011
 
 
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");
 
1015
                goto out;
 
1016
        }
 
1017
 
 
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");
 
1022
                goto out;
 
1023
        }
 
1024
 
 
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");
 
1029
                goto out;
 
1030
        }
 
1031
 
 
1032
        /*
 
1033
         * Delete T side LIDs before writing.
 
1034
         *
 
1035
         * Note:
 
1036
         *   - Applicable for FWv >= 760.
 
1037
         *   - Current Code Update design is to ignore
 
1038
         *     any delete lid failure, and continue with
 
1039
         *     the update.
 
1040
         */
 
1041
        rc = code_update_del_lid(DEL_UPD_SIDE_LIDS);
 
1042
 
 
1043
        if (rc)
 
1044
                prlog(PR_TRACE, "CUPD: Failed to delete LIDs (%d). This is okay, continuing..", rc);
 
1045
 
 
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);
 
1052
                        goto abort_update;
 
1053
                }
 
1054
 
 
1055
                rc = get_lid_data(list, be32_to_cpu(idx_entry->size),
 
1056
                                  be32_to_cpu(idx_entry->offset));
 
1057
                if (rc) {
 
1058
                        log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
 
1059
                                "Failed to parse LID from firmware image."
 
1060
                                " (rc : %d).\n", rc);
 
1061
                        goto abort_update;
 
1062
                }
 
1063
 
 
1064
                rc = code_update_write_lid(be32_to_cpu(idx_entry->id),
 
1065
                                           be32_to_cpu(idx_entry->size));
 
1066
                if (rc) {
 
1067
                        log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
 
1068
                                "Failed to write LID to FSP. (rc : %d).\n", rc);
 
1069
                        goto abort_update;
 
1070
                }
 
1071
 
 
1072
                /* Unmap TCE */
 
1073
                code_update_tce_unmap(PSI_DMA_CODE_UPD_SIZE);
 
1074
 
 
1075
                /* Next LID index */
 
1076
                idx_entry = (void *)idx_entry + sizeof(struct lid_index_entry);
 
1077
        }
 
1078
 
 
1079
        /* Code update completed */
 
1080
        rc = code_update_complete(FSP_CMD_FLASH_COMPLETE);
 
1081
 
 
1082
        return rc;
 
1083
 
 
1084
abort_update:
 
1085
        rc = code_update_complete(FSP_CMD_FLASH_ABORT);
 
1086
        if (rc)
 
1087
                log_simple_error(&e_info(OPAL_RC_CU_FLASH), "CUPD: "
 
1088
                         "Code update abort command failed. (rc : %d).", rc);
 
1089
 
 
1090
out:
 
1091
        return -1;
 
1092
}
 
1093
 
 
1094
static int64_t validate_sglist(struct opal_sg_list *list)
 
1095
{
 
1096
        struct opal_sg_list *sg;
 
1097
        struct opal_sg_entry *prev_entry, *entry;
 
1098
        int length, num_entries, i;
 
1099
 
 
1100
        prev_entry = NULL;
 
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)
 
1105
                        return -1;
 
1106
 
 
1107
                for (i = 0; i < num_entries; i++) {
 
1108
                        entry = &sg->entry[i];
 
1109
 
 
1110
                        /* All entries must be aligned */
 
1111
                        if (((uint64_t)be64_to_cpu(entry->data)) & 0xfff)
 
1112
                                return OPAL_PARAMETER;
 
1113
 
 
1114
                        /* All non-terminal entries size must be aligned */
 
1115
                        if (prev_entry && (prev_entry->length & 0xfff))
 
1116
                                return OPAL_PARAMETER;
 
1117
 
 
1118
                        prev_entry = entry;
 
1119
                }
 
1120
        }
 
1121
        return OPAL_SUCCESS;
 
1122
}
 
1123
 
 
1124
static int64_t fsp_opal_update_flash(struct opal_sg_list *list)
 
1125
{
 
1126
        struct opal_sg_entry *entry;
 
1127
        int length, num_entries, result = 0, rc = OPAL_PARAMETER;
 
1128
 
 
1129
        /* Ensure that the sg list honors our alignment requirements */
 
1130
        rc = validate_sglist(list);
 
1131
        if (rc) {
 
1132
                log_simple_error(&e_info(OPAL_RC_CU_SG_LIST),
 
1133
                        "CUPD: sglist fails alignment requirements\n");
 
1134
                return rc;
 
1135
        }
 
1136
 
 
1137
        lock(&flash_lock);
 
1138
        if (!list) {    /* Cancel update request */
 
1139
                fsp_flash_term_hook = NULL;
 
1140
                image_data = NULL;
 
1141
                rc = OPAL_SUCCESS;
 
1142
                goto out;
 
1143
        }
 
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)
 
1147
                goto out;
 
1148
 
 
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)) {
 
1155
                image_data = list;
 
1156
                fsp_flash_term_hook = fsp_flash_firmware;
 
1157
                goto out;
 
1158
        }
 
1159
 
 
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;
 
1165
 
 
1166
out:
 
1167
        unlock(&flash_lock);
 
1168
        return rc;
 
1169
}
 
1170
 
 
1171
/*
 
1172
 * Code Update notifications
 
1173
 *
 
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.
 
1177
 */
 
1178
static bool code_update_notify(uint32_t cmd_sub_mod, struct fsp_msg *msg)
 
1179
{
 
1180
        int rc;
 
1181
        uint32_t cmd;
 
1182
 
 
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]);
 
1188
                break;
 
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);
 
1195
                break;
 
1196
        default:
 
1197
                log_simple_error(&e_info(OPAL_RC_CU_NOTIFY), "CUPD: Unknown "
 
1198
                        "notification [cmd = 0x%x]\n", cmd_sub_mod);
 
1199
                return false;
 
1200
        }
 
1201
 
 
1202
        rc = fsp_queue_msg(fsp_mkmsg(cmd, 0), fsp_freemsg);
 
1203
        if (rc)
 
1204
                log_simple_error(&e_info(OPAL_RC_CU_NOTIFY), "CUPD: Failed to "
 
1205
                        "queue code update notification response :%d\n", rc);
 
1206
 
 
1207
        return true;
 
1208
}
 
1209
 
 
1210
/*
 
1211
 * Handle FSP R/R event.
 
1212
 *
 
1213
 * Note:
 
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.
 
1217
 *
 
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.
 
1222
 */
 
1223
static bool fsp_code_update_rr(uint32_t cmd_sub_mod,
 
1224
                               struct fsp_msg *msg __unused)
 
1225
{
 
1226
        switch (cmd_sub_mod) {
 
1227
        case FSP_RESET_START:
 
1228
                lock(&flash_lock);
 
1229
 
 
1230
                if (code_update_check_state() == OPAL_BUSY)
 
1231
                        flash_state = FLASH_STATE_ABORT;
 
1232
 
 
1233
                unlock(&flash_lock);
 
1234
                return true;
 
1235
        case FSP_RELOAD_COMPLETE:
 
1236
                lock(&flash_lock);
 
1237
 
 
1238
                /* Lets try to parse marker LID again, if we failed
 
1239
                 * to parse marker LID last time.
 
1240
                 */
 
1241
                if (code_update_check_state() == OPAL_INTERNAL_ERROR)
 
1242
                        fetch_com_marker_lid();
 
1243
 
 
1244
                unlock(&flash_lock);
 
1245
                return true;
 
1246
        }
 
1247
        return false;
 
1248
}
 
1249
 
 
1250
static struct fsp_client fsp_cupd_client_rr = {
 
1251
                .message = fsp_code_update_rr,
 
1252
};
 
1253
 
 
1254
static struct fsp_client fsp_get_notify = {
 
1255
        .message = code_update_notify,
 
1256
};
 
1257
 
 
1258
void fsp_code_update_init(void)
 
1259
{
 
1260
        if (!fsp_present()) {
 
1261
                flash_state = FLASH_STATE_ABSENT;
 
1262
                return;
 
1263
        }
 
1264
 
 
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);
 
1269
 
 
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);
 
1274
 
 
1275
        /* Flash hook */
 
1276
        fsp_flash_term_hook = NULL;
 
1277
 
 
1278
        /* Fetch various code update related sys parameters */
 
1279
        get_ipl_side();
 
1280
        get_code_update_policy();
 
1281
        get_platform_hmc_managed();
 
1282
 
 
1283
        /* Fetch common marker LID */
 
1284
        lid_data = memalign(TCE_PSIZE, MARKER_LID_SIZE);
 
1285
        if (!lid_data) {
 
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;
 
1289
                return;
 
1290
        }
 
1291
        fetch_com_marker_lid();
 
1292
}