From nobody Fri May 10 05:39:40 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1597413335; cv=none; d=zohomail.com; s=zohoarc; b=NT9hNbKC3kLuSOmp04rSaNH9beglGUjfuq2wJQpBmfiI2KWC3LBGhSMlsOnEGHkPRcuOUOZ0v/R/4rYA+c5I/DRys+Drao2svSiZcmySIcSVxDlCRD4Di1ob5v3IYId6KQ9p1JWKNuDG9Hf3HLH1KlGxTtBrSb/8yC3DPjHJdeo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597413335; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=vK1Kqnfa37R8fkDMpPv7Ynr6mECnHkM0SRyiPBNsaaM=; b=XCK6BCqYMeIBGsagiURdOYWmqXwBdf5ty2I775kEnnrGNPg/VJMp26j+VEAy7vfV9aXJgqU0iCZ8qiRbxVLkmtQIhRjWutXL5PGr3Gj8MxNq57esR8dpO4HF7CEXThhZU8oKXFF+k5SrAOsDpquQXAngWDSIG6yBetoADCDZHQM= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1597413335029907.5522362740732; Fri, 14 Aug 2020 06:55:35 -0700 (PDT) Received: from localhost ([::1]:45778 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k6ZYw-0004Ls-1U for importer@patchew.org; Fri, 14 Aug 2020 09:16:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46510) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k6ZXY-0003GA-AV for qemu-devel@nongnu.org; Fri, 14 Aug 2020 09:14:36 -0400 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:48798) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k6ZXW-0007tf-6S for qemu-devel@nongnu.org; Fri, 14 Aug 2020 09:14:36 -0400 Received: from sakura.ysato.name (ik1-413-38519.vs.sakura.ne.jp [153.127.30.23]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id B1084106E0D; Fri, 14 Aug 2020 22:14:28 +0900 (JST) Received: from yo-satoh-debian.localdomain (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by sakura.ysato.name (Postfix) with ESMTPSA id 164661C0BF9; Fri, 14 Aug 2020 22:14:28 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Subject: [PATCH] loader.c: Add support Motrola S-record format. Date: Fri, 14 Aug 2020 22:14:21 +0900 Message-Id: <20200814131421.28336-1-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: softfail client-ip=202.224.55.13; envelope-from=ysato@users.sourceforge.jp; helo=mail01.asahi-net.or.jp X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/14 09:14:29 X-ACL-Warn: Detected OS = ??? X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yoshinori Sato Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Since the Renesas development environment may use the S-Record format, it is convenient to handle this as well as the HEX format. Signed-off-by: Yoshinori Sato --- include/hw/loader.h | 14 +++ hw/core/loader.c | 212 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+) diff --git a/include/hw/loader.h b/include/hw/loader.h index a9eeea3952..b6590f53b1 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -55,6 +55,20 @@ int load_image_targphys_as(const char *filename, */ int load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace= *as); =20 +/** + * load_targphys_srec_as: + * @filename: Path to the .hex file + * @entry: Store the entry point given by the .hex file + * @as: The AddressSpace to load the .hex file to. The value of + * address_space_memory is used if nothing is supplied here. + * + * Load a fixed .srec file into memory. + * + * Returns the size of the loaded .hex file on success, -1 otherwise. + */ +int load_targphys_srec_as(const char *filename, + hwaddr *entry, AddressSpace *as); + /** load_image_targphys: * Same as load_image_targphys_as(), but doesn't allow the caller to speci= fy * an AddressSpace. diff --git a/hw/core/loader.c b/hw/core/loader.c index 8bbb1797a4..cfb328bd68 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -1618,3 +1618,215 @@ int load_targphys_hex_as(const char *filename, hwad= dr *entry, AddressSpace *as) g_free(hex_blob); return total_size; } + +typedef enum { + SREC_SOH, + SREC_TYPE, + SREC_LEN, + SREC_ADDR, + SREC_DATA, + SREC_SKIP, + SREC_SUM, +} srec_state; + +typedef struct { + srec_state state; + int nibble; + int total_size; + uint32_t address; + uint32_t topaddr; + uint32_t bufremain; + int length; + int addr_len; + int record_type; + uint8_t byte; + uint8_t data[DATA_FIELD_MAX_LEN]; + uint8_t *datap; + uint8_t *bufptr; + uint8_t sum; +} SrecLine; + +static bool parse_srec_line(SrecLine *line, char c) +{ + if (!g_ascii_isxdigit(c)) { + return false; + } + line->byte <<=3D 4; + line->byte |=3D g_ascii_xdigit_value(c); + line->nibble++; + if (line->nibble =3D=3D 2) { + line->nibble =3D 0; + line->length--; + line->sum +=3D line->byte; + switch (line->state) { + case SREC_SOH: + case SREC_TYPE: + /* first 2chars ignore parse */ + break; + case SREC_LEN: + line->sum =3D line->length =3D line->byte; + if (line->addr_len > 0) { + line->state =3D SREC_ADDR; + line->address =3D 0; + } else { + line->state =3D SREC_SKIP; + } + break; + case SREC_ADDR: + line->address <<=3D 8; + line->address |=3D line->byte; + if (--line->addr_len =3D=3D 0) { + if (line->length > 1) { + if (line->record_type !=3D 0) { + line->state =3D SREC_DATA; + } else { + line->state =3D SREC_SKIP; + } + line->datap =3D line->data; + } else { + line->state =3D SREC_SUM; + } + } + break; + case SREC_DATA: + *line->datap++ =3D line->byte; + /* fail through */ + case SREC_SKIP: + if (line->length =3D=3D 1) { + line->state =3D SREC_SUM; + } + break; + case SREC_SUM: + if ((line->sum & 0xff) !=3D 0xff) { + return false; + } + } + } + return true; +} + +#define SRECBUFSIZE 0x40000 + +/* return size or -1 if error */ +static int parse_srec_blob(const char *filename, hwaddr *addr, + uint8_t *hex_blob, size_t hex_blob_size, + AddressSpace *as) +{ + SrecLine line; + size_t len; + int total_len =3D 0; + uint8_t *end =3D hex_blob + hex_blob_size; + rom_transaction_begin(); + line.state =3D SREC_SOH; + line.bufptr =3D g_malloc(SRECBUFSIZE); + line.bufremain =3D SRECBUFSIZE; + line.topaddr =3D UINT32_MAX; + for (; hex_blob < end; ++hex_blob) { + switch (*hex_blob) { + case '\r': + case '\n': + if (line.state =3D=3D SREC_SUM) { + switch (line.record_type) { + case 1: + case 2: + case 3: + len =3D line.datap - line.data; + if (line.topaddr =3D=3D UINT32_MAX) { + line.topaddr =3D line.address; + } + /* If the buffer overflows, write to rom */ + if (line.bufremain < len || + line.address < line.topaddr || + (line.address - line.topaddr + len) > SRECBUFSIZE)= { + rom_add_blob_fixed_as(filename, line.bufptr, + SRECBUFSIZE - line.bufremain, + line.topaddr, as); + line.topaddr =3D line.address; + line.bufremain =3D SRECBUFSIZE; + } + memcpy(line.bufptr + (line.address - line.topaddr), + line.data, len); + line.bufremain -=3D len; + total_len +=3D len; + break; + case 7: + case 8: + case 9: + *addr =3D line.address; + break; + } + line.state =3D SREC_SOH; + } + break; + /* start of a new record. */ + case 'S': + if (line.state !=3D SREC_SOH) { + total_len =3D -1; + goto out; + } + line.state =3D SREC_TYPE; + break; + /* decoding lines */ + default: + if (line.state =3D=3D SREC_TYPE) { + if (g_ascii_isdigit(*hex_blob)) { + line.record_type =3D g_ascii_digit_value(*hex_blob); + switch (line.record_type) { + case 1: + case 2: + case 3: + line.addr_len =3D 1 + line.record_type; + break; + case 0: + case 5: + line.addr_len =3D 2; + break; + case 7: + case 8: + case 9: + line.addr_len =3D 11 - line.record_type; + break; + default: + line.addr_len =3D 0; + } + } + line.state =3D SREC_LEN; + line.nibble =3D 0; + } else { + if (!parse_srec_line(&line, *hex_blob)) { + total_len =3D -1; + goto out; + } + } + break; + } + } + /* Write unwritten binary to rom */ + if (line.bufremain < SRECBUFSIZE) { + rom_add_blob_fixed_as(filename, line.bufptr, + SRECBUFSIZE - line.bufremain, + line.topaddr, as); + } +out: + rom_transaction_end(total_len !=3D -1); + g_free(line.bufptr); + return total_len; +} + +/* return size or -1 if error */ +int load_targphys_srec_as(const char *filename, hwaddr *entry, AddressSpac= e *as) +{ + gsize hex_blob_size; + gchar *hex_blob; + int total_size =3D 0; + + if (!g_file_get_contents(filename, &hex_blob, &hex_blob_size, NULL)) { + return -1; + } + + total_size =3D parse_srec_blob(filename, entry, (uint8_t *)hex_blob, + hex_blob_size, as); + + g_free(hex_blob); + return total_size; +} --=20 2.20.1