libinstaller: Use SOURCE_DATE_EPOCH for synthesized modification time stamps
[syslinux.git] / com32 / modules / sdi.c
blobe57ad4a3239a6d429bfc107b9fba40f1637156c7
1 /* ----------------------------------------------------------------------- *
3 * Copyright 2008 H. Peter Anvin - All Rights Reserved
4 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
9 * Boston MA 02110-1301, USA; either version 2 of the License, or
10 * (at your option) any later version; incorporated herein by reference.
12 * ----------------------------------------------------------------------- */
15 * sdi.c
17 * Loader for the Microsoft System Deployment Image (SDI) format.
18 * Based on a historical patch by Remi Lefevre.
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <inttypes.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <minmax.h>
29 #include <sys/stat.h>
30 #include <console.h>
31 #include <dprintf.h>
33 #include <syslinux/loadfile.h>
34 #include <syslinux/movebits.h>
35 #include <syslinux/bootrm.h>
37 typedef uint8_t guid_t[16];
39 struct SDIHeader {
40 uint32_t Signature;
41 char Version[4];
42 uint64_t MDBtype;
43 uint64_t BootCodeOffset;
44 uint64_t BootCodeSize;
45 uint64_t VendorID;
46 uint64_t DeviceID;
47 guid_t DeviceModel;
48 uint64_t DeviceRole;
49 uint64_t Reserved1;
50 guid_t RuntimeGUID;
51 uint64_t RuntimeOEMrev;
52 uint64_t Reserved2;
53 uint64_t PageAlignment; /* BLOB alignment value in pages */
54 uint64_t Reserved3[48];
55 uint64_t Checksum;
58 #define SDI_LOAD_ADDR (16 << 20) /* 16 MB */
59 #define SDI_SIGNATURE ('$' + ('S' << 8) + ('D' << 16) + ('I' << 24))
61 static inline void error(const char *msg)
63 fputs(msg, stderr);
66 static int boot_sdi(void *ptr, size_t len)
68 const struct SDIHeader *hdr = ptr;
69 struct syslinux_memmap *mmap = NULL, *amap = NULL;
70 struct syslinux_rm_regs regs;
71 struct syslinux_movelist *ml = NULL;
73 /* **** Basic sanity checking **** */
74 if (hdr->Signature != SDI_SIGNATURE) {
75 fputs("No $SDI signature in file\n", stdout);
76 goto bail;
78 if (memcmp(hdr->Version, "0001", 4)) {
79 int i;
80 fputs("Warning: unknown SDI version: ", stdout);
81 for (i = 0; i < 4; i++)
82 putchar(hdr->Version[i]);
83 putchar('\n');
84 /* Then try anyway... */
87 /* **** Setup **** */
88 mmap = syslinux_memory_map();
89 amap = syslinux_dup_memmap(mmap);
90 if (!mmap || !amap)
91 goto bail;
93 /* **** Map the BOOT BLOB to 0x7c00 **** */
94 if (!hdr->BootCodeOffset) {
95 fputs("No BOOT BLOB in image\n", stdout);
96 goto bail;
98 if (!hdr->BootCodeSize) {
99 fputs("BOOT BLOB is empty\n", stdout);
100 goto bail;
102 if (len < hdr->BootCodeOffset + hdr->BootCodeSize) {
103 fputs("BOOT BLOB extends beyond file\n", stdout);
104 goto bail;
107 if (syslinux_memmap_type(amap, 0x7c00, hdr->BootCodeSize) != SMT_FREE) {
108 fputs("BOOT BLOB too large for memory\n", stdout);
109 goto bail;
111 if (syslinux_add_memmap(&amap, 0x7c00, hdr->BootCodeSize, SMT_ALLOC))
112 goto bail;
113 if (syslinux_add_movelist(&ml, 0x7c00, (addr_t) ptr + hdr->BootCodeOffset,
114 hdr->BootCodeSize))
115 goto bail;
117 /* **** Map the entire image to SDI_LOAD_ADDR **** */
118 if (syslinux_memmap_type(amap, SDI_LOAD_ADDR, len) != SMT_FREE) {
119 fputs("Image too large for memory\n", stdout);
120 goto bail;
122 if (syslinux_add_memmap(&amap, SDI_LOAD_ADDR, len, SMT_ALLOC))
123 goto bail;
124 if (syslinux_add_movelist(&ml, SDI_LOAD_ADDR, (addr_t) ptr, len))
125 goto bail;
127 /* **** Set up registers **** */
128 memset(&regs, 0, sizeof regs);
129 regs.ip = 0x7c00;
130 regs.esp.l = 0x7c00;
131 regs.edx.l = SDI_LOAD_ADDR | 0x41;
133 fputs("Booting...\n", stdout);
134 syslinux_shuffle_boot_rm(ml, mmap, 0, &regs);
136 bail:
137 syslinux_free_memmap(amap);
138 syslinux_free_memmap(mmap);
139 syslinux_free_movelist(ml);
140 return -1;
144 * Check that the sum of all bytes from first 512 bytes (SDI header)
145 * is 0 modulo 256.
147 int has_valid_header(unsigned char *header)
149 unsigned char checksum;
150 unsigned int i;
152 checksum = 0;
153 for (i = 0; i < sizeof(struct SDIHeader); i++)
154 checksum += header[i];
155 return (!checksum);
158 int main(int argc, char *argv[])
160 void *data;
161 size_t data_len;
163 if (argc != 2) {
164 error("Usage: sdi.c32 sdi_file\n");
165 return 1;
168 fputs("Loading ", stdout);
169 fputs(argv[1], stdout);
170 fputs("... ", stdout);
171 if (zloadfile(argv[1], &data, &data_len)) {
172 error("failed!\n");
173 return 1;
175 fputs("ok\n", stdout);
177 if (!has_valid_header(data)) {
178 error("SDI header is corrupted\n");
179 return 1;
182 boot_sdi(data, data_len);
183 error("Invalid SDI file or insufficient memory\n");
184 return 1;