スキップしてメイン コンテンツに移動

Zephyr build (3)

この記事で関係するターゲット

staticIdt.o ターゲット

[zephyr_base]/Makefile
staticIdt.o: $(TMP_ELF)
        $(call cmd,gen_idt)

$(TMP_ELF)

$(TMP_ELF)は、.tmp_zephyr.prebuilt。
[zephyr_base]/Makefile
TMP_ELF = .tmp_$(KERNEL_NAME).prebuilt

$(call cmd,gen_idt)

cmd_get_idt ファンクションを実行。

cmd_gen_idt ファンクション

[zephyr_base]/Makefile
cmd_gen_idt =                                                             \
(                                                                               \
        $(OBJCOPY) -I $(OUTPUT_FORMAT)  -O binary -j intList $< isrList.bin &&  ・・・①\
        $(GENIDT) -i isrList.bin -n $(CONFIG_IDT_NUM_VECTORS) -o staticIdt.bin  \
                -b int_vector_alloc.bin -m irq_int_vector_map.bin               \
                -l $(CONFIG_MAX_IRQ_LINES) &&                                   ・・・②\
        $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT)              \
                --rename-section .data=staticIdt staticIdt.bin staticIdt.o &&   ・・・③\
        $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT)              \
                --rename-section .data=int_vector_alloc int_vector_alloc.bin    \
                int_vector_alloc.o &&                                           ・・・④\
        $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT)              \
        --rename-section .data=irq_int_vector_map irq_int_vector_map.bin        \
                irq_int_vector_map.o &&                                         ・・・⑤\
        rm staticIdt.bin irq_int_vector_map.bin int_vector_alloc.bin isrList.bin・・・⑥\
)

① $(OBJCOPY) -I $(OUTPUT_FORMAT) -O binary -j intList $< isrList.bin

/Volumes/CrossToolNG/x-tools/i586-pc-elf/bin/i586-pc-elf-objcopy -I elf32-i386  -O binary -j intList .tmp_zephyr.prebuilt isrList.bin
objcopy --help
i586-pc-elf-objcopy [option(s)] in-file [out-file]
  -I --input-target <bfdname>      Assume input file is in format <bfdname>
  -O --output-target <bfdname>     Create an output file in format <bfdname>
  -j --only-section <name>         Only copy section <name> into the output

入力: .tmp_zephyr.prebuilt
出力: isrList.bin
.tmp_zephyr.prebuilt (i386 ELF32ファイル形式)の intList セクションを isrList.bin(バイナリファイル形式)へコピーする。

② $(GENIDT) -i isrList.bin -n $(CONFIG_IDT_NUM_VECTORS) -o staticIdt.bin -b int_vector_alloc.bin -m irq_int_vector_map.bin -l $(CONFIG_MAX_IRQ_LINES)

./scripts/gen_idt/gen_idt -i isrList.bin -n 256 -o staticIdt.bin  -b int_vector_alloc.bin -m irq_int_vector_map.bin -l 128
./scripts/gen_idt/gen_idt
[zephyr_base]/scripts/gen_idt/gen_idt.c をコンパイルして生成する。
[zephyr_base]/scripts/gen_idt/gen_idt.c
(省略)
/**
 * @file
 * @brief Generate static IDT and a bitmap of allocated interrupt vectors.
 * Creates a static IA-32 Interrupt Descriptor Table (IDT).
 *
 * This program expects to be invoked as follows:
 *  gen_idt -i <input file> -o <IDT output file> -n <# of interrupt vectors>
 *          -b <allocated vectors bitmap file>
 * All parameters are required.
 *
 * The <input file> is assumed to be a binary file containing the intList
 * section from the Zephyr Kernel ELF image.
 *
 * <number of interrupt vectors> is the same as CONFIG_IDT_NUM_VECTORS.
 *
 * It is expected that this program is invoked from within the build system
 * during the link stage.
 */
(省略)
$ ./outdir/scripts/gen_idt/gen_idt -h

gen_idt -i <input file> -n <n>

 options

    -b <allocated interrupt vector bitmap output file>
        [Mandatory] The interrupt vector bitmap output file.
    -i <binary file>
        [Mandatory] The input file in binary format.
    -o <IDT output file>
        [Mandatory] The IDT output file.
    -m <IRQ to interrupt vector map file>
        [Mandatory] The IRQ to interrupt vector output file
    -n <n>
        [Mandatory] Number of vectors
    -l <n>
        [Mandatory] Number of IRQ lines
    -v  Display version.
    -h  Display this help.

