ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c File Reference

On-silicon HIL: open + parse a real .epub from SD via ra8_fs (#114). More...

#include <stddef.h>
#include <stdint.h>
#include "epub.h"
#include "epub_fixture.h"
#include "epub_fs.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_isr.h"
#include "ra8_log.h"
#include "ra8_port_constants.h"
#include "ra8_port_utils.h"
#include "ra8_sci_spi.h"
#include "ra8_sdmmc_spi.h"
#include "ra8_spi.h"
#include "ra8_time.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  eoh_consts_t : uint32_t {
  k_eoh_uart_baud = 115200U ,
  k_eoh_spi_chan = 0U ,
  k_eoh_expect_chap = 2U ,
  k_eoh_expect_crc = 0xCF23AEEEU ,
  k_eoh_chap_cap = 4096U ,
  k_eoh_crc_init = 0xFFFFFFFFU ,
  k_eoh_crc_poly = 0xEDB88320U ,
  k_eoh_crc_bits = 8U ,
  k_eoh_hex_nibbles = 8U ,
  k_eoh_nibble_bits = 4U ,
  k_eoh_nibble_mask = 0x0FU ,
  k_eoh_dec_ten = 10U
}
 Console / SPI / parse knobs (no magic numbers). More...
enum  eoh_err_t : uint32_t {
  k_eoh_err_none = 0U ,
  k_eoh_err_init = 1U ,
  k_eoh_err_card = 2U ,
  k_eoh_err_mount = 3U ,
  k_eoh_err_prov = 4U ,
  k_eoh_err_open = 5U ,
  k_eoh_err_chap = 6U ,
  k_eoh_err_load = 7U ,
  k_eoh_err_crc = 8U ,
  k_eoh_err_meta = 9U
}
 Failure-stage codes stamped to g_eoh_err for SWD / --dump-sym. More...
enum  eoh_pace_t : uint32_t { k_eoh_frame_ms = 100U }
 Idle-loop pacing for the success heartbeat. More...

Functions

static void eoh_print (const uint8_t *msg, uint32_t len)
 Emit a byte run on the SCI8 console.
static void eoh_fail (uint32_t err, const uint8_t *msg, uint32_t len)
 Stamp the failure stage, print the FAIL banner, and park the CPU.
static uint32_t eoh_crc32 (const uint8_t *data, size_t len)
 CRC-32 (reflected, poly 0xEDB88320) over data.
static void eoh_print_hex (uint32_t value)
 Print a 32-bit value as 8 upper-case hex digits.
static void eoh_print_uint (uint32_t value)
 Print a small unsigned integer in decimal.
static ra8_err_t eoh_spi_set_clock (void *ctx, uint32_t hz)
static ra8_err_t eoh_spi_cs (void *ctx, bool asserted)
 ra8_sdmmc_spi_transport_t::cs over ra8_gpio (CS active-low).
static ra8_err_t eoh_spi_xfer (void *ctx, const uint8_t *tx, uint8_t *rx, uint32_t len)
 ra8_sdmmc_spi_transport_t::xfer over ra8_sci_spi_xfer.
static ra8_err_t eoh_spi_pins_init (void)
 Route Pmod2 SPI pins and claim CS as a GPIO output (idle high).
static void eoh_setup_or_halt (uint32_t *out_pclka_hz)
 Bring up CGC + SysTick + console SCI + SPI + CS GPIO; halt on fail.
static void eoh_init_card_or_halt (uint32_t *pclka_hz)
 Init the SD card over SPI; halt with a diagnostic on failure.
static ra8_fs_mount_teoh_mount_or_halt (void)
 Mount the card, formatting FAT32 first if it is blank/unmountable.
static void eoh_provision_or_halt (ra8_fs_mount_t *mount)
 Write the baked .epub onto the volume if k_eoh_book_path absent.
static uint16_t eoh_parse_or_halt (ra8_fs_mount_t *mount, uint32_t *out_crc)
 Open the provisioned .epub off SD, verify the spine, CRC chapter 0.
void main (void)
 App entry: SD bring-up -> provision -> open/parse -> heartbeat idle.

Variables

