Coverage Report

Created: 2025-06-15 00:57

/src/cmp_tool/programs/rdcu_pkt_to_file.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file   rdcu_pkt_to_file.c
3
 * @author Dominik Loidolt (dominik.loidolt@univie.ac.at)
4
 * @date   2020
5
 *
6
 * @copyright GPLv2
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms and conditions of the GNU General Public License,
9
 * version 2, as published by the Free Software Foundation.
10
 *
11
 * This program is distributed in the hope it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14
 * more details.
15
 *
16
 * @brief RDCU packets to file library
17
 *
18
 * This library provided a rmap_rx and rmap_tx function for the rdcu_rmap
19
 * library to write generated packets into text files.
20
 * @warning this part of the software is not intended to run on-board on the ICU.
21
 */
22
23
#include <stdint.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <limits.h>
28
#include <errno.h>
29
#include <sys/stat.h>
30
31
#include <cmp_support.h>
32
#include <rdcu_pkt_to_file.h>
33
#include <cmp_rdcu.h>
34
#include <rdcu_rmap.h>
35
#include <rdcu_ctrl.h>
36
#include <rdcu_cmd.h>
37
#include <cmp_rdcu_testing.h>
38
39
40
/* Name of the directory where the RMAP packages are stored */
41
static char tc_folder_dir[MAX_TC_FOLDER_DIR_LEN] = "TC_FILES";
42
43
44
/**
45
 * @brief set the directory name where the RMAP packages are stored
46
 *
47
 * @param dir_name  name of the directory where the RMAP packages are stored
48
 */
49
50
void set_tc_folder_dir(const char *dir_name)
51
0
{
52
0
  if (!dir_name)
53
0
    return;
54
55
0
  strncpy(tc_folder_dir, dir_name, sizeof(tc_folder_dir));
56
  /*  Ensure null-termination. */
57
0
  tc_folder_dir[sizeof(tc_folder_dir) - 1] = '\0';
58
0
}
59
60
61
/**
62
 * @brief return a file to write with the name format dir_name/XXX.tc, where XXX
63
 *  is n_tc in decimal representation
64
 *
65
 * @param dir_name  name of the directory where the RMAP packages are stored
66
 * @param n_tc    number of TC commands
67
 *
68
 * @return  pointer to the new file stream
69
 * @see https://developers.redhat.com/blog/2018/05/24/detecting-string-truncation-with-gcc-8/
70
 */
71
72
static FILE *open_file_tc(const char *dir_name, int n_tc)
73
0
{
74
0
  char *pathname;
75
0
  FILE *fp;
76
0
  int n;
77
78
0
  errno = 0;
79
0
  n = snprintf(NULL, 0, "%s/%04d.tc", dir_name, n_tc);
80
0
  if (n < 0) {
81
0
    perror("snprintf failed");
82
0
    abort();
83
0
  }
84
85
0
  errno = 0;
86
0
  pathname = (char *)malloc((size_t)n + 1);
87
0
  if (!pathname) {
88
0
    perror("malloc failed");
89
0
    abort();
90
0
  }
91
92
0
  errno = 0;
93
0
  n = snprintf(pathname, (size_t)n + 1, "%s/%04d.tc", dir_name, n_tc);
94
0
  if (n < 0) {
95
0
    perror("snprintf failed");
96
0
    abort();
97
0
  }
98
99
0
  fp = fopen(pathname, "w");
100
0
  free(pathname);
101
0
  return fp;
102
0
}
103
104
105
/**
106
 * @brief implementation of the rmap_rx function for the rdcu_rmap lib, all
107
 *  generated packages are written to a file.
108
 */
109
110
static int32_t rmap_tx_to_file(const void *hdr, uint32_t hdr_size,
111
             const uint8_t non_crc_bytes, const void *data,
112
             uint32_t data_size)