Returns -1 on error, 0 on success

入力: isrList.bin
出力: staticIdt.bin、int_vector_alloc.bin、irq_int_vector_map.bin
isrList.bin をもとに、割り込みディスクリプタテーブルファイル staticIdt.bin、割り込みベクタ割当ビットマップファイル int_vector_alloc.bin、IRQ-割り込みベクタマップファイル irq_int_vector_map.bin を作成する。
割り込みベクタ数は256。IRQ割り込み線数は128。
staticIdt.bin だけでは、デフォルトのハンドラを使ったのか、指定したハンドラを使ったのか区別がつかないから、 int_vector_alloc.binが必要?
staticIdt.bin だけでは、割り込みベクタがIRQで発生したものなのか、例外・ソフトウェア割り込みで発生したものなのか区別がつかないから、irq_int_vector_map.binが必要?
isrList.bin
登録したい割り込み、例外(?)の情報。
isrList.binは、下記の genidt_header と supplied_entry[] から構成される。
[zephyr_base]/scripts/gen_idt/gen_idt.c
struct genidt_header_s {
        void *spurious_addr; // staticIdt.binの生成時に使用。isrList.binで指定しない割り込み用の割り込みハンドラのアドレス。
        // 割り込みベクタ番号8,10,11,12,13,14,17で使用。エラー番号をスタックにプッシュする。
        // _EXC_ERROR_CODE_FAULTS @ [zephyr_base]/arch/x86/include/idtEnt.h 参照
        void *spurious_no_error_addr; // 同上。上記以外の割り込みベクタ番号で使用。エラー内容をスタックにプッシュしない。
        unsigned int num_entries; // supplied_entry の数
};
struct genidt_entry_s {
        void *isr; // 割り込みハンドラのアドレス
        unsigned int irq; // UNSPECIFIED_IRQ でない時、IRQ番号
        unsigned int priority; // 割り込み優先度。この値をもとにマップする割り込みベクタ番号を決定する。
        // 0<= priority <= 13。irqがIRQ番号の時(=vector_idが UNSPECIFIED_INT_VECTOR の時)に使用。
        unsigned int vector_id; // UNSPECIFIED_INT_VECTOR でない時、割り込みベクタ番号
        unsigned int dpl; // Descriptor Privilege Level (プログラム中では0と仮定している。validate_dpl()参照)
};
static struct genidt_header_s  genidt_header;
static struct genidt_entry_s   supplied_entry[MAX_NUM_VECTORS];
staticIdt.bin
generate_idt()@[zephyr_base]/scripts/gen_idt/gen_idt.c
unsigned long long idt_entry の配列(割り込みベクタ番号順)
//  _IdtEntCreate() @ arch/x86/include/idtEnt.h で生成する
idt_entryの詳細は、Interrupt Descriptor Table - OSDev Wiki の IDT entry を参照。
isrList.bin内のsupplied_entry[].isr、supplied_entry[].dpl をもとに idt_entry を生成する。
int_vector_alloc.bin
generate_interrupt_vector_bitmap()@[zephyr_base]/scripts/gen_idt/gen_idt.c
unsigned int interrupt_vector_bitmap[num_elements];
// num_elemsents = 8; (割り込みベクタ数+31)/32
// 各ビットが、割り込みハンドラ(?)が割り当てられたかどうかを示す。ビット値が0の時、割り当てられたとする。
// interrupt_vector_bitmap[0]の0ビット目が0の場合、割り込み番号0が割り当てらたことを意味する。
// この配列を int_vector_alloc.bin に書き込む
irq_int_vector_map.bin
外部割り込み(IRQ:Interrupt ReQuest)を割り込みベクタに割り当てた(マップした)結果のファイル。