static const ra8_port_pin_t k_eoh_pin_sck = (ra8_port_pin_t)k_ra8_board_pmod2_spi_sck
 Pmod2 SPI pins (J25) – SCI0 Simple-SPI; CS held by GPIO.
static const ra8_port_pin_t k_eoh_pin_cipo = (ra8_port_pin_t)k_ra8_board_pmod2_spi_cipo
static const ra8_port_pin_t k_eoh_pin_copi = (ra8_port_pin_t)k_ra8_board_pmod2_spi_copi
static const ra8_port_pin_t k_eoh_pin_cs = (ra8_port_pin_t)k_ra8_board_pmod2_spi_cs
static const char k_eoh_book_path [] = "BOOK.EPB"
 Book path on the SD volume (8.3 short name; ra8_fs is root-only).
volatile uint32_t g_eoh_err = (uint32_t)k_eoh_err_none
 First failing stage (eoh_err_t), 0 on success.
volatile uint32_t g_eoh_chapters = 0U
 Parsed chapter (spine) count on success; 0 otherwise.
volatile uint32_t g_eoh_crc = 0U
 Chapter-0 decompressed-XHTML CRC-32 on success; 0 otherwise.
volatile uint32_t g_eoh_heartbeat = 0U
 Idle heartbeat; advances ONLY after a clean parse (the HIL gate).
static epub_book_t s_book
 Opened book (large – file-scope, not on the stack).
