summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/libopenbios/elf_info.c
blob: f7febef9d77de9fdbf8004169de777f1c5e3c21d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Support for ELF Boot Proposal as a boot image */
#include "config.h"
#include "arch/common/elf_boot.h"
#include "libopenbios/sys_info.h"
#include "asm/io.h"
#include "libopenbios/ipchecksum.h"
#include "openbios-version.h"
#define printf printk
#define debug  printk

/* ELF image notes provide information to the loader who boots us */

/* This compiles and generates correct PT_NOTE segment for me.
 * If it doesn't, use assembly version below. */

struct elf_image_note {
    Elf_Nhdr hdr0;
    char name0[sizeof(ELF_NOTE_BOOT)];
    char prog_name[sizeof(PROGRAM_NAME)];

    Elf_Nhdr hdr1;
    char name1[sizeof(ELF_NOTE_BOOT)];
    char version[sizeof(OPENBIOS_VERSION_STR)];

    Elf_Nhdr hdr2;
    char name2[sizeof(ELF_NOTE_BOOT)];
    unsigned short checksum;
};

const struct elf_image_note elf_image_notes
	__attribute__ ((section (".note.ELFBoot"))) =
{
    .hdr0 = {
	.n_namesz = sizeof(ELF_NOTE_BOOT),
	.n_descsz = sizeof(PROGRAM_NAME),
	.n_type = EIN_PROGRAM_NAME,
    },
    .name0 = ELF_NOTE_BOOT,
    .prog_name = PROGRAM_NAME,

    .hdr1 = {
	.n_namesz = sizeof(ELF_NOTE_BOOT),
        .n_descsz = sizeof(OPENBIOS_VERSION_STR),
	.n_type = EIN_PROGRAM_VERSION,
    },
    .name1 = ELF_NOTE_BOOT,
    .version = OPENBIOS_VERSION_STR,

    .hdr2 = {
	.n_namesz = sizeof(ELF_NOTE_BOOT),
	.n_descsz = sizeof(unsigned short),
	.n_type = EIN_PROGRAM_CHECKSUM,
    },
    .name2 = ELF_NOTE_BOOT,
    .checksum = 0, /* to be computed by external tool */
};

/* This is refered by other files */
const char *program_name = elf_image_notes.prog_name;
const char *program_version = elf_image_notes.version;

#if 0

	/* This tells the linker to make a PT_NOTE segment.
	 * If the section is named just ".note", it will be
	 * mixed up with useless .version notes generated by GCC.
	 */
	.section ".note.ELFBoot", "a"

	.align 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_NAME
1:	.asciz "ELFBoot"
2:	.align 4
3:	.asciz PROGRAM_NAME
4:

	.align 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_VERSION
1:	.asciz "ELFBoot"
2:	.align 4
3:      .asciz OPENBIOS_VERSION_STR
4:

	.align 4
	.int 2f - 1f
	.int 4f - 3f
	.int EIN_PROGRAM_CHECKSUM
1:	.asciz "ELFBoot"
2:	.align 4
3:	.short 0
4:
#endif

/* Collect information from the ELF bootloader
 * Note that we have to copy them to our own memory,
 * otherwise they might be overwritten afterward. */
void collect_elfboot_info(struct sys_info *info)
{
    Elf_Bhdr *hdr = NULL;
    char *addr, *end;
    Elf_Nhdr *nhdr;
    char *desc;

    if (info->boot_type == ELF_BHDR_MAGIC)
	hdr = phys_to_virt(info->boot_data);
    else
	hdr = phys_to_virt(info->boot_arg);

    if (hdr->b_signature != ELF_BHDR_MAGIC)
	return;

    if (ipchksum(hdr, hdr->b_size) != 0) {
	printf("Broken ELF boot notes\n");
	return;
    }

    addr = (char *) (hdr + 1);
    end = addr + hdr->b_size;
    while (addr <  end) {
	nhdr = (Elf_Nhdr *) addr;
	addr += sizeof(Elf_Nhdr);
	addr += (nhdr->n_namesz + 3) & ~3;
	desc = addr;
	addr += (nhdr->n_descsz + 3) & ~3;

	if (nhdr->n_namesz == 0) {
	    /* Standard notes */
	    switch (nhdr->n_type) {
	    case EBN_FIRMWARE_TYPE:
		info->firmware = strdup(desc);
		break;
	    case EBN_BOOTLOADER_NAME:
		debug("Bootloader: %s\n", desc);
		break;
	    case EBN_BOOTLOADER_VERSION:
		debug("Version: %s\n", desc);
		break;
	    case EBN_COMMAND_LINE:
		info->command_line = strdup(desc);
		break;
	    case EBN_LOADED_IMAGE:
		debug("Image name: %s\n", desc);
		break;
	    }
	}
    }
}