113
0
{
114
0
  static int n_pkt = 1; /* number of packets */
115
0
  static char tc_folder_dir_old[MAX_TC_FOLDER_DIR_LEN] = {0};
116
0
  uint8_t *blob = NULL;
117
0
  uint32_t n, i;
118
0
  FILE *fp;
119
120
0
  if (hdr == NULL)
121
0
    return 0;
122
123
  /* make sure that string is null-terminated */
124
0
  tc_folder_dir[MAX_TC_FOLDER_DIR_LEN - 1] = '\0';
125
126
0
  if (strcmp(tc_folder_dir, tc_folder_dir_old) != 0) {
127
0
    struct stat st = { 0 };
128
129
0
    n_pkt = 1;
130
131
    /* creating a directory if that directory does not exist */
132
0
    if (stat(tc_folder_dir, &st) == -1) {
133
0
      int err;
134
      #if defined(_WIN32) || defined(_WIN64)
135
        err = mkdir(tc_folder_dir);
136
      #else
137
0
        err = mkdir(tc_folder_dir, 0700);
138
0
      #endif
139
0
      if (err)
140
0
        return -1;
141
0
    }
142
143
0
    strncpy(tc_folder_dir_old, tc_folder_dir,
144
0
      sizeof(tc_folder_dir_old));
145
0
    tc_folder_dir_old[sizeof(tc_folder_dir_old) - 1] = '\0';
146
0
  }
147
148
0
  n = rdcu_package(NULL, hdr, hdr_size, non_crc_bytes, data, data_size);
149
0
  if (!n)
150
0
    return -1;
151
0
  blob = malloc(n);
152
0
  if (!blob) {
153
0
    printf("malloc for tx_pkt failed\n");
154
0
    return -1;
155
0
  }
156
157
0
  n = rdcu_package(blob, hdr, hdr_size, non_crc_bytes, data, data_size);
158
0
  if (!n) {
159
0
    free(blob);
160
0
    return -1;
161
0
  }
162
163
0
  fp = open_file_tc(tc_folder_dir, n_pkt);
164
165
0
  if (fp == NULL) {
166
0
    perror("fopen()");
167
0
    free(blob);
168
0
    return -1;
169
0
  }
170
171
0
  for (i = 0; i < n; i++) {
172
    /* printf("%02X ", blob[i]); */
173
0
    fprintf(fp, "%02X ", blob[i]);
174
    /* if (i && !((i + 1) % 40)) */
175
    /* printf("\n"); */
176
0
  }
177
178
  /* printf("\n"); */
179
0
  fprintf(fp, "\n");
180
0
  fclose(fp);
181
182
0
  free(blob);
183
184
0
  n_pkt++;
185
0
  return 0;
186
0
}
187
188
189
/**
190
 * @brief Dummy implementation of the rmap_rx function for the rdcu_rmap lib. We
191
 * do not want to receive any packages.
192
 */
193
194
static uint32_t rmap_rx_dummy(uint8_t *pkt)
195
0
{
196
0
  (void)(pkt);
197
0
  return 0;
198
0
}
199
200
201
/**
202
 * @brief read out .rdcu_pkt_mode_cfg configure file
203
 *
204
 * @param icu_addr  RMAP source logical address
205
 * @param rdcu_addr RMAP destination logical address
206
 * @param mtu   the maximum data transfer size per unit
207
 *
208
 * @returns 0 on success, otherwise error
209
 */
210
211
static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr,
212
          uint32_t *mtu)
213
0
{
214
  /* TODO: Build string" %s/.rdcu_pkt_mode_cfg", RDCU_PKT_MODE_DIR */
215
0
  char line[256];
216
0
  char *end;
217
0
  FILE *fp = fopen(".rdcu_pkt_mode_cfg", "r");
218
219
0
  *icu_addr = DEF_ICU_ADDR;
220
0
  *rdcu_addr = DEF_RDCU_ADDR;
221
0
  *mtu = DEF_MTU;
222
223
0
  if (fp == NULL) {
224
    /* use default values */
225
0
    printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %u for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu);
226
0
    return 0;
227
0
  }