static epub_stream_fs_ctx_t s_epub_io
 Streamed-open source-file context; must outlive s_book (#230).
static uint8_t s_chapter [k_eoh_chap_cap]
 Chapter-0 XHTML scratch (file-scope to keep the stack small).
static ra8_fs_backend_t s_backend
 SD backend; file-scope so the mount handle may reference it.
static const uint8_t k_msg_boot [] = "epub-open-hil: boot\r\n"
static const uint8_t k_msg_cardok [] = "epub-open-hil: card ready\r\n"
static const uint8_t k_msg_finit [] = "epub-hil: FAIL init\r\n"
static const uint8_t k_msg_fcard [] = "epub-hil: FAIL card\r\n"
static const uint8_t k_msg_fmount [] = "epub-hil: FAIL mount\r\n"
static const uint8_t k_msg_fprov [] = "epub-hil: FAIL provision\r\n"
static const uint8_t k_msg_fopen [] = "epub-hil: FAIL open\r\n"
static const uint8_t k_msg_fchap [] = "epub-hil: FAIL chapters\r\n"
static const uint8_t k_msg_fload [] = "epub-hil: FAIL load\r\n"
static const uint8_t k_msg_fcrc [] = "epub-hil: FAIL crc\r\n"
static const uint8_t k_msg_fmeta [] = "epub-hil: FAIL meta\r\n"
static const uint8_t k_msg_pre [] = "epub-hil: chapters="
static const uint8_t k_msg_crc [] = " ch0_crc="
static const uint8_t k_msg_ok [] = " PASS\r\n"

Detailed Description

On-silicon HIL: open + parse a real .epub from SD via ra8_fs (#114).

Tag
[Ring 6 / APP] {World: S}

epub_parse proved the epub parse stack runs on the M85 from a baked in-memory blob (#139). This app closes the storage gap: it reads the .epub off a real microSD card through ra8_fs – the exact path the e-reader uses – so the byte-twiddling parse layer is exercised against real SD timing + the FAT read path, not just a .rodata array.

Flow: bring up the Pmod2 microSD over the ra8_sdmmc_spi SPI-mode driver, mount an ra8_fs volume (formatting FAT32 first if the card is blank), self-provision a known 2-chapter .epub onto it if absent (the same seed_two_chapters seed as epub_parse), then epub_open_streamed_fs() it – the production open path (#230): no whole-file buffer, every ZIP read seeks the card on demand – and assert:

  • chapter (spine) count == 2,
  • chapter 0's decompressed XHTML CRC-32 == 0xCF23AEEE (byte-exact for the seed; identical on ra8_emulator and silicon),
  • Dublin Core metadata parses with a non-empty title. The SCI8 console banner on success is:

epub-hil: chapters=2 ch0_crc=CF23AEEE PASS

The HIL gate is memprobe (J-Link / ra8_emulator --dump-sym), not the console: an SD app drives the SCI0 Simple-SPI bus, and ra8_emulator folds every SCI channel into one console line, so the SCI8 banner is interleaved with SPI traffic there (the same reason the sibling SD HIL apps – sd_font_render, fs_format_mount – gate on SWD globals). The success path advances g_eoh_heartbeat once per frame and only after every assertion passes (chapter count, byte-exact CRC, metadata); any failure stamps g_eoh_err and parks without bumping the heartbeat. So a steadily-advancing heartbeat with a zero g_eoh_err proves the whole SD -> ra8_fs -> epub pipeline ran. The console banner remains for a real-bench scope and human triage.

Required external hardware (on-bench): Digilent PMOD MicroSD (410-380) in Pmod2 (J25) with a microSD inserted. THIS APP MAY FORMAT THE CARD. Under ra8_emulator attach a blank card with --sd-new 64:fat32.

Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ eoh_consts_t

enum eoh_consts_t : uint32_t

Console / SPI / parse knobs (no magic numbers).

Enumerator
k_eoh_uart_baud 

Console baud.

k_eoh_spi_chan 

Pmod2 / J25 SCI0 Simple-SPI.

k_eoh_expect_chap 

Spine length of the baked seed.

k_eoh_expect_crc 

Chapter-0 XHTML CRC-32 (seed).

k_eoh_chap_cap 

Chapter XHTML scratch capacity.

k_eoh_crc_init 

CRC-32 initial value.

k_eoh_crc_poly 

CRC-32 reflected polynomial.

k_eoh_crc_bits 

Bits folded per byte.

k_eoh_hex_nibbles 

Hex digits in a 32-bit value.

k_eoh_nibble_bits 

Bits per hex nibble.

k_eoh_nibble_mask 

Low-nibble mask.

k_eoh_dec_ten 

Hex digit / decimal split.

Definition at line 69 of file main.c.

◆ eoh_err_t

enum eoh_err_t : uint32_t

Failure-stage codes stamped to g_eoh_err for SWD / --dump-sym.

Zero means "no failure yet". Each value identifies the first step that failed, so a memprobe gate can triage without the console.

Enumerator
k_eoh_err_none 

No failure (success path).

k_eoh_err_init 

CGC / time / console / SPI bring-up.

k_eoh_err_card 

SD card SPI init.

k_eoh_err_mount 

Mount (and format-if-blank).

k_eoh_err_prov 

Provision the .epub onto the card.

k_eoh_err_open 

epub_open_streamed_fs.

k_eoh_err_chap 

Chapter-count mismatch.

k_eoh_err_load 

Chapter-0 DEFLATE load.

k_eoh_err_crc 

Chapter-0 CRC mismatch.

k_eoh_err_meta 

Metadata parse / empty title.

Definition at line 100 of file main.c.

◆ eoh_pace_t

enum eoh_pace_t : uint32_t

Idle-loop pacing for the success heartbeat.

Enumerator
k_eoh_frame_ms 

Heartbeat period in milliseconds.

Definition at line 114 of file main.c.

Function Documentation

◆ eoh_crc32()

uint32_t eoh_crc32 ( const uint8_t * data,
size_t len )
static

CRC-32 (reflected, poly 0xEDB88320) over data.

Definition at line 183 of file main.c.

References k_eoh_crc_bits, k_eoh_crc_init, and k_eoh_crc_poly.

Referenced by eoh_parse_or_halt().

◆ eoh_fail()

void eoh_fail ( uint32_t err,
const uint8_t * msg,
uint32_t len )
static

Stamp the failure stage, print the FAIL banner, and park the CPU.

Records err in g_eoh_err (for the --dump-sym / J-Link memprobe gate), emits msg on the console (for a real-bench scope), then spins in WFI. The success heartbeat (g_eoh_heartbeat) is never bumped from here, so a memprobe gate sees a frozen heartbeat plus a non-zero g_eoh_err.

Parameters
[in]errFailure-stage code (eoh_err_t).
[in]msgConsole diagnostic bytes.
[in]lenLength of msg.

Definition at line 173 of file main.c.

References eoh_print(), and g_eoh_err.

Referenced by eoh_init_card_or_halt(), eoh_mount_or_halt(), eoh_parse_or_halt(), eoh_provision_or_halt(), and eoh_setup_or_halt().

◆ eoh_init_card_or_halt()

void eoh_init_card_or_halt ( uint32_t * pclka_hz)
static

Init the SD card over SPI; halt with a diagnostic on failure.

Definition at line 295 of file main.c.

References eoh_fail(), eoh_print(), eoh_spi_cs(), eoh_spi_set_clock(), eoh_spi_xfer(), k_eoh_err_card, k_msg_cardok, k_msg_fcard, k_ra8_ok, and ra8_sdmmc_spi_init().

Referenced by main().

◆ eoh_mount_or_halt()

ra8_fs_mount_t * eoh_mount_or_halt ( void )
static

Mount the card, formatting FAT32 first if it is blank/unmountable.

Binds the SD backend, tries to mount; a blank card (e.g. ra8_emulator's --sd-new before any format, or a fresh bench card) fails to mount, so it is formatted FAT32 and mounted. Halts on a hard failure.

Returns
The mounted volume handle (never NULL on return).

Definition at line 316 of file main.c.

References eoh_fail(), k_eoh_err_mount, k_msg_fmount, k_ra8_fs_type_fat32, k_ra8_ok, ra8_fs_format_opts_t::label, ra8_fs_format(), ra8_fs_mount(), ra8_sdmmc_spi_bind_fs_backend(), s_backend, and ra8_fs_format_opts_t::type.

Referenced by main().

◆ eoh_parse_or_halt()

uint16_t eoh_parse_or_halt ( ra8_fs_mount_t * mount,
uint32_t * out_crc )
static

Open the provisioned .epub off SD, verify the spine, CRC chapter 0.

Parameters
[in]mountMounted SD volume holding k_eoh_book_path.
[out]out_crcReceives the CRC-32 of chapter 0's decompressed XHTML.
Returns
The chapter (spine) count.

Definition at line 355 of file main.c.

References eoh_crc32(), eoh_fail(), epub_get_chapter_count(), epub_get_metadata(), epub_load_chapter(), epub_open_streamed_fs(), k_eoh_book_path, k_eoh_chap_cap, k_eoh_err_chap, k_eoh_err_crc, k_eoh_err_load, k_eoh_err_meta, k_eoh_err_open, k_eoh_expect_chap, k_eoh_expect_crc, k_msg_fchap, k_msg_fcrc, k_msg_fload, k_msg_fmeta, k_msg_fopen, k_ra8_ok, s_book, s_chapter, s_epub_io, and epub_metadata_t::title.

Referenced by main().

◆ eoh_print()

void eoh_print ( const uint8_t * msg,
uint32_t len )
static

Emit a byte run on the SCI8 console.

Definition at line 156 of file main.c.

References ra8_board_uart_console_write().

Referenced by eoh_fail(), eoh_init_card_or_halt(), eoh_print_hex(), eoh_print_uint(), and main().

◆ eoh_print_hex()

void eoh_print_hex ( uint32_t value)
static

Print a 32-bit value as 8 upper-case hex digits.

Definition at line 197 of file main.c.

References eoh_print(), k_eoh_dec_ten, k_eoh_hex_nibbles, k_eoh_nibble_bits, and k_eoh_nibble_mask.

Referenced by main().

◆ eoh_print_uint()

void eoh_print_uint ( uint32_t value)
static

Print a small unsigned integer in decimal.

Definition at line 210 of file main.c.

References eoh_print(), and k_eoh_dec_ten.

Referenced by main().

◆ eoh_provision_or_halt()

void eoh_provision_or_halt ( ra8_fs_mount_t * mount)
static

Write the baked .epub onto the volume if k_eoh_book_path absent.

Definition at line 335 of file main.c.

References eoh_fail(), k_eoh_book_path, k_eoh_err_prov, k_epub_fixture, k_epub_fixture_len, k_msg_fprov, k_ra8_fs_mode_read, k_ra8_ok, ra8_fs_close(), ra8_fs_open(), and ra8_fs_write_file().

Referenced by main().

◆ eoh_setup_or_halt()

void eoh_setup_or_halt ( uint32_t * out_pclka_hz)
static

◆ eoh_spi_cs()

ra8_err_t eoh_spi_cs ( void * ctx,
bool asserted )
static

ra8_sdmmc_spi_transport_t::cs over ra8_gpio (CS active-low).

Definition at line 238 of file main.c.

References k_eoh_pin_cs, k_ra8_level_high, k_ra8_level_low, and ra8_gpio_write().

Referenced by eoh_init_card_or_halt().

◆ eoh_spi_pins_init()

ra8_err_t eoh_spi_pins_init ( void )
staticnodiscard

Route Pmod2 SPI pins and claim CS as a GPIO output (idle high).

Definition at line 252 of file main.c.

References k_eoh_pin_cipo, k_eoh_pin_copi, k_eoh_pin_cs, k_eoh_pin_sck, k_ra8_level_high, k_ra8_ok, k_ra8_psel_sci_async, ra8_gpio_output_init(), and ra8_pfs_route_peripheral().

Referenced by eoh_setup_or_halt().

◆ eoh_spi_set_clock()

ra8_err_t eoh_spi_set_clock ( void * ctx,
uint32_t hz )
static

Definition at line 231 of file main.c.

References k_eoh_spi_chan, and ra8_sci_spi_set_clock().

Referenced by eoh_init_card_or_halt().

◆ eoh_spi_xfer()

ra8_err_t eoh_spi_xfer ( void * ctx,
const uint8_t * tx,
uint8_t * rx,
uint32_t len )
static

ra8_sdmmc_spi_transport_t::xfer over ra8_sci_spi_xfer.

Definition at line 245 of file main.c.

References k_eoh_spi_chan, and ra8_sci_spi_xfer().

Referenced by eoh_init_card_or_halt().

◆ main()

void main ( void )

App entry: SD bring-up -> provision -> open/parse -> heartbeat idle.

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success g_eoh_chapters / g_eoh_crc hold the parsed results, the banner is emitted, and g_eoh_heartbeat advances once per frame.
On any failure g_eoh_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

Definition at line 393 of file main.c.

References eoh_init_card_or_halt(), eoh_mount_or_halt(), eoh_parse_or_halt(), eoh_print(), eoh_print_hex(), eoh_print_uint(), eoh_provision_or_halt(), eoh_setup_or_halt(), g_eoh_chapters, g_eoh_crc, g_eoh_heartbeat, k_eoh_frame_ms, k_msg_boot, k_msg_crc, k_msg_ok, k_msg_pre, ra8_delay_ms(), ra8_isr_globals_enable(), and ra8_log_init().

Variable Documentation

◆ g_eoh_chapters

volatile uint32_t g_eoh_chapters = 0U

Parsed chapter (spine) count on success; 0 otherwise.

Definition at line 125 of file main.c.

Referenced by main().

◆ g_eoh_crc

volatile uint32_t g_eoh_crc = 0U

Chapter-0 decompressed-XHTML CRC-32 on success; 0 otherwise.

Definition at line 127 of file main.c.

Referenced by main().

◆ g_eoh_err

volatile uint32_t g_eoh_err = (uint32_t)k_eoh_err_none

First failing stage (eoh_err_t), 0 on success.

SWD / --dump-sym.

Note
Exported (non-static) so a memprobe gate can read it by symbol.

Definition at line 123 of file main.c.

Referenced by eoh_fail().

◆ g_eoh_heartbeat

volatile uint32_t g_eoh_heartbeat = 0U

Idle heartbeat; advances ONLY after a clean parse (the HIL gate).

Definition at line 129 of file main.c.

Referenced by main().

◆ k_eoh_book_path

const char k_eoh_book_path[] = "BOOK.EPB"
static

Book path on the SD volume (8.3 short name; ra8_fs is root-only).

Definition at line 91 of file main.c.

Referenced by eoh_parse_or_halt(), and eoh_provision_or_halt().

◆ k_eoh_pin_cipo

Definition at line 86 of file main.c.

Referenced by eoh_spi_pins_init().

◆ k_eoh_pin_copi

Definition at line 87 of file main.c.

Referenced by eoh_spi_pins_init().

◆ k_eoh_pin_cs

Definition at line 88 of file main.c.

Referenced by eoh_spi_cs(), and eoh_spi_pins_init().

◆ k_eoh_pin_sck

Pmod2 SPI pins (J25) – SCI0 Simple-SPI; CS held by GPIO.

Definition at line 85 of file main.c.

Referenced by eoh_spi_pins_init().

◆ k_msg_boot

const uint8_t k_msg_boot[] = "epub-open-hil: boot\r\n"
static

Definition at line 140 of file main.c.

Referenced by main().

◆ k_msg_cardok

const uint8_t k_msg_cardok[] = "epub-open-hil: card ready\r\n"
static

Definition at line 141 of file main.c.

Referenced by eoh_init_card_or_halt(), and etoc_init_card_or_halt().

◆ k_msg_crc

const uint8_t k_msg_crc[] = " ch0_crc="
static

Definition at line 152 of file main.c.

Referenced by erb_render_chapter(), ls_emit_banner(), and main().

◆ k_msg_fcard

const uint8_t k_msg_fcard[] = "epub-hil: FAIL card\r\n"
static

Definition at line 143 of file main.c.

Referenced by eoh_init_card_or_halt(), and etoc_init_card_or_halt().

◆ k_msg_fchap

const uint8_t k_msg_fchap[] = "epub-hil: FAIL chapters\r\n"
static

Definition at line 147 of file main.c.

Referenced by eoh_parse_or_halt().

◆ k_msg_fcrc

const uint8_t k_msg_fcrc[] = "epub-hil: FAIL crc\r\n"
static

Definition at line 149 of file main.c.

Referenced by eoh_parse_or_halt(), and wa_verify_or_halt().

◆ k_msg_finit

const uint8_t k_msg_finit[] = "epub-hil: FAIL init\r\n"
static

Definition at line 142 of file main.c.

Referenced by eoh_setup_or_halt(), and etoc_setup_or_halt().

◆ k_msg_fload

const uint8_t k_msg_fload[] = "epub-hil: FAIL load\r\n"
static

Definition at line 148 of file main.c.

Referenced by eoh_parse_or_halt().

◆ k_msg_fmeta

const uint8_t k_msg_fmeta[] = "epub-hil: FAIL meta\r\n"
static

Definition at line 150 of file main.c.

Referenced by eoh_parse_or_halt().

◆ k_msg_fmount

const uint8_t k_msg_fmount[] = "epub-hil: FAIL mount\r\n"
static

Definition at line 144 of file main.c.

Referenced by eoh_mount_or_halt(), and etoc_mount_or_halt().

◆ k_msg_fopen

const uint8_t k_msg_fopen[] = "epub-hil: FAIL open\r\n"
static

Definition at line 146 of file main.c.

Referenced by eoh_parse_or_halt().

◆ k_msg_fprov

const uint8_t k_msg_fprov[] = "epub-hil: FAIL provision\r\n"
static

Definition at line 145 of file main.c.

Referenced by eoh_provision_or_halt(), and etoc_provision_one().

◆ k_msg_ok

const uint8_t k_msg_ok[] = " PASS\r\n"
static

Definition at line 153 of file main.c.

Referenced by ez_print_banner(), main(), and mg_print_banner().

◆ k_msg_pre

const uint8_t k_msg_pre[] = "epub-hil: chapters="
static

Definition at line 151 of file main.c.

Referenced by ez_print_banner(), ls_emit_banner(), main(), and mg_print_banner().

◆ s_backend

ra8_fs_backend_t s_backend
static

SD backend; file-scope so the mount handle may reference it.

Definition at line 138 of file main.c.

Referenced by eoh_mount_or_halt(), etoc_mount_or_halt(), internal_pc_mount_or_halt(), and sh_sd_mount().

◆ s_book

◆ s_chapter

uint8_t s_chapter[k_eoh_chap_cap]
static

Chapter-0 XHTML scratch (file-scope to keep the stack small).

Definition at line 136 of file main.c.

Referenced by eoh_parse_or_halt(), and ep_parse_or_halt().

◆ s_epub_io

epub_stream_fs_ctx_t s_epub_io
static

Streamed-open source-file context; must outlive s_book (#230).

Definition at line 134 of file main.c.

Referenced by eoh_parse_or_halt(), etoc_check_bad(), etoc_read_toc(), sh_sd_close_epub(), and sh_sd_open_epub().