From nobody Sat Sep 26 20:50:59 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1788263858; cv=none; d=zohomail.com; s=zohoarc; b=Zx1PitPgu+tFNvlSpvN2njRImmXXSgC2sGlQUi9e4f3I6sMn/3rCHEeRq+WOvNyVooQRWMRgWzEQ24widS3A3TodQjQTbUyXZyFbYo82m6c37UOrnNxpSwxRueB4+QcCHfR750ZvsvaA59j31TrQ1MPJNTwAz+aFCWMa6K2k6tE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788263858; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=7kwdjrF+q/XbeywvWNcw3Wj5lkryI6dPWIi6HjkeNoE=; b=WByo/YaZatPGvUk2oUm0KOJ4Ud+oNyG80q3YGuekjoghgB3iF19mgmtqPx8gKZD3/GieZPtkWMy7y1GX1M9gwzKX0ZpWPbGmde1D8IN24YwkIpEshTFBQFJM7t8LSbqh0NBSua1d7a4AQVfnnFNTTlvbgtLR/ryCBuP/HYT/h+U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1788263858171535.2239075162678; Tue, 1 Sep 2026 04:57:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x1N6i-0006u8-6Y; Tue, 01 Sep 2026 07:56:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x1Ln8-0001Wl-Py for qemu-devel@nongnu.org; Tue, 01 Sep 2026 06:32:34 -0400 Received: from mail-pg1-x529.google.com ([2607:f8b0:4864:20::529]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1x1Ln6-0004m9-MH for qemu-devel@nongnu.org; Tue, 01 Sep 2026 06:32:34 -0400 Received: by mail-pg1-x529.google.com with SMTP id 41be03b00d2f7-ca766c1c9ccso3150230a12.0 for ; Tue, 01 Sep 2026 03:32:31 -0700 (PDT) Received: from DESKTOP-G8U0VEE ([2405:201:e03d:cb:7583:6eee:4319:afcd]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3286f80a0a5sm41589717eec.11.2026.09.01.03.32.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Sep 2026 03:32:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788258751; x=1788863551; darn=nongnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=7kwdjrF+q/XbeywvWNcw3Wj5lkryI6dPWIi6HjkeNoE=; b=Cm0Y8y53wZ0XaYlOvD7Y24BX5jrJ2PebhjgfGVUo/eq1oiknDF+0Sv0qcRQ2YOlYEW LSRZCC3doGGnTQlxClFjvoBZeu4BC1SZSDP4GDYzogLi/dE+cu01QYQWRVze5Qv5jHMf /ISNnFr/71l+qqAv/M2ZnsrMaO0ES1KiCetxUWwkUtwCtyPXC1GUKfTTI/R3qaBhW46k IG/554owRJYBqvnHSMeFRuO9B6nFpAu1YVb8wukM3vyFMwOdNj5nk10inTwpOs69okLX ixNuy++GZD5F2Wnmseh7x5Hd+4glLsBEadKMyzsjLmIDEtcp3LlLOGqUvdhDWEfq/QbL xT1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788258751; x=1788863551; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=7kwdjrF+q/XbeywvWNcw3Wj5lkryI6dPWIi6HjkeNoE=; b=QliFRif2WVqtYZMwDdgHvhXFCd7oy803ZJOcLZuQDNSlYKjgUski07KJJwRLx9YwrD mYdHzVTwgjSqAqSxjZPo/nRIDf6cLgmUA5rhFlg7Hk2taWbg5zIRKxbkBGZ0S5N/myIk G6gkTiE7XDPUuBn0AZvbS//nH50Hbt6mhOoQSk5Ysr5JOMWZ8B1R15WOIh+X8ZhpxXUQ B6UrMbJegBHBz1xBTS6JnDi+PV44tcMJBcXAAF6WicEg6vijuXOfHL2ejujgicE0pbV2 OOlJHSrqs//iyCRqhszUuJMXpT+TLTRAOg6EC9dVLTjDvboitOGi4TMcji/lAwBKn0xt VdTg== X-Gm-Message-State: AFuF++kKCGDaiWgO6w+x64hjWDrpES2z+16AVNxHskQdn/3IxWHb8dR2 sK0jh/gY2Pvzuo6ocWupbdzfR2DZ5tKBv8+rWmwncDxukrfsXkRRMp0BqMimGA== X-Gm-Gg: AYBFou3Zbenq35ytVITjBFZAwb+pZhEusYn/Qcdd7dJw6XQS+gwkNiIrmd3wKQB5Ryh MeLkV0XWzJ8dbyqhRMnE7MN/shMAT6Jdr52pOsWq0xqvJb+33uBfhzcuojyGSrdYISucQDh3Ons U+tzG1w+72Yr0+U2bsKAf6iF4NciiuN998P5iA6ETpgEpqRhuewnL2PA77EGCPCJkIPVRiAhjrM Uv5MeTUnQ8fbW6KbLXNxOhixM0AKbuZ7LIqk8w8pmH181vIOzp0xVmQnXLajsQdOLILCuWwkmC6 h45frXIzBeWvq/JRzja5T4veI8RgXtXBYVW+/i1ZB2PdnwYaUhEnrt4VoCgOvDw0fl4q3C3jNWr ftpn4dLtzynPFtfkP/viuw3HUJpLs4JcJCAj9iXoZM8M7AA1FkS6wDvZPpjdIkPK7hJXYAH/ax1 uXw0HFSx1jQP5B+8rhOit/sQDJyYATiHIKGhdw+9J+KCylNYDsnSqibIiu2AA2gX5rAkNw2+Yi7 aLdRhpB X-Received: by 2002:a17:90b:50c6:b0:38e:97f0:aa4b with SMTP id 98e67ed59e1d1-396d1017316mr51494987a91.13.1788258750620; Tue, 01 Sep 2026 03:32:30 -0700 (PDT) From: Nagendran K To: qemu-devel@nongnu.org Cc: philmd@linaro.org, Nagendran K Subject: [PATCH] hw/core/loader.c: Added Extended Tektronix HEX file support Date: Tue, 1 Sep 2026 16:02:17 +0530 Message-ID: <20260901103223.710-1-nagendranjairam52@gmail.com> X-Mailer: git-send-email 2.54.0.windows.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=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::529; envelope-from=nagendranjairam52@gmail.com; helo=mail-pg1-x529.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Tue, 01 Sep 2026 07:56:49 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1788263861197154100 Content-Type: text/plain; charset="utf-8" Added support for loading Extended Tektronix HEX files through the generic loader. The loader parses Extended Tektronix records, validates their checksums, and loads the data at the addresses specified in the file. This allows Extended Tektronix files to be loaded directly without manual conversion to another supported format. Tested by loading an Extended Tektronix file containing a simple UART application on the RealView EB machine. The application executed successfully and produced the expected UART output. Signed-off-by: Nagendran K --- hw/core/loader.c | 141 +++++++++++++++++++++++---------------- include/hw/core/loader.h | 7 +- 2 files changed, 87 insertions(+), 61 deletions(-) diff --git a/hw/core/loader.c b/hw/core/loader.c index 2943f69e92..33ccb51d56 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -1958,8 +1958,11 @@ typedef struct { } Ext_Tek_HexLine; =20 /* return 0 or -1 if error */ -static bool parse_ext_tek_hex_record(Ext_Tek_HexLine *line, uint8_t *our_c= hecksum, const uint8_t c, - uint32_t *index, const bool in_process) +static bool parse_ext_tek_hex_record(Ext_Tek_HexLine *line, + uint8_t *our_checksum, + const uint8_t c, + uint32_t *index, + const bool in_process) { /* +---------+---------------+-----------+---------------+------------= -+ * | record | record | | | = | @@ -1977,27 +1980,35 @@ static bool parse_ext_tek_hex_record(Ext_Tek_HexLin= e *line, uint8_t *our_checksu if (!g_ascii_isxdigit(c) || !in_process) { return false; } - //still idx is computed nibble wise + /* still idx is computed nibble wise */ value =3D g_ascii_xdigit_value(c); value =3D (idx & 0x1) ? (value & 0xf) : (value << 4); if (idx < 2) { line->record_length |=3D value; - } else if (idx=3D=3D2) { + } else if (idx =3D=3D 2) { line->record_type |=3D value; - } else if (2 < idx && idx <=3D4) { + } else if (2 < idx && idx <=3D 4) { line->checksum |=3D value; } - //Extracting address length from record to fill that many no of addres= s characters in the address field of the line structure.=20 - else if ( idx=3D=3D5){ + /* + * Extracting address length from record to fill that many no of addre= ss + * characters in the address field of the line structure. + */ + else if (idx =3D=3D 5) { address_len |=3D value; - }else if (6 <=3D idx && idx <=3D (6 + address_len)) { + } else if (6 <=3D idx && + idx <=3D (6 + address_len)) { line->address <<=3D address_len; line->address +=3D g_ascii_xdigit_value(c); } - //Checking whether index above address last char index and reaches til= l record length=20 + /* + * Checking whether index above address last char index + * and reaches till record length. Right shifting one divides the + * nibble wise index by 2 to get the byte wise index to + * fill the data field of the line structure + */ else if ((6 + address_len) < idx && - idx <=3D line->record_length) { - //Right shifting one divides the nibble wise index by 2 to get the= byte wise index to fill the data field of the line structure. + idx <=3D line->record_length) { line->data[(idx - (6 + address_len)) >> 1] |=3D value; } else { return false; @@ -2040,12 +2051,12 @@ static int handle_ext_tek_hex_record_type(Ext_TekHe= xParser *parser) } =20 /* copy from line buffer to output bin_buf */ - //sizeof(line->data) is given to dynamically calculate the size of= data field + /* sizeof(line->data) dynamically calculates the size of data fiel= d */ memcpy(parser->bin_buf + parser->current_rom_index, line->data, sizeof(line->data)); parser->current_rom_index +=3D sizeof(line->data); parser->total_size +=3D sizeof(line->data); - //As address is absolute address, we dont need to calculate next a= ddress to write + /* As address is absolute, we dont need to calculate next address = */ break; =20 case TEK_TERMINATION_RECORD: @@ -2065,15 +2076,18 @@ static int handle_ext_tek_hex_record_type(Ext_TekHe= xParser *parser) } =20 /* return size or -1 if error */ -static int parse_ext_tek_hex_blob(const char *filename, hwaddr *addr, uint= 8_t *ext_tek_blob, - size_t ext_tek_blob_size, AddressSpace *as) -{ - bool in_process =3D false; /* avoid re-enter and - * check whether record begin with '%' */ +static int parse_ext_tek_hex_blob(const char *filename, + hwaddr *addr, + uint8_t *ext_tek_blob, + size_t ext_tek_blob_size, + AddressSpace *as) +{ + /* avoid re-enter and check whether record begin with '%' */ + bool in_process =3D false; uint8_t *end =3D ext_tek_blob + ext_tek_blob_size; uint8_t our_checksum =3D 0; uint32_t record_index =3D 0; - =20 + Ext_TekHexParser parser =3D { .filename =3D filename, .bin_buf =3D g_malloc(ext_tek_blob_size), @@ -2085,47 +2099,52 @@ static int parse_ext_tek_hex_blob(const char *filen= ame, hwaddr *addr, uint8_t *e rom_transaction_begin(); =20 for (; ext_tek_blob < end && !parser.complete; ++ext_tek_blob) { - switch (*ext_tek_blob) { - case '\r': - case '\n': - if (!in_process) { - break; - } + switch (*ext_tek_blob) { + case '\r': + case '\n': + if (!in_process) { + break; + } =20 - in_process =3D false; - //record_length byte stores the number of hex characters (nibbles)= in the record - //so, record_length as the authoritative count of hex characters (= nibbles) in the record=20 - //and compare it directly to the nibble index(record index). - if ((parser.line.record_length !=3D record_index) || (our_checksum= !=3D 0)) { - parser.total_size =3D -1; - goto out; - } + in_process =3D false; + /* + * record_length byte stores the number of hex characters + * (nibbles) in the record and compare it directly to + * the nibble index(record index). + */ + if ((parser.line.record_length !=3D record_index) || + (our_checksum !=3D 0)) { + parser.total_size =3D -1; + goto out; + } =20 - if (handle_ext_tek_hex_record_type(&parser) =3D=3D -1) { - parser.total_size =3D -1; - goto out; - } - break; + if (handle_ext_tek_hex_record_type(&parser) =3D=3D -1) { + parser.total_size =3D -1; + goto out; + } + break; =20 - /* start of a new record. */ - case '%': - memset(&parser.line, 0, sizeof(Ext_Tek_HexLine)); - in_process =3D true; - record_index =3D 0; - break; + /* start of a new record. */ + case '%': + memset(&parser.line, 0, sizeof(Ext_Tek_HexLine)); + in_process =3D true; + record_index =3D 0; + break; =20 - /* decoding lines */ - default: - if (!parse_ext_tek_hex_record(&parser.line, &our_checksum, *ext_te= k_blob, - &record_index, in_process)) { - parser.total_size =3D -1; - goto out; - } - break; - } + /* decoding lines */ + default: + if (!parse_ext_tek_hex_record(&parser.line, + &our_checksum, + *ext_tek_blob, + &record_index, in_process)) { + parser.total_size =3D -1; + goto out; + } + break; + } } =20 - out: + out: g_free(parser.bin_buf); rom_transaction_end(parser.total_size !=3D -1); return parser.total_size; @@ -2133,18 +2152,22 @@ static int parse_ext_tek_hex_blob(const char *filen= ame, hwaddr *addr, uint8_t *e =20 =20 /* return size or -1 if error */ -ssize_t load_targphys_ext_tek_hex_as(const char *filename, hwaddr *entry, = AddressSpace *as) +ssize_t load_targphys_ext_tek_hex_as(const char *filename, + hwaddr *entry, + AddressSpace *as) { gsize ext_tek_blob_size; gchar *ext_tek_blob; int total_size =3D 0; =20 - if (!g_file_get_contents(filename, &ext_tek_blob, &ext_tek_blob_size, = NULL)) { + if (!g_file_get_contents(filename, &ext_tek_blob, + &ext_tek_blob_size, NULL)) { return -1; } - total_size =3D parse_ext_tek_hex_blob(filename, entry, (uint8_t *)ext_= tek_blob, - ext_tek_blob_size, as); + total_size =3D parse_ext_tek_hex_blob(filename, entry, + (uint8_t *)ext_tek_blob, + ext_tek_blob_size, as); =20 g_free(ext_tek_blob); return total_size; -} \ No newline at end of file +} diff --git a/include/hw/core/loader.h b/include/hw/core/loader.h index 336a987f85..c0d29b1d44 100644 --- a/include/hw/core/loader.h +++ b/include/hw/core/loader.h @@ -57,7 +57,8 @@ ssize_t load_image_targphys_as(const char *filename, ssize_t load_targphys_hex_as(const char *filename, hwaddr *entry, AddressSpace *as); =20 - /**load_targphys_ext_tek_as: +/** + * load_targphys_ext_tek_as: * @filename: Path to the .tek file * @entry: Store the entry point given by the .tek file * @as: The AddressSpace to load the .tek file to. The value of @@ -67,7 +68,9 @@ ssize_t load_targphys_hex_as(const char *filename, hwaddr= *entry, * * Returns the size of the loaded .tek file on success, -1 otherwise. */ -ssize_t load_targphys_ext_tek_hex_as(const char *filename, hwaddr *entry, = AddressSpace *as); +ssize_t load_targphys_ext_tek_hex_as(const char *filename, + hwaddr *entry, + AddressSpace *as); =20 /** load_image_targphys: * Same as load_image_targphys_as(), but doesn't allow the caller to speci= fy --=20 2.54.0.windows.1