]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - wimboot/wimboot-2.7.3/src/efifile.c
1.1.07 release
[Ventoy.git] / wimboot / wimboot-2.7.3 / src / efifile.c
1 /*
2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 /**
21 * @file
22 *
23 * EFI file system access
24 *
25 */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <wchar.h>
31 #include "wimboot.h"
32 #include "vdisk.h"
33 #include "cmdline.h"
34 #include "wimpatch.h"
35 #include "wimfile.h"
36 #include "efi.h"
37 #include "efifile.h"
38
39 /** bootmgfw.efi path within WIM */
40 static const wchar_t bootmgfw_path[] = L"\\Windows\\Boot\\EFI\\bootmgfw.efi";
41
42 /** Other paths within WIM */
43 static const wchar_t *efi_wim_paths[] = {
44 L"\\Windows\\Boot\\DVD\\EFI\\boot.sdi",
45 L"\\Windows\\Boot\\DVD\\EFI\\BCD",
46 L"\\Windows\\Boot\\Fonts\\segmono_boot.ttf",
47 L"\\Windows\\Boot\\Fonts\\segoen_slboot.ttf",
48 L"\\Windows\\Boot\\Fonts\\segoe_slboot.ttf",
49 L"\\Windows\\Boot\\Fonts\\wgl4_boot.ttf",
50 L"\\sms\\boot\\boot.sdi",
51 NULL
52 };
53
54 /** bootmgfw.efi file */
55 struct vdisk_file *bootmgfw;
56
57 /**
58 * Get architecture-specific boot filename
59 *
60 * @ret bootarch Architecture-specific boot filename
61 */
62 static const CHAR16 * efi_bootarch ( void ) {
63 static const CHAR16 bootarch_full[] = EFI_REMOVABLE_MEDIA_FILE_NAME;
64 const CHAR16 *tmp;
65 const CHAR16 *bootarch = bootarch_full;
66
67 for ( tmp = bootarch_full ; *tmp ; tmp++ ) {
68 if ( *tmp == L'\\' )
69 bootarch = ( tmp + 1 );
70 }
71 return bootarch;
72 }
73
74 /**
75 * Read from EFI file
76 *
77 * @v vfile Virtual file
78 * @v data Data buffer
79 * @v offset Offset
80 * @v len Length
81 */
82 static void efi_read_file ( struct vdisk_file *vfile, void *data,
83 size_t offset, size_t len ) {
84 #if 0
85 EFI_FILE_PROTOCOL *file = vfile->opaque;
86 UINTN size = len;
87 EFI_STATUS efirc;
88
89 /* Set file position */
90 if ( ( efirc = file->SetPosition ( file, offset ) ) != 0 ) {
91 die ( "Could not set file position: %#lx\n",
92 ( ( unsigned long ) efirc ) );
93 }
94
95 /* Read from file */
96 if ( ( efirc = file->Read ( file, &size, data ) ) != 0 ) {
97 die ( "Could not read from file: %#lx\n",
98 ( ( unsigned long ) efirc ) );
99 }
100 #endif /* #if 0 */
101
102 (void)vfile;
103
104 pfventoy_file_read((const char *)vfile->opaque, (int)offset, (int)len, data);
105 }
106
107 /**
108 * Patch BCD file
109 *
110 * @v vfile Virtual file
111 * @v data Data buffer
112 * @v offset Offset
113 * @v len Length
114 */
115 static void efi_patch_bcd ( struct vdisk_file *vfile __unused, void *data,
116 size_t offset, size_t len ) {
117 static const wchar_t search[] = L".exe";
118 static const wchar_t replace[] = L".efi";
119 size_t i;
120
121 /* Do nothing if BCD patching is disabled */
122 if ( cmdline_rawbcd )
123 return;
124
125 /* Patch any occurrences of ".exe" to ".efi". In the common
126 * simple cases, this allows the same BCD file to be used for
127 * both BIOS and UEFI systems.
128 */
129 for ( i = 0 ; ( i + sizeof ( search ) ) < len ; i++ ) {
130 if ( wcscasecmp ( ( data + i ), search ) == 0 ) {
131 memcpy ( ( data + i ), replace, sizeof ( replace ) );
132 DBG ( "...patched BCD at %#zx: \"%ls\" to \"%ls\"\n",
133 ( offset + i ), search, replace );
134 }
135 }
136 }
137
138 /**
139 * Extract files from EFI file system
140 *
141 * @v handle Device handle
142 */
143 void efi_extract ( EFI_HANDLE handle ) {
144 struct vdisk_file *wim = NULL;
145 struct vdisk_file *vfile;
146 CHAR16 wname[64];
147 int i, j, k;
148 char *pos;
149 size_t len = 0;
150
151 (void)handle;
152
153 /* Read root directory */
154 for (i = 0; i < cmdline_vf_num; i++) {
155 pos = strchr(cmdline_vf_path[i], ':');
156
157 *pos = 0;
158 k = (int)strlen(cmdline_vf_path[i]);
159
160 memset(wname, 0, sizeof(wname));
161 for (j = 0; j < k; j++)
162 {
163 wname[j] = cmdline_vf_path[i][j];
164 }
165
166 len = pfventoy_file_size(pos + 1);
167 vfile = vdisk_add_file (cmdline_vf_path[i], pos + 1, len, efi_read_file);
168
169 /* Check for special-case files */
170 if ( ( wcscasecmp ( wname, efi_bootarch() ) == 0 ) ||
171 ( wcscasecmp ( wname, L"bootmgfw.efi" ) == 0 ) ) {
172 DBG ( "...found bootmgfw.efi file %ls\n", wname );
173 bootmgfw = vfile;
174 } else if ( wcscasecmp ( wname, L"BCD" ) == 0 ) {
175 DBG ( "...found BCD\n" );
176 vdisk_patch_file ( vfile, efi_patch_bcd );
177 } else if ( wcscasecmp ( ( wname + ( wcslen ( wname ) - 4 ) ),
178 L".wim" ) == 0 ) {
179 DBG ( "...found WIM file %ls\n", wname );
180 wim = vfile;
181 }
182 }
183
184 /* Process WIM image */
185 if ( wim ) {
186 vdisk_patch_file ( wim, patch_wim );
187 if ( ( ! bootmgfw ) &&
188 ( bootmgfw = wim_add_file ( wim, cmdline_index,
189 bootmgfw_path,
190 efi_bootarch() ) ) ) {
191 DBG ( "...extracted %ls\n", bootmgfw_path );
192 }
193 wim_add_files ( wim, cmdline_index, efi_wim_paths );
194 }
195
196 /* Check that we have a boot file */
197 if ( ! bootmgfw ) {
198 die ( "FATAL: no %ls or bootmgfw.efi found\n",
199 efi_bootarch() );
200 }
201 }