228
229
0
  while (fgets(line, sizeof(line), fp)) {
230
0
    size_t l;
231
0
    unsigned long i;
232
0
    char *p;
233
234
0
    p = strchr(line, '\n');
235
0
    if (p) {
236
0
      *p = '\0';
237
0
    } else {
238
0
      fprintf(stderr, "Error read in line to long.\n");
239
0
      fclose(fp);
240
0
      return -1;
241
0
    }
242
243
0
    if (line[0] == ' ' || line[0] == '\t' || line[0] == '#')
244
0
      continue;
245
0
    l = strlen("ICU_ADDR");
246
0
    if (!strncmp(line, "ICU_ADDR", l)) {
247
0
      end = NULL;
248
0
      errno = 0;
249
0
      i = strtoul(line + l, &end, 0);
250
0
      if (end == line + l || errno == ERANGE || i > 0xFF) {
251
0
        fprintf(stderr, "Error reading ICU_ADDR.\n");
252
0
        errno = 0;
253
0
        fclose(fp);
254
0
        return -1;
255
0
      }
256
0
      *icu_addr = (uint8_t)i;
257
0
      continue;
258
0
    }
259
0
    l = strlen("RDCU_ADDR");
260
0
    if (!strncmp(line, "RDCU_ADDR", l)) {
261
0
      end = NULL;
262
0
      errno = 0;
263
0
      i = strtoul(line + l, &end, 0);
264
0
      if (end == line + l || errno == ERANGE || i > 0xFF) {
265
0
        fprintf(stderr, "Error reading RDCU_ADDR.\n");
266
0
        errno = 0;
267
0
        fclose(fp);
268
0
        return -1;
269
0
      }
270
0
      *rdcu_addr = (uint8_t)i;
271
0
      continue;
272
0
    }
273
0
    l = strlen("MTU");
274
0
    if (!strncmp(line, "MTU", l)) {
275
0
      end = NULL;
276
0
      errno = 0;
277
0
      i = strtoul(line + l, &end, 0);
278
0
      if (end == line + l || errno == ERANGE || i > INT32_MAX) {
279
0
        fprintf(stderr, "Error reading MTU.\n");
280
0
        errno = 0;
281
0
        fclose(fp);
282
0
        return -1;
283
0
      }
284
0
      *mtu = (uint32_t)i;
285
0
      continue;
286
0
    }
287
0
  }
288
0
  fclose(fp);
289
290
0
  printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %u for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu);
291
292
0
  return 0;
293
0
}
294
295
296
/**
297
 * @brief initialise the RDCU packets to file library
298
 *
299
 * @note use the .rdcu_pkt_mode_cfg file to read the icu_addr, rdcu_addr and mtu
300
 *  parameters
301
 *
302
 * @returns 0 on success, otherwise error
303
 */
304
305
int init_rmap_pkt_to_file(void)
306
0
{
307
0
  uint8_t icu_addr, rdcu_addr;
308
0
  uint32_t mtu;
309
310
0
  if (read_rdcu_pkt_mode_cfg(&icu_addr, &rdcu_addr, &mtu))
311
0
    return -1;
312
313
0
  rdcu_ctrl_init();
314
0
  rdcu_set_source_logical_address(icu_addr);
315
0
  rdcu_set_destination_logical_address(rdcu_addr);
316
0
  rdcu_set_destination_key(RDCU_DEST_KEY);
317
0
  rdcu_rmap_init(mtu, rmap_tx_to_file, rmap_rx_dummy);
318
0
  return 0;
319
0
}
320
321
322
/**
323
 * @brief generates the RMAP packets to set up an RDCU compression
324
 * @note note that the initialization function init_rmap_pkt_to_file() must be
325
 *  executed before
326
 * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
327
 *  .rdcu_pkt_mode_cfg file
328
 *
329
 * @param rcfg  RDCU compressor configuration contains all parameters required
330
 *    for compression
331
 *
332
 * @returns 0 on success, error otherwise
333
 */
334
335
int gen_write_rdcu_pkts(const struct rdcu_cfg *rcfg)
336
0
{
337
0
  struct stat st = { 0 };
338
339
0
  if (!rcfg)
340
0
    return -1;
341
342
  /* creating TC_DIR directory if that directory does not exist */
343
0
  if (stat(TC_DIR, &st) == -1) {
344
0
    int err;
345
    #if defined(_WIN32) || defined(_WIN64)
346
      err = mkdir(TC_DIR);
347
    #else
348
0
      err = mkdir(TC_DIR, 0700);
349
0
    #endif
350
0
    if (err)
351
0
      return -1;
352
0
  }
353
354
0
  set_tc_folder_dir(TC_DIR "/compress_data");
355
0
  if (rdcu_compress_data(rcfg))
356
0
    return -1;
357
358
0
  return 0;
359
0
}
360
361
362
/**
363
 * @brief generates the RMAP packets to read the result of an RDCU compression
364
 * @note note that the initialization function init_rmap_pkt_to_file() must be
365
 *  executed before
366
 * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
367
 *  .rdcu_pkt_mode_cfg file
368
 *
369
 * @param info   compressor information contains information of an executed
370
 *     compression
371
 *
372
 * @returns 0 on success, error otherwise
373
 */
