1 /* SPDX-License-Identifier: GPL-2.0-only */
16 #define SEEK_SET 0 /* Seek from beginning of file. */
18 #define DIR_SEPARATOR '/'
19 #define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
20 #define HAS_DRIVE_SPEC(f) (0)
22 #define COVERAGE_SIZE (32*1024)
24 #define COVERAGE_MAGIC 0x584d4153
26 static FILE *current_file
= NULL
;
27 static FILE *previous_file
= NULL
;
29 static FILE *fopen(const char *path
, const char *mode
)
31 #if CONFIG(DEBUG_COVERAGE)
32 printk(BIOS_DEBUG
, "%s %s with mode %s\n", __func__
, path
, mode
);
35 current_file
= cbmem_add(CBMEM_ID_COVERAGE
, 32*1024);
37 previous_file
= current_file
;
39 (FILE *)(ALIGN_UP(((unsigned long)previous_file
->data
40 + previous_file
->len
), 16));
43 // TODO check if we're at the end of the CBMEM region (ENOMEM)
45 current_file
->magic
= COVERAGE_MAGIC
;
46 current_file
->next
= NULL
;
48 previous_file
->next
= current_file
;
49 current_file
->filename
= (char *)¤t_file
[1];
50 strcpy(current_file
->filename
, path
);
52 (char *)ALIGN_UP(((unsigned long)current_file
->filename
53 + strlen(path
) + 1), 16);
54 current_file
->offset
= 0;
55 current_file
->len
= 0;
61 static int fclose(FILE *stream
)
63 #if CONFIG(DEBUG_COVERAGE)
64 printk(BIOS_DEBUG
, "%s %s\n", __func__
, stream
->filename
);
69 static int fseek(FILE *stream
, long offset
, int whence
)
71 /* fseek should only be called with offset==0 and whence==SEEK_SET
72 * to a freshly opened file. */
73 gcc_assert(offset
== 0 && whence
== SEEK_SET
);
74 #if CONFIG(DEBUG_COVERAGE)
75 printk(BIOS_DEBUG
, "%s %s offset=%ld whence=%d\n",
76 __func__
, stream
->filename
, offset
, whence
);
81 static long ftell(FILE *stream
)
83 /* ftell should currently not be called */
85 #if CONFIG(DEBUG_COVERAGE)
86 printk(BIOS_DEBUG
, "%s %s\n", __func__
, stream
->filename
);
91 static size_t fread(void *ptr
, size_t size
, size_t nmemb
, FILE *stream
)
93 #if CONFIG(DEBUG_COVERAGE)
94 printk(BIOS_DEBUG
, "%s: ptr=%p size=%zd nmemb=%zd FILE*=%p\n",
95 __func__
, ptr
, size
, nmemb
, stream
);
100 static size_t fwrite(const void *ptr
, size_t size
, size_t nmemb
, FILE *stream
)
102 #if CONFIG(DEBUG_COVERAGE)
103 printk(BIOS_DEBUG
, "%s: %zd * %zd bytes to file %s\n",
104 __func__
, nmemb
, size
, stream
->filename
);
106 // TODO check if file is last opened file and fail otherwise.
108 memcpy(stream
->data
+ stream
->offset
, ptr
, size
* nmemb
);
109 stream
->len
+= (nmemb
* size
) - (stream
->len
- stream
->offset
);
110 stream
->offset
+= nmemb
* size
;
114 static void setbuf(FILE *stream
, char *buf
)
116 gcc_assert(buf
== 0);
119 static void coverage_init(void *unused
)
121 extern long __CTOR_LIST__
;
122 typedef void (*func_ptr
)(void);
123 func_ptr
*ctor
= (func_ptr
*) &__CTOR_LIST__
;
127 for (; *ctor
!= (func_ptr
) 0; ctor
++)
131 void __gcov_flush(void);
132 static void coverage_exit(void *unused
)
134 #if CONFIG(DEBUG_COVERAGE)
135 printk(BIOS_DEBUG
, "Syncing coverage data.\n");
140 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE
, BS_ON_ENTRY
, coverage_init
, NULL
);
141 BOOT_STATE_INIT_ENTRY(BS_OS_RESUME
, BS_ON_ENTRY
, coverage_exit
, NULL
);
142 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD
, BS_ON_EXIT
, coverage_exit
, NULL
);