マップの方法:
割り込みベクタ番号は、supplied_entry[].vector_id をもとに、IRQより先に割り当てる。
priority 0 の IRQ は、割り込みベクタ番号 0〜15 の中で未割当の番号に割り当てる。
priority 1 の IRQ は、割り込みベクタ番号 16〜32 の中で未割当の番号に割り当てる。
...
priority 13 の IRQ は、割り込みベクタ番号 224〜239 の中で未割当の番号に割り当てる。
未割当の番号がない場合、エラーとなり、gen_idt は終了する。
generate_interrupt_vector_bitmap()@[zephyr_base]/scripts/gen_idt/gen_idt.c
uint8_t  map_irq_to_vector_id[MAX_IRQS]
// map_irq_to_vector_id[IRQ番号] = 割り込みベクタ番号
// この配列を irq_int_vector_map.bin に書き込む
$(GENIDT)
[zephyr_base]/Makefile
GENIDT  = scripts/gen_idt/gen_idt
$(CONFIG_IDT_NUM_VECTORS)
[zephyr_base]/samples/hello_world/microkernel/outdir/.config
CONFIG_IDT_NUM_VECTORS=256
$(CONFIG_MAX_IRQ_LINES)
[zephyr_base]/samples/hello_world/microkernel/outdir/.config
CONFIG_MAX_IRQ_LINES=128

③ $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) --rename-section .data=staticIdt staticIdt.bin staticIdt.o

/Volumes/CrossToolNG/x-tools/i586-pc-elf/bin/i586-pc-elf-objcopy -I binary -B i386 -O elf32-i386 --rename-section .data=staticIdt staticIdt.bin staticIdt.o 
入力: staticIdt.bin
出力: staticIdt.o
staticIdt.bin(バイナリファイル)の.dataセクション(データ全体?)をstaticIdtにリネームしてstaticIdt.o(elf32-i386形式)に出力する。
$(KERNEL_ELF_NAME) ターゲットで使用し、zephyr.elf へリンクする。
objcopy --help
i586-pc-elf-objcopy [option(s)] in-file [out-file]
  -I --input-target <bfdname>      Assume input file is in format <bfdname>
  -B --binary-architecture <arch>  Set output arch, when input is arch-less
  -O --output-target <bfdname>     Create an output file in format <bfdname>
     --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>

④ $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) --rename-section .data=int_vector_alloc int_vector_alloc.bin int_vector_alloc.o

/Volumes/CrossToolNG/x-tools/i586-pc-elf/bin/i586-pc-elf-objcopy -I binary -B i386 -O elf32-i386 --rename-section .data=int_vector_alloc int_vector_alloc.bin int_vector_alloc.o 
入力: int_vector_alloc.bin
出力: int_vector_alloc.o
int_vector_alloc.bin(バイナリファイル)の.dataセクション(データ全体?)をint_vector_allocにリネームしてint_vector_alloc.o(elf32-i386形式)に出力する。
$(KERNEL_ELF_NAME) ターゲットで使用し、zephyr.elf へリンクする。
objcopy --helpは上記を参照。

⑤ $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) --rename-section .data=irq_int_vector_map irq_int_vector_map.bin irq_int_vector_map.o

/Volumes/CrossToolNG/x-tools/i586-pc-elf/bin/i586-pc-elf-objcopy -I binary -B i386 -O elf32-i386 --rename-section .data=irq_int_vector_map irq_int_vector_map.bin irq_int_vector_map.o 
入力: irq_int_vector_map.bin
出力: irq_int_vector_map.o
irq_int_vector_map.bin(バイナリファイル)の.dataセクション(データ全体?)をirq_int_vector_mapにリネームしてirq_int_vector_map.o(elf32-i386形式)に出力する。
$(KERNEL_ELF_NAME) ターゲットで使用し、zephyr.elf へリンクする。
objcopy --helpは上記を参照。

⑥ rm staticIdt.bin irq_int_vector_map.bin int_vector_alloc.bin isrList.bin

rm staticIdt.bin irq_int_vector_map.bin int_vector_alloc.bin isrList.bin
不要になったstaticIdt.bin、irq_int_vector_map.bin、int_vector_alloc.bin isrList.binを削除する。

コメント

このブログの人気の投稿

Initial run-length encoding@bzip2を読んでみた