374
375
int gen_read_rdcu_pkts(const struct cmp_info *info)
376
0
{
377
0
  int s;
378
0
  void *tmp_buf;
379
0
  struct stat st = { 0 };
380
381
0
  if (!info)
382
0
    return -1;
383
384
  /* creating TC_DIR directory if that directory does not exist */
385
0
  if (stat(TC_DIR, &st) == -1) {
386
0
    int err;
387
    #if defined(_WIN32) || defined(_WIN64)
388
      err = mkdir(TC_DIR);
389
    #else
390
0
      err = mkdir(TC_DIR, 0700);
391
0
    #endif
392
0
    if (err)
393
0
      return -1;
394
0
  }
395
396
0
  set_tc_folder_dir(TC_DIR "/read_status");
397
0
  if (rdcu_read_cmp_status(NULL))
398
0
    return -1;
399
400
0
  set_tc_folder_dir(TC_DIR "/read_info");
401
0
  if (rdcu_read_cmp_info(NULL))
402
0
    return -1;
403
404
0
  set_tc_folder_dir(TC_DIR "/read_cmp_data");
405
0
  s = rdcu_read_cmp_bitstream(info, NULL);
406
0
  if (s < 0)
407
0
    return -1;
408
0
  tmp_buf = malloc((size_t)s);
409
0
  if (!tmp_buf)
410
0
    return -1;
411
0
  s = rdcu_read_cmp_bitstream(info, tmp_buf);
412
0
  free(tmp_buf);
413
0
  if (s < 0)
414
0
    return -1;
415
416
0
  if (model_mode_is_used(info->cmp_mode_used)) {
417
0
    set_tc_folder_dir(TC_DIR "/read_upmodel");
418
0
    s = rdcu_read_model(info, NULL);
419
0
    if (s < 0)
420
0
      return -1;
421
0
    tmp_buf = malloc((size_t)s);
422
0
    if (!tmp_buf)
423
0
      return -1;
424
0
    s = rdcu_read_model(info, tmp_buf);
425
0
    free(tmp_buf);
426
0
    if (s < 0)
427
0
      return -1;
428
0
  }
429
0
  return 0;
430
0
}
431
432
433
/**
434
 * @brief generate the RMAP packets to set up an RDCU compression, read the
435
 *  bitstream and the updated model in parallel to write the data to compressed
436
 *  and the model and start the compression
437
 * @note the compressed data are read from cfg->rdcu_buffer_adr with the length
438
 *  of last_cmp_size
439
 * @note note that the initialization function init_rmap_pkt_to_file() must be
440
 *  executed before
441
 * @note the configuration of the ICU_ADDR, RDCU_ADDR, MTU settings are in the
442
 *  .rdcu_pkt_mode_cfg file
443
 *
444
 * @param rcfg    RDCU compressor configuration contains all parameters
445
 *      required for compression
446
 * @param last_info compression information from the last executed
447
 *      compression
448
 *
449
 * @returns 0 on success, error otherwise
450
 */
451
452
int gen_rdcu_parallel_pkts(const struct rdcu_cfg *rcfg,
453
         const struct cmp_info *last_info)
454
0
{
455
0
  struct stat st = { 0 };
456
457
0
  if (!rcfg)
458
0
    return -1;
459
460
  /* creating TC_DIR directory if that directory does not exist */
461
0
  if (stat(TC_DIR, &st) == -1) {
462
0
    int err;
463
    #if defined(_WIN32) || defined(_WIN64)
464
      err = mkdir(TC_DIR);
465
    #else
466
0
      err = mkdir(TC_DIR, 0700);
467
0
    #endif
468
0
    if (err)
469
0
      return -1;
470
0
  }
471
472
0
  set_tc_folder_dir(TC_DIR "/compress_data_parallel");
473
0
  if (rdcu_compress_data_parallel(rcfg, last_info))
474
0
    return -1;
475
476
0
  return 0;
477
0
}