03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#pragma ident "%Z%%M% %I% %E% SMI"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * download.c: support to the scadm download option (download service
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processor firmware)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <libintl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <stdio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <string.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <time.h> /* required by rsc.h */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include "adm.h"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include "librsc.h"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include "smq.h"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern smq_t ADM_bpMsgQueue;
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern smq_msg_t ADM_bpMsgBuffer[ADM_BP_BUFF_SIZE];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void usage();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelADM_Process_download(int argc, char *argv[])
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int BootRetry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t DownloadLocation;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static bp_msg_t Message;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static struct timespec Timeout;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *Filename;
03831d35f7499c87d51205817c93e9a8d42c4baestevel FILE *FilePtr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel timestruc_t Delay;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bootOpt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((argc != 3) && (argc != 4)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel usage();
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (argc == 4) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcasecmp(argv[2], "boot") != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel usage();
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel Filename = argv[3];
03831d35f7499c87d51205817c93e9a8d42c4baestevel DownloadLocation = BP_DAT2_FLASH_BOOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bootOpt = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else { /* no [boot] option */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel Filename = argv[2];
03831d35f7499c87d51205817c93e9a8d42c4baestevel DownloadLocation = BP_DAT2_FLASH_MAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bootOpt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((FilePtr = fopen(Filename, "r")) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext("scadm: file could not be opened"), Filename);
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Verify file is s-record */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ADM_Valid_srecord(FilePtr) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext("scadm: file not a valid s-record"), Filename);
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Don't call rscp_start() because SC may still be in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * boot monitor. The boot monitor will not respond to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rscp_start()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize Message Queue used between ADM_Callback and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ADM_Boot_recv(). ADM_Callback is called from seperate thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (smq_init(&ADM_bpMsgQueue, ADM_bpMsgBuffer,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ADM_BP_BUFF_SIZE) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext("scadm: ERROR, unable to setup message queue"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Initialize callback for Boot Monitor RX */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rscp_register_bpmsg_cb(ADM_Callback) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext("scadm: ERROR, callback init failed"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel BootRetry = ADM_BOOT_RETRY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (BootRetry > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize Message each time because this structure is reused
03831d35f7499c87d51205817c93e9a8d42c4baestevel * during receive. Since this operation is not time critical,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is not a concern
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel Message.cmd = BP_OBP_BOOTINIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Message.dat1 = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Message.dat2 = DownloadLocation;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rscp_send_bpmsg(&Message);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize Timeout each time just to be robust. Since this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * operation is not time critical, this is not a concern.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel Timeout.tv_nsec = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Timeout.tv_sec = ADM_BOOT_INIT_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* If we timeout, decrement BootRetry and try again */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ADM_Boot_recv(&Message, &Timeout) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* We got a timeout */
03831d35f7499c87d51205817c93e9a8d42c4baestevel BootRetry = BootRetry - 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* we got a message back, see what it is */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((Message.cmd != BP_RSC_BOOTACK) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (Message.dat1 != BP_DAT1_BOOTINIT_ACK)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ADM_Display_download_error(Message.cmd,
03831d35f7499c87d51205817c93e9a8d42c4baestevel Message.dat1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We got a valid acknowledge, break out of loop and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * start to download s-record
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* See if we ever got a response */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (BootRetry <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext("scadm: SC did not respond during boot "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "initialization"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Download s-record */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ADM_Send_file(FilePtr) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext("scadm: Error downloading file"), Filename);
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* wait a second for BootMonitor to catch up */
03831d35f7499c87d51205817c93e9a8d42c4baestevel Delay.tv_nsec = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Delay.tv_sec = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nanosleep(&Delay, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Send Reset boot protocol message to reboot SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel Message.cmd = BP_OBP_RESET;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Message.dat1 = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Message.dat2 = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rscp_send_bpmsg(&Message);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Cleanup */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rscp_unregister_bpmsg_cb(ADM_Callback);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) smq_destroy(&ADM_bpMsgQueue);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fclose(FilePtr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) printf("%s\n\n", gettext("Download completed successfully"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) printf("%s\n\n", gettext("Please wait for verification"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scadm cannot tell if the SC successfully verified the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * download or not, but instead attempts to send a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * status message (up to 60 times) and assumes proper
03831d35f7499c87d51205817c93e9a8d42c4baestevel * operation when sucessfully sent.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When the boot option is used, the SC may hang after
03831d35f7499c87d51205817c93e9a8d42c4baestevel * resetting itself (after it sucessfully downloads and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * verifies the boot file). To work around this, scadm
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will (1) do a hard reset and pause for 10 seconds
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (2) retry the sending of status messages.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel retry = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (retry == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* reset the SC before retrying */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rsc_nmi() != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext(
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scadm: Unable to reset SC hardware"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel exit(-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* delay while SC resets */
03831d35f7499c87d51205817c93e9a8d42c4baestevel Delay.tv_nsec = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel Delay.tv_sec = ADM_BOOT_LOAD_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) nanosleep(&Delay, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < 60; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rscp_msg_t msg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.type = DP_RSC_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.len = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msg.data = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) printf("%s", gettext("."));
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fflush(stdout);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = rscp_send(&msg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retry++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (bootOpt && (retry < 2));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) printf("\n%s\n\n", gettext("Complete"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) printf("\n%s\n\n", gettext("Error during verification"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelusage()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) fprintf(stderr, "\n%s\n\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel gettext("USAGE: scadm download [boot] <file>"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}