Adding upstream version 4.00~pre61+dfsg.
[syslinux-debian/hramrach.git] / com32 / modules / sdi.c
blobfbca6a5504931073db5d8e8b05a479943223fa59
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>
32 #include <syslinux/loadfile.h>
33 #include <syslinux/movebits.h>
34 #include <syslinux/bootrm.h>
36 #define DEBUG 0
37 #if DEBUG
38 # define dprintf printf
39 #else
40 # define dprintf(f, ...) ((void)0)
41 #endif
43 typedef uint8_t guid_t[16];
45 struct SDIHeader {
46 uint32_t Signature;
47 char Version[4];
48 uint64_t MDBtype;
49 uint64_t BootCodeOffset;
50 uint64_t BootCodeSize;
51 uint64_t VendorID;
52 uint64_t DeviceID;
53 guid_t DeviceModel;
54 uint64_t DeviceRole;
55 uint64_t Reserved1;
56 guid_t RuntimeGUID;
57 uint64_t RuntimeOEMrev;
58 uint64_t Reserved2;
59 uint64_t PageAlignment; /* BLOB alignment value in pages */
60 uint64_t Reserved3[48];
61 uint64_t Checksum;
64 #define SDI_LOAD_ADDR (16 << 20) /* 16 MB */
65 #define SDI_SIGNATURE ('$' + ('S' << 8) + ('D' << 16) + ('I' << 24))
67 static inline void error(const char *msg)
69 fputs(msg, stderr);
72 static int boot_sdi(void *ptr, size_t len)
74 const struct SDIHeader *hdr = ptr;
75 struct syslinux_memmap *mmap = NULL, *amap = NULL;
76 struct syslinux_rm_regs regs;
77 struct syslinux_movelist *ml = NULL;
79 /* **** Basic sanity checking **** */
80 if (hdr->Signature != SDI_SIGNATURE) {
81 fputs("No $SDI signature in file\n", stdout);
82 goto bail;
84 if (memcmp(hdr->Version, "0001", 4)) {
85 int i;
86 fputs("Warning: unknown SDI version: ", stdout);
87 for (i = 0; i < 4; i++)
88 putchar(hdr->Version[i]);
89 putchar('\n');
90 /* Then try anyway... */
93 /* **** Setup **** */
94 mmap = syslinux_memory_map();
95 amap = syslinux_dup_memmap(mmap);
96 if (!mmap || !amap)
97 goto bail;
99 /* **** Map the BOOT BLOB to 0x7c00 **** */
100 if (!hdr->BootCodeOffset) {
101 fputs("No BOOT BLOB in image\n", stdout);
102 goto bail;
104 if (!hdr->BootCodeSize) {
105 fputs("BOOT BLOB is empty\n", stdout);
106 goto bail;
108 if (len < hdr->BootCodeOffset + hdr->BootCodeSize) {
109 fputs("BOOT BLOB extends beyond file\n", stdout);
110 goto bail;
113 if (syslinux_memmap_type(amap, 0x7c00, hdr->BootCodeSize) != SMT_FREE) {
114 fputs("BOOT BLOB too large for memory\n", stdout);
115 goto bail;
117 if (syslinux_add_memmap(&amap, 0x7c00, hdr->BootCodeSize, SMT_ALLOC))
118 goto bail;
119 if (syslinux_add_movelist(&ml, 0x7c00, (addr_t) ptr + hdr->BootCodeOffset,
120 hdr->BootCodeSize))
121 goto bail;
123 /* **** Map the entire image to SDI_LOAD_ADDR **** */
124 if (syslinux_memmap_type(amap, SDI_LOAD_ADDR, len) != SMT_FREE) {
125 fputs("Image too large for memory\n", stdout);
126 goto bail;
128 if (syslinux_add_memmap(&amap, SDI_LOAD_ADDR, len, SMT_ALLOC))
129 goto bail;
130 if (syslinux_add_movelist(&ml, SDI_LOAD_ADDR, (addr_t) ptr, len))
131 goto bail;
133 /* **** Set up registers **** */
134 memset(&regs, 0, sizeof regs);
135 regs.ip = 0x7c00;
136 regs.esp.l = 0x7c00;
137 regs.edx.l = SDI_LOAD_ADDR | 0x41;
139 fputs("Booting...\n", stdout);
140 syslinux_shuffle_boot_rm(ml, mmap, 0, &regs);
142 bail:
143 syslinux_free_memmap(amap);
144 syslinux_free_memmap(mmap);
145 syslinux_free_movelist(ml);
146 return -1;
150 * Check that the sum of all bytes from first 512 bytes (SDI header)
151 * is 0 modulo 256.
153 int has_valid_header(unsigned char *header)
155 unsigned char checksum;
156 unsigned int i;
158 checksum = 0;
159 for (i = 0; i < sizeof(struct SDIHeader); i++)
160 checksum += header[i];
161 return (!checksum);
164 int main(int argc, char *argv[])
166 void *data;
167 size_t data_len;
169 openconsole(&dev_null_r, &dev_stdcon_w);
171 if (argc != 2) {
172 error("Usage: sdi.c32 sdi_file\n");
173 return 1;
176 fputs("Loading ", stdout);
177 fputs(argv[1], stdout);
178 fputs("... ", stdout);
179 if (zloadfile(argv[1], &data, &data_len)) {
180 error("failed!\n");
181 return 1;
183 fputs("ok\n", stdout);
185 if (!has_valid_header(data)) {
186 error("SDI header is corrupted\n");
187 return 1;
190 boot_sdi(data, data_len);
191 error("Invalid SDI file or insufficient memory\n");
192 return 1;