Wikipediaのbzip2圧縮アルゴリズムの一部を読んだので意訳して紹介します。 参考にしたソースコードは bzip2-1.0.6 です。 Wikipedia https://en.wikipedia.org/wiki/Bzip2#Initial_run-length_encoding bzip2 ソースコード https://github.com/junkawa/bzip2/tree/master/bzip2-1.0.6 概要 bzip2では、入力データを読み込んだ時( copy_input_until_stop()@bzlib.c → ADD_CHAR_TO_BLOCK() → add_pair_to_block() ) に ランレングス符号化 を行う。 Wikipedia Any sequence of 4 to 255 consecutive duplicate symbols is replaced by the first four symbols and a repeat length between 0 and 251.   4〜255回、同じシンボルが連続した場合、「最初の4シンボル+残りの繰り返し回数」に置き換わる。 Thus the sequence "AAAAAAABBBBCCCD" is replaced with "AAAA\3BBBB\0CCCD", where "\3" and "\0" represent byte values 3 and 0 respectively.  "AAAAAAABBBBCCCD"は、"AAAA\3BBBB\0CCCD"に置き換わる。 AAAAAAA (Aが7回)は、最初の4シンボル(AAAA) + 残りの繰り返し回数(3)となる。 BBBB (Bが4回)は、最初の4シンボル(BBBB) + 残りの繰り返し回数(0)となる。 C,Dは連続回数が4回に達しないのでそのままとなる。 ここでは分かりやすさのため、A,B,Cというシンボルを使っているが、実際のbzip2では1シンボルは1バイト(0〜255の値)。 したがって、シンボル7...

Zephyr build (4)

この記事で関係するターゲット $(TMP_ELF) ターゲット このターゲットは、アーキテクチャに関係なく実行される(x86依存ではない)。 [zephyr_base]/Makefile $(TMP_ELF): $(zephyr-deps) $(KBUILD_ZEPHYR_APP) linker.cmd $(KERNEL_NAME).lnk $(Q)$(CC) -T linker.cmd @$(KERNEL_NAME).lnk -o $@ $(TMP_ELF) 前の記事 参照。 $(zephyr-deps) TODO 後で調べる $(KBUILD_ZEPHYR_APP) 未定義 $(KERNEL_NAME).lnk zephyr.lnk $(KERNEL_NAME) については、 前の記事 参照。 $(Q)$(CC) -T linker.cmd @$(KERNEL_NAME).lnk -o $@ /Volumes/CrossToolNG/x-tools/i586-pc-elf/bin/i586-pc-elf-gcc -T linker.cmd @zephyr.lnk -o .tmp_zephyr.prebuilt リンカスクリプト (linker.cmd)、リンカオプション(zephyr.lnk)を使い、.tmp_zephyr.prebuilt を生成する。 linker.cmd [zephyr_base]/samples/hello_world/microkernel/outdir/linker.cmd 次の記事 参照 zephyr.lnk [zephyr_base]/Makefile 次の記事 参照

Zephyr build (2)

この記事で関係するターゲット qemu ターゲット [zephyr_base]/Makefile qemu: zephyr (省略) 詳細は 前の記事 参照。 zephyrターゲット [zephyr_base]/Makefile zephyr: $(zephyr-deps) $(KERNEL_BIN_NAME) $(zephyr-deps) [zephyr_base]/Makefile $(zephyr-deps) := $(KBUILD_LDS) $(KBUILD_ZEPHYR_MAIN) TODO 後で調べる $(KERNEL_BIN_NAME) zephyr.bin [zephyr_base]/samples/hello_world/microkernel/outdir/.config CONFIG_KERNEL_BIN_NAME="zephyr" TODO .config の生成方法(ct-ng makemenuconfigがベース?)、.config の Makefile中のinlcude箇所。 [zephyr_base]/Makefile KERNEL_NAME = $(subst $(DQUOTE),,$(CONFIG_KERNEL_BIN_NAME)) KERNEL_BIN_NAME = $(KERNEL_NAME).bin $(KERNEL_BIN_NAME) ターゲット [zephyr_base]/Makefile ifeq ($(ARCH),x86) $(KERNEL_ELF_NAME): staticIdt.o final-linker.cmd $(call cmd,lnk_elf) @$(WARN_ABOUT_ASSERT) else $(KERNEL_ELF_NAME): $(TMP_ELF) @cp $(TMP_ELF) $(KERNEL_ELF_NAME) @$(WARN_ABOUT_ASSERT) endif 今回は、ARCHがx86の場合を調べる。 staticIdt.o 次の記事 参照 final-linker.cmd TODO 調査 $(KERNEL_ELF_NAME) zephyr.elf [zephy...