Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
dadigang
Ventoy
Commits
93996cf7
Commit
93996cf7
authored
May 13, 2021
by
longpanda
Browse files
1. Optimization for WIMBOOT mode.
2. Add WIMBOOT for UEFI mode.
parent
ca62128f
Changes
120
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2991 additions
and
0 deletions
+2991
-0
wimboot/wimboot-2.7.3/src/lznt1.h
wimboot/wimboot-2.7.3/src/lznt1.h
+47
-0
wimboot/wimboot-2.7.3/src/lzx.c
wimboot/wimboot-2.7.3/src/lzx.c
+670
-0
wimboot/wimboot-2.7.3/src/lzx.h
wimboot/wimboot-2.7.3/src/lzx.h
+180
-0
wimboot/wimboot-2.7.3/src/main.c
wimboot/wimboot-2.7.3/src/main.c
+515
-0
wimboot/wimboot-2.7.3/src/memmap.c
wimboot/wimboot-2.7.3/src/memmap.c
+105
-0
wimboot/wimboot-2.7.3/src/memmap.h
wimboot/wimboot-2.7.3/src/memmap.h
+58
-0
wimboot/wimboot-2.7.3/src/paging.c
wimboot/wimboot-2.7.3/src/paging.c
+255
-0
wimboot/wimboot-2.7.3/src/paging.h
wimboot/wimboot-2.7.3/src/paging.h
+79
-0
wimboot/wimboot-2.7.3/src/pause.c
wimboot/wimboot-2.7.3/src/pause.c
+46
-0
wimboot/wimboot-2.7.3/src/pause.h
wimboot/wimboot-2.7.3/src/pause.h
+32
-0
wimboot/wimboot-2.7.3/src/peloader.c
wimboot/wimboot-2.7.3/src/peloader.c
+118
-0
wimboot/wimboot-2.7.3/src/peloader.h
wimboot/wimboot-2.7.3/src/peloader.h
+195
-0
wimboot/wimboot-2.7.3/src/rotate.h
wimboot/wimboot-2.7.3/src/rotate.h
+51
-0
wimboot/wimboot-2.7.3/src/script.lds
wimboot/wimboot-2.7.3/src/script.lds
+116
-0
wimboot/wimboot-2.7.3/src/sha1.c
wimboot/wimboot-2.7.3/src/sha1.c
+232
-0
wimboot/wimboot-2.7.3/src/sha1.h
wimboot/wimboot-2.7.3/src/sha1.h
+72
-0
wimboot/wimboot-2.7.3/src/stdarg.h
wimboot/wimboot-2.7.3/src/stdarg.h
+36
-0
wimboot/wimboot-2.7.3/src/stddef.h
wimboot/wimboot-2.7.3/src/stddef.h
+40
-0
wimboot/wimboot-2.7.3/src/stdint.h
wimboot/wimboot-2.7.3/src/stdint.h
+48
-0
wimboot/wimboot-2.7.3/src/stdio.c
wimboot/wimboot-2.7.3/src/stdio.c
+96
-0
No files found.
wimboot/wimboot-2.7.3/src/lznt1.h
0 → 100644
View file @
93996cf7
#ifndef _LZNT1_H
#define _LZNT1_H
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* LZNT1 decompression
*
*/
#include <stdint.h>
/** Extract LZNT1 block length */
#define LZNT1_BLOCK_LEN( header ) ( ( (header) & 0x0fff ) + 1 )
/** Determine if LZNT1 block is compressed */
#define LZNT1_BLOCK_COMPRESSED( header ) ( (header) & 0x8000 )
/** Extract LZNT1 compressed value length */
#define LZNT1_VALUE_LEN( tuple, split ) \
( ( (tuple) & ( ( 1 << (split) ) - 1 ) ) + 3 )
/** Extract LZNT1 compressed value offset */
#define LZNT1_VALUE_OFFSET( tuple, split ) ( ( (tuple) >> split ) + 1 )
extern
ssize_t
lznt1_decompress
(
const
void
*
data
,
size_t
len
,
void
*
buf
);
#endif
/* _LZNT1_H */
wimboot/wimboot-2.7.3/src/lzx.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* LZX decompression
*
* This algorithm is derived jointly from the document "[MS-PATCH]:
* LZX DELTA Compression and Decompression", available from
*
* http://msdn.microsoft.com/en-us/library/cc483133.aspx
*
* and from the file lzx-decompress.c in the wimlib source code.
*
*/
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "wimboot.h"
#include "huffman.h"
#include "lzx.h"
/** Base positions, indexed by position slot */
static
unsigned
int
lzx_position_base
[
LZX_POSITION_SLOTS
];
/**
* Attempt to accumulate bits from LZX bitstream
*
* @v lzx Decompressor
* @v bits Number of bits to accumulate
* @v norm_value Accumulated value (normalised to 16 bits)
*
* Note that there may not be sufficient accumulated bits in the
* bitstream; callers must check that sufficient bits are available
* before using the value.
*/
static
int
lzx_accumulate
(
struct
lzx
*
lzx
,
unsigned
int
bits
)
{
const
uint16_t
*
src16
;
/* Accumulate more bits if required */
if
(
(
lzx
->
bits
<
bits
)
&&
(
lzx
->
input
.
offset
<
lzx
->
input
.
len
)
)
{
src16
=
(
(
void
*
)
lzx
->
input
.
data
+
lzx
->
input
.
offset
);
lzx
->
input
.
offset
+=
sizeof
(
*
src16
);
lzx
->
accumulator
|=
(
*
src16
<<
(
16
-
lzx
->
bits
)
);
lzx
->
bits
+=
16
;
}
return
(
lzx
->
accumulator
>>
16
);
}
/**
* Consume accumulated bits from LZX bitstream
*
* @v lzx Decompressor
* @v bits Number of bits to consume
* @ret rc Return status code
*/
static
int
lzx_consume
(
struct
lzx
*
lzx
,
unsigned
int
bits
)
{
/* Fail if insufficient bits are available */
if
(
lzx
->
bits
<
bits
)
{
DBG
(
"LZX input overrun in %#zx/%#zx out %#zx)
\n
"
,
lzx
->
input
.
offset
,
lzx
->
input
.
len
,
lzx
->
output
.
offset
);
return
-
1
;
}
/* Consume bits */
lzx
->
accumulator
<<=
bits
;
lzx
->
bits
-=
bits
;
return
0
;
}
/**
* Get bits from LZX bitstream
*
* @v lzx Decompressor
* @v bits Number of bits to fetch
* @ret value Value, or negative error
*/
static
int
lzx_getbits
(
struct
lzx
*
lzx
,
unsigned
int
bits
)
{
int
norm_value
;
int
rc
;
/* Accumulate more bits if required */
norm_value
=
lzx_accumulate
(
lzx
,
bits
);
/* Consume bits */
if
(
(
rc
=
lzx_consume
(
lzx
,
bits
)
)
!=
0
)
return
rc
;
return
(
norm_value
>>
(
16
-
bits
)
);
}
/**
* Align LZX bitstream for byte access
*
* @v lzx Decompressor
* @v bits Minimum number of padding bits
* @ret rc Return status code
*/
static
int
lzx_align
(
struct
lzx
*
lzx
,
unsigned
int
bits
)
{
int
pad
;
/* Get padding bits */
pad
=
lzx_getbits
(
lzx
,
bits
);
if
(
pad
<
0
)
return
pad
;
/* Consume all accumulated bits */
lzx_consume
(
lzx
,
lzx
->
bits
);
return
0
;
}
/**
* Get bytes from LZX bitstream
*
* @v lzx Decompressor
* @v data Data buffer, or NULL
* @v len Length of data buffer
* @ret rc Return status code
*/
static
int
lzx_getbytes
(
struct
lzx
*
lzx
,
void
*
data
,
size_t
len
)
{
/* Sanity check */
if
(
(
lzx
->
input
.
offset
+
len
)
>
lzx
->
input
.
len
)
{
DBG
(
"LZX input overrun in %#zx/%#zx out %#zx)
\n
"
,
lzx
->
input
.
offset
,
lzx
->
input
.
len
,
lzx
->
output
.
offset
);
return
-
1
;
}
/* Copy data */
if
(
data
)
memcpy
(
data
,
(
lzx
->
input
.
data
+
lzx
->
input
.
offset
),
len
);
lzx
->
input
.
offset
+=
len
;
return
0
;
}
/**
* Decode LZX Huffman-coded symbol
*
* @v lzx Decompressor
* @v alphabet Huffman alphabet
* @ret raw Raw symbol, or negative error
*/
static
int
lzx_decode
(
struct
lzx
*
lzx
,
struct
huffman_alphabet
*
alphabet
)
{
struct
huffman_symbols
*
sym
;
int
huf
;
int
rc
;
/* Accumulate sufficient bits */
huf
=
lzx_accumulate
(
lzx
,
HUFFMAN_BITS
);
if
(
huf
<
0
)
return
huf
;
/* Decode symbol */
sym
=
huffman_sym
(
alphabet
,
huf
);
/* Consume bits */
if
(
(
rc
=
lzx_consume
(
lzx
,
huffman_len
(
sym
)
)
)
!=
0
)
return
rc
;
return
huffman_raw
(
sym
,
huf
);
}
/**
* Generate Huffman alphabet from raw length table
*
* @v lzx Decompressor
* @v count Number of symbols
* @v bits Length of each length (in bits)
* @v lengths Lengths table to fill in
* @v alphabet Huffman alphabet to fill in
* @ret rc Return status code
*/
static
int
lzx_raw_alphabet
(
struct
lzx
*
lzx
,
unsigned
int
count
,
unsigned
int
bits
,
uint8_t
*
lengths
,
struct
huffman_alphabet
*
alphabet
)
{
unsigned
int
i
;
int
len
;
int
rc
;
/* Read lengths */
for
(
i
=
0
;
i
<
count
;
i
++
)
{
len
=
lzx_getbits
(
lzx
,
bits
);
if
(
len
<
0
)
return
len
;
lengths
[
i
]
=
len
;
}
/* Generate Huffman alphabet */
if
(
(
rc
=
huffman_alphabet
(
alphabet
,
lengths
,
count
)
)
!=
0
)
return
rc
;
return
0
;
}
/**
* Generate pretree
*
* @v lzx Decompressor
* @v count Number of symbols
* @v lengths Lengths table to fill in
* @ret rc Return status code
*/
static
int
lzx_pretree
(
struct
lzx
*
lzx
,
unsigned
int
count
,
uint8_t
*
lengths
)
{
unsigned
int
i
;
unsigned
int
length
;
int
dup
=
0
;
int
code
;
int
rc
;
/* Generate pretree alphabet */
if
(
(
rc
=
lzx_raw_alphabet
(
lzx
,
LZX_PRETREE_CODES
,
LZX_PRETREE_BITS
,
lzx
->
pretree_lengths
,
&
lzx
->
pretree
)
)
!=
0
)
return
rc
;
/* Read lengths */
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
dup
)
{
/* Duplicate previous length */
lengths
[
i
]
=
lengths
[
i
-
1
];
dup
--
;
}
else
{
/* Get next code */
code
=
lzx_decode
(
lzx
,
&
lzx
->
pretree
);
if
(
code
<
0
)
return
code
;
/* Interpret code */
if
(
code
<=
16
)
{
length
=
(
(
lengths
[
i
]
-
code
+
17
)
%
17
);
}
else
if
(
code
==
17
)
{
length
=
0
;
dup
=
lzx_getbits
(
lzx
,
4
);
if
(
dup
<
0
)
return
dup
;
dup
+=
3
;
}
else
if
(
code
==
18
)
{
length
=
0
;
dup
=
lzx_getbits
(
lzx
,
5
);
if
(
dup
<
0
)
return
dup
;
dup
+=
19
;
}
else
if
(
code
==
19
)
{
length
=
0
;
dup
=
lzx_getbits
(
lzx
,
1
);
if
(
dup
<
0
)
return
dup
;
dup
+=
3
;
code
=
lzx_decode
(
lzx
,
&
lzx
->
pretree
);
if
(
code
<
0
)
return
code
;
length
=
(
(
lengths
[
i
]
-
code
+
17
)
%
17
);
}
else
{
DBG
(
"Unrecognised pretree code %d
\n
"
,
code
);
return
-
1
;
}
lengths
[
i
]
=
length
;
}
}
/* Sanity check */
if
(
dup
)
{
DBG
(
"Pretree duplicate overrun
\n
"
);
return
-
1
;
}
return
0
;
}
/**
* Generate aligned offset Huffman alphabet
*
* @v lzx Decompressor
* @ret rc Return status code
*/
static
int
lzx_alignoffset_alphabet
(
struct
lzx
*
lzx
)
{
int
rc
;
/* Generate aligned offset alphabet */
if
(
(
rc
=
lzx_raw_alphabet
(
lzx
,
LZX_ALIGNOFFSET_CODES
,
LZX_ALIGNOFFSET_BITS
,
lzx
->
alignoffset_lengths
,
&
lzx
->
alignoffset
)
)
!=
0
)
return
rc
;
return
0
;
}
/**
* Generate main Huffman alphabet
*
* @v lzx Decompressor
* @ret rc Return status code
*/
static
int
lzx_main_alphabet
(
struct
lzx
*
lzx
)
{
int
rc
;
/* Generate literal symbols pretree */
if
(
(
rc
=
lzx_pretree
(
lzx
,
LZX_MAIN_LIT_CODES
,
lzx
->
main_lengths
.
literals
)
)
!=
0
)
{
DBG
(
"Could not construct main literal pretree
\n
"
);
return
rc
;
}
/* Generate remaining symbols pretree */
if
(
(
rc
=
lzx_pretree
(
lzx
,
(
LZX_MAIN_CODES
-
LZX_MAIN_LIT_CODES
),
lzx
->
main_lengths
.
remainder
)
)
!=
0
)
{
DBG
(
"Could not construct main remainder pretree
\n
"
);
return
rc
;
}
/* Generate Huffman alphabet */
if
(
(
rc
=
huffman_alphabet
(
&
lzx
->
main
,
lzx
->
main_lengths
.
literals
,
LZX_MAIN_CODES
)
)
!=
0
)
{
DBG
(
"Could not generate main alphabet
\n
"
);
return
rc
;
}
return
0
;
}
/**
* Generate length Huffman alphabet
*
* @v lzx Decompressor
* @ret rc Return status code
*/
static
int
lzx_length_alphabet
(
struct
lzx
*
lzx
)
{
int
rc
;
/* Generate pretree */
if
(
(
rc
=
lzx_pretree
(
lzx
,
LZX_LENGTH_CODES
,
lzx
->
length_lengths
)
)
!=
0
)
{
DBG
(
"Could not generate length pretree
\n
"
);
return
rc
;
}
/* Generate Huffman alphabet */
if
(
(
rc
=
huffman_alphabet
(
&
lzx
->
length
,
lzx
->
length_lengths
,
LZX_LENGTH_CODES
)
)
!=
0
)
{
DBG
(
"Could not generate length alphabet
\n
"
);
return
rc
;
}
return
0
;
}
/**
* Process LZX block header
*
* @v lzx Decompressor
* @ret rc Return status code
*/
static
int
lzx_block_header
(
struct
lzx
*
lzx
)
{
size_t
block_len
;
int
block_type
;
int
default_len
;
int
len_high
;
int
len_low
;
int
rc
;
/* Get block type */
block_type
=
lzx_getbits
(
lzx
,
LZX_BLOCK_TYPE_BITS
);
if
(
block_type
<
0
)
return
block_type
;
lzx
->
block_type
=
block_type
;
/* Check block length */
default_len
=
lzx_getbits
(
lzx
,
1
);
if
(
default_len
<
0
)
return
default_len
;
if
(
default_len
)
{
block_len
=
LZX_DEFAULT_BLOCK_LEN
;
}
else
{
len_high
=
lzx_getbits
(
lzx
,
8
);
if
(
len_high
<
0
)
return
len_high
;
len_low
=
lzx_getbits
(
lzx
,
8
);
if
(
len_low
<
0
)
return
len_low
;
block_len
=
(
(
len_high
<<
8
)
|
len_low
);
}
lzx
->
output
.
threshold
=
(
lzx
->
output
.
offset
+
block_len
);
/* Handle block type */
switch
(
block_type
)
{
case
LZX_BLOCK_ALIGNOFFSET
:
/* Generated aligned offset alphabet */
if
(
(
rc
=
lzx_alignoffset_alphabet
(
lzx
)
)
!=
0
)
return
rc
;
/* Fall through */
case
LZX_BLOCK_VERBATIM
:
/* Generate main alphabet */
if
(
(
rc
=
lzx_main_alphabet
(
lzx
)
)
!=
0
)
return
rc
;
/* Generate lengths alphabet */
if
(
(
rc
=
lzx_length_alphabet
(
lzx
)
)
!=
0
)
return
rc
;
break
;
case
LZX_BLOCK_UNCOMPRESSED
:
/* Align input stream */
if
(
(
rc
=
lzx_align
(
lzx
,
1
)
)
!=
0
)
return
rc
;
/* Read new repeated offsets */
if
(
(
rc
=
lzx_getbytes
(
lzx
,
&
lzx
->
repeated_offset
,
sizeof
(
lzx
->
repeated_offset
)))
!=
0
)
return
rc
;
break
;
default:
DBG
(
"Unrecognised block type %d
\n
"
,
block_type
);
return
-
1
;
}
return
0
;
}
/**
* Process uncompressed data
*
* @v lzx Decompressor
* @ret rc Return status code
*/
static
int
lzx_uncompressed
(
struct
lzx
*
lzx
)
{
void
*
data
;
size_t
len
;
int
rc
;
/* Copy bytes */
data
=
(
lzx
->
output
.
data
?
(
lzx
->
output
.
data
+
lzx
->
output
.
offset
)
:
NULL
);
len
=
(
lzx
->
output
.
threshold
-
lzx
->
output
.
offset
);
if
(
(
rc
=
lzx_getbytes
(
lzx
,
data
,
len
)
)
!=
0
)
return
rc
;
/* Align input stream */
if
(
len
%
2
)
lzx
->
input
.
offset
++
;
return
0
;
}
/**
* Process an LZX token
*
* @v lzx Decompressor
* @ret rc Return status code
*
* Variable names are chosen to match the LZX specification
* pseudo-code.
*/
static
int
lzx_token
(
struct
lzx
*
lzx
)
{
unsigned
int
length_header
;
unsigned
int
position_slot
;
unsigned
int
offset_bits
;
unsigned
int
i
;
size_t
match_offset
;
size_t
match_length
;
int
verbatim_bits
;
int
aligned_bits
;
int
main
;
int
length
;
uint8_t
*
copy
;
/* Get main symelse*/
main
=
lzx_decode
(
lzx
,
&
lzx
->
main
);
if
(
main
<
0
)
return
main
;
/* Check for literals */
if
(
main
<
LZX_MAIN_LIT_CODES
)
{
if
(
lzx
->
output
.
data
)
lzx
->
output
.
data
[
lzx
->
output
.
offset
]
=
main
;
lzx
->
output
.
offset
++
;
return
0
;
}
main
-=
LZX_MAIN_LIT_CODES
;
/* Calculate the match length */
length_header
=
(
main
&
7
);
if
(
length_header
==
7
)
{
length
=
lzx_decode
(
lzx
,
&
lzx
->
length
);
if
(
length
<
0
)
return
length
;
}
else
{
length
=
0
;
}
match_length
=
(
length_header
+
2
+
length
);
/* Calculate the position slot */
position_slot
=
(
main
>>
3
);
if
(
position_slot
<
LZX_REPEATED_OFFSETS
)
{
/* Repeated offset */
match_offset
=
lzx
->
repeated_offset
[
position_slot
];
lzx
->
repeated_offset
[
position_slot
]
=
lzx
->
repeated_offset
[
0
];
lzx
->
repeated_offset
[
0
]
=
match_offset
;
}
else
{
/* Non-repeated offset */
offset_bits
=
lzx_footer_bits
(
position_slot
);
if
(
(
lzx
->
block_type
==
LZX_BLOCK_ALIGNOFFSET
)
&&
(
offset_bits
>=
3
)
)
{
verbatim_bits
=
lzx_getbits
(
lzx
,
(
offset_bits
-
3
));
if
(
verbatim_bits
<
0
)
return
verbatim_bits
;
verbatim_bits
<<=
3
;
aligned_bits
=
lzx_decode
(
lzx
,
&
lzx
->
alignoffset
);
if
(
aligned_bits
<
0
)
return
aligned_bits
;
}
else
{
verbatim_bits
=
lzx_getbits
(
lzx
,
offset_bits
);
if
(
verbatim_bits
<
0
)
return
verbatim_bits
;
aligned_bits
=
0
;
}
match_offset
=
(
lzx_position_base
[
position_slot
]
+
verbatim_bits
+
aligned_bits
-
2
);
/* Update repeated offset list */
for
(
i
=
(
LZX_REPEATED_OFFSETS
-
1
)
;
i
>
0
;
i
--
)
lzx
->
repeated_offset
[
i
]
=
lzx
->
repeated_offset
[
i
-
1
];
lzx
->
repeated_offset
[
0
]
=
match_offset
;
}
/* Copy data */
if
(
match_offset
>
lzx
->
output
.
offset
)
{
DBG
(
"LZX match underrun out %#zx offset %#zx len %#zx
\n
"
,
lzx
->
output
.
offset
,
match_offset
,
match_length
);
return
-
1
;
}
if
(
lzx
->
output
.
data
)
{
copy
=
&
lzx
->
output
.
data
[
lzx
->
output
.
offset
];
for
(
i
=
0
;
i
<
match_length
;
i
++
)
copy
[
i
]
=
copy
[
i
-
match_offset
];
}
lzx
->
output
.
offset
+=
match_length
;
return
0
;
}
/**
* Translate E8 jump addresses
*
* @v lzx Decompressor
*/
static
void
lzx_translate_jumps
(
struct
lzx
*
lzx
)
{
size_t
offset
;
int32_t
*
target
;
/* Sanity check */
if
(
lzx
->
output
.
offset
<
10
)
return
;
/* Scan for jump instructions */
for
(
offset
=
0
;
offset
<
(
lzx
->
output
.
offset
-
10
)
;
offset
++
)
{
/* Check for jump instruction */
if
(
lzx
->
output
.
data
[
offset
]
!=
0xe8
)
continue
;
/* Translate jump target */
target
=
(
(
int32_t
*
)
&
lzx
->
output
.
data
[
offset
+
1
]
);
if
(
*
target
>=
0
)
{
if
(
*
target
<
LZX_WIM_MAGIC_FILESIZE
)
*
target
-=
offset
;
}
else
{
if
(
*
target
>=
-
(
(
int32_t
)
offset
)
)
*
target
+=
LZX_WIM_MAGIC_FILESIZE
;
}
offset
+=
sizeof
(
*
target
);
}
}
/**
* Decompress LZX-compressed data
*
* @v data Compressed data
* @v len Length of compressed data
* @v buf Decompression buffer, or NULL
* @ret out_len Length of decompressed data, or negative error
*/
ssize_t
lzx_decompress
(
const
void
*
data
,
size_t
len
,
void
*
buf
)
{
struct
lzx
lzx
;
unsigned
int
i
;
int
rc
;
/* Sanity check */
if
(
len
%
2
)
{
DBG
(
"LZX cannot handle odd-length input data
\n
"
);
return
-
1
;
}
/* Initialise global state, if required */
if
(
!
lzx_position_base
[
LZX_POSITION_SLOTS
-
1
]
)
{
for
(
i
=
1
;
i
<
LZX_POSITION_SLOTS
;
i
++
)
{
lzx_position_base
[
i
]
=
(
lzx_position_base
[
i
-
1
]
+
(
1
<<
lzx_footer_bits
(
i
-
1
)
)
);
}
}
/* Initialise decompressor */
memset
(
&
lzx
,
0
,
sizeof
(
lzx
)
);
lzx
.
input
.
data
=
data
;
lzx
.
input
.
len
=
len
;
lzx
.
output
.
data
=
buf
;
for
(
i
=
0
;
i
<
LZX_REPEATED_OFFSETS
;
i
++
)
lzx
.
repeated_offset
[
i
]
=
1
;
/* Process blocks */
while
(
lzx
.
input
.
offset
<
lzx
.
input
.
len
)
{
/* Process block header */
if
(
(
rc
=
lzx_block_header
(
&
lzx
)
)
!=
0
)
return
rc
;
/* Process block contents */
if
(
lzx
.
block_type
==
LZX_BLOCK_UNCOMPRESSED
)
{
/* Copy uncompressed data */
if
(
(
rc
=
lzx_uncompressed
(
&
lzx
)
)
!=
0
)
return
rc
;
}
else
{
/* Process token stream */
while
(
lzx
.
output
.
offset
<
lzx
.
output
.
threshold
)
{
if
(
(
rc
=
lzx_token
(
&
lzx
)
)
!=
0
)
return
rc
;
}
}
}
/* Postprocess to undo E8 jump compression */
if
(
lzx
.
output
.
data
)
lzx_translate_jumps
(
&
lzx
);
return
lzx
.
output
.
offset
;
}
wimboot/wimboot-2.7.3/src/lzx.h
0 → 100644
View file @
93996cf7
#ifndef _LZX_H
#define _LZX_H
/*
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* LZX decompression
*
*/
#include <stdint.h>
#include "huffman.h"
/** Number of aligned offset codes */
#define LZX_ALIGNOFFSET_CODES 8
/** Aligned offset code length (in bits) */
#define LZX_ALIGNOFFSET_BITS 3
/** Number of pretree codes */
#define LZX_PRETREE_CODES 20
/** Pretree code length (in bits) */
#define LZX_PRETREE_BITS 4
/** Number of literal main codes */
#define LZX_MAIN_LIT_CODES 256
/** Number of position slots */
#define LZX_POSITION_SLOTS 30
/** Number of main codes */
#define LZX_MAIN_CODES ( LZX_MAIN_LIT_CODES + ( 8 * LZX_POSITION_SLOTS ) )
/** Number of length codes */
#define LZX_LENGTH_CODES 249
/** Block type length (in bits) */
#define LZX_BLOCK_TYPE_BITS 3
/** Default block length */
#define LZX_DEFAULT_BLOCK_LEN 32768
/** Number of repeated offsets */
#define LZX_REPEATED_OFFSETS 3
/** Don't ask */
#define LZX_WIM_MAGIC_FILESIZE 12000000
/** Block types */
enum
lzx_block_type
{
/** Verbatim block */
LZX_BLOCK_VERBATIM
=
1
,
/** Aligned offset block */
LZX_BLOCK_ALIGNOFFSET
=
2
,
/** Uncompressed block */
LZX_BLOCK_UNCOMPRESSED
=
3
,
};
/** An LZX input stream */
struct
lzx_input_stream
{
/** Data */
const
uint8_t
*
data
;
/** Length */
size_t
len
;
/** Offset within stream */
size_t
offset
;
};
/** An LZX output stream */
struct
lzx_output_stream
{
/** Data, or NULL */
uint8_t
*
data
;
/** Offset within stream */
size_t
offset
;
/** End of current block within stream */
size_t
threshold
;
};
/** LZX decompressor */
struct
lzx
{
/** Input stream */
struct
lzx_input_stream
input
;
/** Output stream */
struct
lzx_output_stream
output
;
/** Accumulator */
uint32_t
accumulator
;
/** Number of bits in accumulator */
unsigned
int
bits
;
/** Block type */
enum
lzx_block_type
block_type
;
/** Repeated offsets */
unsigned
int
repeated_offset
[
LZX_REPEATED_OFFSETS
];
/** Aligned offset Huffman alphabet */
struct
huffman_alphabet
alignoffset
;
/** Aligned offset raw symbols
*
* Must immediately follow the aligned offset Huffman
* alphabet.
*/
huffman_raw_symbol_t
alignoffset_raw
[
LZX_ALIGNOFFSET_CODES
];
/** Aligned offset code lengths */
uint8_t
alignoffset_lengths
[
LZX_ALIGNOFFSET_CODES
];
/** Pretree Huffman alphabet */
struct
huffman_alphabet
pretree
;
/** Pretree raw symbols
*
* Must immediately follow the pretree Huffman alphabet.
*/
huffman_raw_symbol_t
pretree_raw
[
LZX_PRETREE_CODES
];
/** Preetree code lengths */
uint8_t
pretree_lengths
[
LZX_PRETREE_CODES
];
/** Main Huffman alphabet */
struct
huffman_alphabet
main
;
/** Main raw symbols
*
* Must immediately follow the main Huffman alphabet.
*/
huffman_raw_symbol_t
main_raw
[
LZX_MAIN_CODES
];
/** Main code lengths */
struct
{
/** Literals */
uint8_t
literals
[
LZX_MAIN_LIT_CODES
];
/** Remaining symbols */
uint8_t
remainder
[
LZX_MAIN_CODES
-
LZX_MAIN_LIT_CODES
];
}
__attribute__
((
packed
))
main_lengths
;
/** Length Huffman alphabet */
struct
huffman_alphabet
length
;
/** Length raw symbols
*
* Must immediately follow the length Huffman alphabet.
*/
huffman_raw_symbol_t
length_raw
[
LZX_LENGTH_CODES
];
/** Length code lengths */
uint8_t
length_lengths
[
LZX_LENGTH_CODES
];
};
/**
* Calculate number of footer bits for a given position slot
*
* @v position_slot Position slot
* @ret footer_bits Number of footer bits
*/
static
inline
unsigned
int
lzx_footer_bits
(
unsigned
int
position_slot
)
{
if
(
position_slot
<
2
)
{
return
0
;
}
else
if
(
position_slot
<
38
)
{
return
(
(
position_slot
/
2
)
-
1
);
}
else
{
return
17
;
}
}
extern
ssize_t
lzx_decompress
(
const
void
*
data
,
size_t
len
,
void
*
buf
);
#endif
/* _LZX_H */
wimboot/wimboot-2.7.3/src/main.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Main entry point
*
*/
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include "wimboot.h"
#include "peloader.h"
#include "int13.h"
#include "vdisk.h"
#include "cpio.h"
#include "lznt1.h"
#include "xca.h"
#include "cmdline.h"
#include "wimpatch.h"
#include "wimfile.h"
#include "pause.h"
#include "paging.h"
#include "memmap.h"
/** Start of our image (defined by linker) */
extern
char
_start
[];
/** End of our image (defined by linker) */
extern
char
_end
[];
/** Command line */
char
*
cmdline
;
/** initrd */
void
*
initrd
;
/** Length of initrd */
size_t
initrd_len
;
/** bootmgr.exe path within WIM */
static
const
wchar_t
bootmgr_path
[]
=
L"
\\
Windows
\\
Boot
\\
PXE
\\
bootmgr.exe"
;
/** Other paths within WIM */
static
const
wchar_t
*
wim_paths
[]
=
{
L"
\\
Windows
\\
Boot
\\
DVD
\\
PCAT
\\
boot.sdi"
,
L"
\\
Windows
\\
Boot
\\
DVD
\\
PCAT
\\
BCD"
,
L"
\\
Windows
\\
Boot
\\
Fonts
\\
segmono_boot.ttf"
,
L"
\\
Windows
\\
Boot
\\
Fonts
\\
segoen_slboot.ttf"
,
L"
\\
Windows
\\
Boot
\\
Fonts
\\
segoe_slboot.ttf"
,
L"
\\
Windows
\\
Boot
\\
Fonts
\\
wgl4_boot.ttf"
,
L"
\\
sms
\\
boot
\\
boot.sdi"
,
NULL
};
/** bootmgr.exe file */
static
struct
vdisk_file
*
bootmgr
;
/** WIM image file */
static
struct
vdisk_file
*
bootwim
;
/** Minimal length of embedded bootmgr.exe */
#define BOOTMGR_MIN_LEN 16384
/** 1MB memory threshold */
#define ADDR_1MB 0x00100000
/** 2GB memory threshold */
#define ADDR_2GB 0x80000000
/** Memory regions */
enum
{
WIMBOOT_REGION
=
0
,
PE_REGION
,
INITRD_REGION
,
NUM_REGIONS
};
/**
* Wrap interrupt callback
*
* @v params Parameters
*/
static
void
call_interrupt_wrapper
(
struct
bootapp_callback_params
*
params
)
{
struct
paging_state
state
;
uint16_t
*
attributes
;
/* Handle/modify/pass-through interrupt as required */
if
(
params
->
vector
.
interrupt
==
0x13
)
{
/* Enable paging */
enable_paging
(
&
state
);
/* Intercept INT 13 calls for the emulated drive */
emulate_int13
(
params
);
/* Disable paging */
disable_paging
(
&
state
);
}
else
if
(
(
params
->
vector
.
interrupt
==
0x10
)
&&
(
params
->
ax
==
0x4f01
)
&&
(
!
cmdline_gui
)
)
{
/* Mark all VESA video modes as unsupported */
attributes
=
REAL_PTR
(
params
->
es
,
params
->
di
);
call_interrupt
(
params
);
*
attributes
&=
~
0x0001
;
}
else
{
/* Pass through interrupt */
call_interrupt
(
params
);
}
}
/** Real-mode callback functions */
static
struct
bootapp_callback_functions
callback_fns
=
{
.
call_interrupt
=
call_interrupt_wrapper
,
.
call_real
=
call_real
,
};
/** Real-mode callbacks */
static
struct
bootapp_callback
callback
=
{
.
fns
=
&
callback_fns
,
};
/** Boot application descriptor set */
static
struct
{
/** Boot application descriptor */
struct
bootapp_descriptor
bootapp
;
/** Boot application memory descriptor */
struct
bootapp_memory_descriptor
memory
;
/** Boot application memory descriptor regions */
struct
bootapp_memory_region
regions
[
NUM_REGIONS
];
/** Boot application entry descriptor */
struct
bootapp_entry_descriptor
entry
;
struct
bootapp_entry_wtf1_descriptor
wtf1
;
struct
bootapp_entry_wtf2_descriptor
wtf2
;
struct
bootapp_entry_wtf3_descriptor
wtf3
;
struct
bootapp_entry_wtf3_descriptor
wtf3_copy
;
/** Boot application callback descriptor */
struct
bootapp_callback_descriptor
callback
;
/** Boot application pointless descriptor */
struct
bootapp_pointless_descriptor
pointless
;
}
__attribute__
((
packed
))
bootapps
=
{
.
bootapp
=
{
.
signature
=
BOOTAPP_SIGNATURE
,
.
version
=
BOOTAPP_VERSION
,
.
len
=
sizeof
(
bootapps
),
.
arch
=
BOOTAPP_ARCH_I386
,
.
memory
=
offsetof
(
typeof
(
bootapps
),
memory
),
.
entry
=
offsetof
(
typeof
(
bootapps
),
entry
),
.
xxx
=
offsetof
(
typeof
(
bootapps
),
wtf3_copy
),
.
callback
=
offsetof
(
typeof
(
bootapps
),
callback
),
.
pointless
=
offsetof
(
typeof
(
bootapps
),
pointless
),
},
.
memory
=
{
.
version
=
BOOTAPP_MEMORY_VERSION
,
.
len
=
sizeof
(
bootapps
.
memory
),
.
num_regions
=
NUM_REGIONS
,
.
region_len
=
sizeof
(
bootapps
.
regions
[
0
]
),
.
reserved_len
=
sizeof
(
bootapps
.
regions
[
0
].
reserved
),
},
.
entry
=
{
.
signature
=
BOOTAPP_ENTRY_SIGNATURE
,
.
flags
=
BOOTAPP_ENTRY_FLAGS
,
},
.
wtf1
=
{
.
flags
=
0x11000001
,
.
len
=
sizeof
(
bootapps
.
wtf1
),
.
extra_len
=
(
sizeof
(
bootapps
.
wtf2
)
+
sizeof
(
bootapps
.
wtf3
)
),
},
.
wtf3
=
{
.
flags
=
0x00000006
,
.
len
=
sizeof
(
bootapps
.
wtf3
),
.
boot_partition_offset
=
(
VDISK_VBR_LBA
*
VDISK_SECTOR_SIZE
),
.
xxx
=
0x01
,
.
mbr_signature
=
VDISK_MBR_SIGNATURE
,
},
.
wtf3_copy
=
{
.
flags
=
0x00000006
,
.
len
=
sizeof
(
bootapps
.
wtf3
),
.
boot_partition_offset
=
(
VDISK_VBR_LBA
*
VDISK_SECTOR_SIZE
),
.
xxx
=
0x01
,
.
mbr_signature
=
VDISK_MBR_SIGNATURE
,
},
.
callback
=
{
.
callback
=
&
callback
,
},
.
pointless
=
{
.
version
=
BOOTAPP_POINTLESS_VERSION
,
},
};
/**
* Test if a paragraph is empty
*
* @v pgh Paragraph
* @ret is_empty Paragraph is empty (all zeroes)
*/
static
int
is_empty_pgh
(
const
void
*
pgh
)
{
const
uint32_t
*
dwords
=
pgh
;
return
(
(
dwords
[
0
]
|
dwords
[
1
]
|
dwords
[
2
]
|
dwords
[
3
]
)
==
0
);
}
/**
* Read from file
*
* @v file Virtual file
* @v data Data buffer
* @v offset Offset
* @v len Length
*/
static
void
read_file
(
struct
vdisk_file
*
file
,
void
*
data
,
size_t
offset
,
size_t
len
)
{
memcpy
(
data
,
(
file
->
opaque
+
offset
),
len
);
}
/**
* Add embedded bootmgr.exe extracted from bootmgr
*
* @v data File data
* @v len Length
* @ret file Virtual file, or NULL
*
* bootmgr.exe is awkward to obtain, since it is not available as a
* standalone file on the installation media, or on an installed
* system, or in a Windows PE image as created by WAIK or WADK. It
* can be extracted from a typical boot.wim image using ImageX, but
* this requires installation of the WAIK/WADK/wimlib.
*
* A compressed version of bootmgr.exe is contained within bootmgr,
* which is trivial to obtain.
*/
static
struct
vdisk_file
*
add_bootmgr
(
const
void
*
data
,
size_t
len
)
{
const
uint8_t
*
compressed
;
size_t
offset
;
size_t
compressed_len
;
ssize_t
(
*
decompress
)
(
const
void
*
data
,
size_t
len
,
void
*
buf
);
ssize_t
decompressed_len
;
size_t
padded_len
;
/* Look for an embedded compressed bootmgr.exe on an
* eight-byte boundary.
*/
for
(
offset
=
BOOTMGR_MIN_LEN
;
offset
<
(
len
-
BOOTMGR_MIN_LEN
)
;
offset
+=
0x08
)
{
/* Initialise checks */
decompress
=
NULL
;
compressed
=
(
data
+
offset
);
compressed_len
=
(
len
-
offset
);
/* Check for an embedded LZNT1-compressed bootmgr.exe.
* Since there is no way for LZNT1 to compress the
* initial "MZ" bytes of bootmgr.exe, we look for this
* signature starting three bytes after a paragraph
* boundary, with a preceding tag byte indicating that
* these two bytes would indeed be uncompressed.
*/
if
(
(
(
offset
&
0x0f
)
==
0x00
)
&&
(
(
compressed
[
0x02
]
&
0x03
)
==
0x00
)
&&
(
compressed
[
0x03
]
==
'M'
)
&&
(
compressed
[
0x04
]
==
'Z'
)
)
{
DBG
(
"...checking for LZNT1-compressed bootmgr.exe at "
"+%#zx
\n
"
,
offset
);
decompress
=
lznt1_decompress
;
}
/* Check for an embedded XCA-compressed bootmgr.exe.
* The bytes 0x00, 'M', and 'Z' will always be
* present, and so the corresponding symbols must have
* a non-zero Huffman length. The embedded image
* tends to have a large block of zeroes immediately
* beforehand, which we check for. It's implausible
* that the compressed data could contain substantial
* runs of zeroes, so we check for that too, in order
* to eliminate some common false positive matches.
*/
if
(
(
(
compressed
[
0x00
]
&
0x0f
)
!=
0x00
)
&&
(
(
compressed
[
0x26
]
&
0xf0
)
!=
0x00
)
&&
(
(
compressed
[
0x2d
]
&
0x0f
)
!=
0x00
)
&&
(
is_empty_pgh
(
compressed
-
0x10
)
)
&&
(
!
is_empty_pgh
(
(
compressed
+
0x400
)
)
)
&&
(
!
is_empty_pgh
(
(
compressed
+
0x800
)
)
)
&&
(
!
is_empty_pgh
(
(
compressed
+
0xc00
)
)
)
)
{
DBG
(
"...checking for XCA-compressed bootmgr.exe at "
"+%#zx
\n
"
,
offset
);
decompress
=
xca_decompress
;
}
/* If we have not found a possible bootmgr.exe, skip
* to the next offset.
*/
if
(
!
decompress
)
continue
;
/* Find length of decompressed image */
decompressed_len
=
decompress
(
compressed
,
compressed_len
,
NULL
);
if
(
decompressed_len
<
0
)
{
/* May be a false positive signature match */
continue
;
}
/* Prepend decompressed image to initrd */
DBG
(
"...extracting embedded bootmgr.exe
\n
"
);
padded_len
=
(
(
decompressed_len
+
PAGE_SIZE
-
1
)
&
~
(
PAGE_SIZE
-
1
)
);
initrd
-=
padded_len
;
initrd_len
+=
padded_len
;
decompress
(
compressed
,
compressed_len
,
initrd
);
/* Add decompressed image */
return
vdisk_add_file
(
"bootmgr.exe"
,
initrd
,
decompressed_len
,
read_file
);
}
DBG
(
"...no embedded bootmgr.exe found
\n
"
);
return
NULL
;
}
/**
* File handler
*
* @v name File name
* @v data File data
* @v len Length
* @ret rc Return status code
*/
static
int
add_file
(
const
char
*
name
,
void
*
data
,
size_t
len
)
{
struct
vdisk_file
*
file
;
/* Store file */
file
=
vdisk_add_file
(
name
,
data
,
len
,
read_file
);
/* Check for special-case files */
if
(
strcasecmp
(
name
,
"bootmgr.exe"
)
==
0
)
{
DBG
(
"...found bootmgr.exe
\n
"
);
bootmgr
=
file
;
}
else
if
(
strcasecmp
(
name
,
"bootmgr"
)
==
0
)
{
DBG
(
"...found bootmgr
\n
"
);
if
(
(
!
bootmgr
)
&&
(
bootmgr
=
add_bootmgr
(
data
,
len
)
)
)
{
DBG
(
"...extracted bootmgr.exe
\n
"
);
}
}
else
if
(
strcasecmp
(
(
name
+
strlen
(
name
)
-
4
),
".wim"
)
==
0
)
{
DBG
(
"...found WIM file %s
\n
"
,
name
);
bootwim
=
file
;
}
return
0
;
}
/**
* Relocate data between 1MB and 2GB if possible
*
* @v data Start of data
* @v len Length of data
* @ret start Start address
*/
static
void
*
relocate_memory_low
(
void
*
data
,
size_t
len
)
{
struct
e820_entry
*
e820
=
NULL
;
uint64_t
end
;
intptr_t
start
;
/* Read system memory map */
while
(
(
e820
=
memmap_next
(
e820
)
)
!=
NULL
)
{
/* Find highest compatible placement within this region */
end
=
(
e820
->
start
+
e820
->
len
);
start
=
(
(
end
>
ADDR_2GB
)
?
ADDR_2GB
:
end
);
if
(
start
<
len
)
continue
;
start
-=
len
;
start
&=
~
(
PAGE_SIZE
-
1
);
if
(
start
<
e820
->
start
)
continue
;
if
(
start
<
ADDR_1MB
)
continue
;
/* Relocate to this region */
memmove
(
(
void
*
)
start
,
data
,
len
);
return
(
(
void
*
)
start
);
}
/* Leave at original location */
return
data
;
}
/**
* Main entry point
*
*/
int
main
(
void
)
{
size_t
padded_len
;
void
*
raw_pe
;
struct
loaded_pe
pe
;
struct
paging_state
state
;
uint64_t
initrd_phys
;
/* Initialise stack cookie */
init_cookie
();
/* Print welcome banner */
printf
(
"
\n\n
Booting wim file...... (This may take a few minutes, please wait)
\n\n
"
);
//printf ( "\n\nwimboot " VERSION " -- Windows Imaging Format "
// "bootloader -- https://ipxe.org/wimboot\n\n" );
/* Process command line */
process_cmdline
(
cmdline
);
/* Initialise paging */
init_paging
();
/* Enable paging */
enable_paging
(
&
state
);
/* Relocate initrd below 2GB if possible, to avoid collisions */
DBG
(
"Found initrd at [%p,%p)
\n
"
,
initrd
,
(
initrd
+
initrd_len
)
);
initrd
=
relocate_memory_low
(
initrd
,
initrd_len
);
DBG
(
"Placing initrd at [%p,%p)
\n
"
,
initrd
,
(
initrd
+
initrd_len
)
);
/* Extract files from initrd */
if
(
cpio_extract
(
initrd
,
initrd_len
,
add_file
)
!=
0
)
die
(
"FATAL: could not extract initrd files
\n
"
);
/* Process WIM image */
if
(
bootwim
)
{
vdisk_patch_file
(
bootwim
,
patch_wim
);
if
(
(
!
bootmgr
)
&&
(
bootmgr
=
wim_add_file
(
bootwim
,
cmdline_index
,
bootmgr_path
,
L"bootmgr.exe"
)
)
)
{
DBG
(
"...extracted bootmgr.exe
\n
"
);
}
wim_add_files
(
bootwim
,
cmdline_index
,
wim_paths
);
}
/* Add INT 13 drive */
callback
.
drive
=
initialise_int13
();
/* Read bootmgr.exe into memory */
if
(
!
bootmgr
)
die
(
"FATAL: no bootmgr.exe
\n
"
);
if
(
bootmgr
->
read
==
read_file
)
{
raw_pe
=
bootmgr
->
opaque
;
}
else
{
padded_len
=
(
(
bootmgr
->
len
+
PAGE_SIZE
-
1
)
&
~
(
PAGE_SIZE
-
1
)
);
raw_pe
=
(
initrd
-
padded_len
);
bootmgr
->
read
(
bootmgr
,
raw_pe
,
0
,
bootmgr
->
len
);
}
/* Load bootmgr.exe into memory */
if
(
load_pe
(
raw_pe
,
bootmgr
->
len
,
&
pe
)
!=
0
)
die
(
"FATAL: Could not load bootmgr.exe
\n
"
);
/* Relocate initrd above 4GB if possible, to free up 32-bit memory */
initrd_phys
=
relocate_memory_high
(
initrd
,
initrd_len
);
DBG
(
"Placing initrd at physical [%#llx,%#llx)
\n
"
,
initrd_phys
,
(
initrd_phys
+
initrd_len
)
);
/* Complete boot application descriptor set */
bootapps
.
bootapp
.
pe_base
=
pe
.
base
;
bootapps
.
bootapp
.
pe_len
=
pe
.
len
;
bootapps
.
regions
[
WIMBOOT_REGION
].
start_page
=
page_start
(
_start
);
bootapps
.
regions
[
WIMBOOT_REGION
].
num_pages
=
page_len
(
_start
,
_end
);
bootapps
.
regions
[
PE_REGION
].
start_page
=
page_start
(
pe
.
base
);
bootapps
.
regions
[
PE_REGION
].
num_pages
=
page_len
(
pe
.
base
,
(
pe
.
base
+
pe
.
len
)
);
bootapps
.
regions
[
INITRD_REGION
].
start_page
=
(
initrd_phys
/
PAGE_SIZE
);
bootapps
.
regions
[
INITRD_REGION
].
num_pages
=
page_len
(
initrd
,
initrd
+
initrd_len
);
/* Omit initrd region descriptor if located above 4GB */
if
(
initrd_phys
>=
ADDR_4GB
)
bootapps
.
memory
.
num_regions
--
;
/* Disable paging */
disable_paging
(
&
state
);
/* Jump to PE image */
DBG
(
"Entering bootmgr.exe with parameters at %p
\n
"
,
&
bootapps
);
if
(
cmdline_pause
)
pause
();
pe
.
entry
(
&
bootapps
.
bootapp
);
die
(
"FATAL: bootmgr.exe returned
\n
"
);
}
wimboot/wimboot-2.7.3/src/memmap.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Memory map
*
*/
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "wimboot.h"
#include "memmap.h"
/** Buffer for INT 15,e820 calls */
static
struct
e820_entry
e820_buf
__attribute__
((
section
(
".bss16"
)
));
/** Continuation value for next INT 15,e820 call */
static
uint32_t
e820_ebx
;
/**
* Get system memory map entry
*
* @v prev Previous system memory map entry, or NULL at start
* @v next Next system memory map entry, or NULL at end
*/
struct
e820_entry
*
memmap_next
(
struct
e820_entry
*
prev
)
{
struct
bootapp_callback_params
params
;
/* Reset buffer and continuation value if restarting */
if
(
!
prev
)
{
memset
(
&
e820_buf
,
0
,
sizeof
(
e820_buf
)
);
e820_ebx
=
0
;
}
else
if
(
e820_ebx
==
0
)
{
/* Reach the end */
return
NULL
;
}
/* Read system memory map */
memset
(
&
params
,
0
,
sizeof
(
params
)
);
do
{
/* Call INT 15,e820 */
params
.
vector
.
interrupt
=
0x15
;
params
.
eax
=
0xe820
;
params
.
ebx
=
e820_ebx
;
params
.
ecx
=
sizeof
(
e820_buf
);
params
.
edx
=
E820_SMAP
;
params
.
es
=
BASE_SEG
;
params
.
edi
=
(
(
(
void
*
)
&
e820_buf
)
-
(
(
void
*
)
BASE_ADDRESS
)
);
call_interrupt
(
&
params
);
/* Record continuation value */
e820_ebx
=
params
.
ebx
;
/* Check result */
if
(
params
.
eflags
&
CF
)
{
DBG
(
"INT 15,e820 failed: error %02x
\n
"
,
params
.
ah
);
break
;
}
if
(
params
.
eax
!=
E820_SMAP
)
{
DBG
(
"INT 15,e820 invalid SMAP signature %08x
\n
"
,
params
.
eax
);
break
;
}
DBG2
(
"INT 15,e820 region [%llx,%llx) type %d
\n
"
,
e820_buf
.
start
,
(
e820_buf
.
start
+
e820_buf
.
len
),
e820_buf
.
type
);
/* Skip non-RAM regions */
if
(
e820_buf
.
type
!=
E820_TYPE_RAM
)
continue
;
if
(
params
.
ecx
>
offsetof
(
typeof
(
e820_buf
),
attrs
)
)
{
if
(
!
(
e820_buf
.
attrs
&
E820_ATTR_ENABLED
)
)
continue
;
if
(
e820_buf
.
attrs
&
E820_ATTR_NONVOLATILE
)
continue
;
}
/* Return this region */
return
&
e820_buf
;
}
while
(
e820_ebx
!=
0
);
return
NULL
;
}
wimboot/wimboot-2.7.3/src/memmap.h
0 → 100644
View file @
93996cf7
#ifndef _MEMMAP_H
#define _MEMMAP_H
/*
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Memory map
*
*/
#include <stdint.h>
/** Magic value for INT 15,e820 calls */
#define E820_SMAP 0x534d4150
/** An INT 15,e820 memory map entry */
struct
e820_entry
{
/** Start of region */
uint64_t
start
;
/** Length of region */
uint64_t
len
;
/** Type of region */
uint32_t
type
;
/** Extended attributes (optional) */
uint32_t
attrs
;
}
__attribute__
((
packed
));
/** Normal RAM */
#define E820_TYPE_RAM 1
/** Region is enabled (if extended attributes are present) */
#define E820_ATTR_ENABLED 0x00000001UL
/** Region is non-volatile memory (if extended attributes are present) */
#define E820_ATTR_NONVOLATILE 0x00000002UL
extern
struct
e820_entry
*
memmap_next
(
struct
e820_entry
*
prev
);
#endif
/* _MEMMAP_H */
wimboot/wimboot-2.7.3/src/paging.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Paging
*
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "wimboot.h"
#include "memmap.h"
#include "paging.h"
/** Virtual address used as a 2MB window during relocation */
#define COPY_WINDOW 0x200000
/** Paging is available */
int
paging
;
/** Page directory pointer table */
static
uint64_t
pdpt
[
4
]
__attribute__
((
aligned
(
PAGE_SIZE
)
));
/** Page directories */
static
uint64_t
pd
[
2048
]
__attribute__
((
aligned
(
PAGE_SIZE
)
));
/**
* Check that paging can be supported
*
* @ret supported Paging can be supported on this CPU
*/
static
int
paging_supported
(
void
)
{
uint32_t
eax
;
uint32_t
ebx
;
uint32_t
ecx
;
uint32_t
edx
;
/* Get CPU features */
__asm__
(
"cpuid"
:
"=a"
(
eax
),
"=b"
(
ebx
),
"=c"
(
ecx
),
"=d"
(
edx
)
:
"0"
(
CPUID_FEATURES
)
);
return
(
edx
&
CPUID_FEATURE_EDX_PAE
);
}
/**
* Map 2MB page directory entry containing address
*
* @v vaddr Virtual address
* @v paddr Physical address
*/
static
void
map_page
(
uint32_t
vaddr
,
uint64_t
paddr
)
{
char
*
byte
=
(
(
char
*
)
(
intptr_t
)
vaddr
);
unsigned
int
index
;
/* Sanity checks */
assert
(
(
vaddr
&
(
PAGE_SIZE_2MB
-
1
)
)
==
0
);
assert
(
(
paddr
&
(
PAGE_SIZE_2MB
-
1
)
)
==
0
);
/* Populate page directory entry */
index
=
(
vaddr
/
PAGE_SIZE_2MB
);
pd
[
index
]
=
(
paddr
|
PG_P
|
PG_RW
|
PG_US
|
PG_PS
);
/* Invalidate TLB */
__asm__
__volatile__
(
"invlpg %0"
:
:
"m"
(
*
byte
)
);
}
/**
* Initialise paging
*
*/
void
init_paging
(
void
)
{
uint32_t
addr
;
unsigned
int
i
;
/* Do nothing if paging is disabled */
if
(
cmdline_linear
)
{
DBG
(
"Paging disabled
\n
"
);
return
;
}
/* Check for PAE */
if
(
!
paging_supported
()
)
{
DBG
(
"Paging not possible on this CPU
\n
"
);
return
;
}
/* Initialise page directory entries */
addr
=
0
;
do
{
map_page
(
addr
,
addr
);
addr
+=
PAGE_SIZE_2MB
;
}
while
(
addr
);
/* Initialise page directory pointer table */
for
(
i
=
0
;
i
<
(
sizeof
(
pdpt
)
/
sizeof
(
pdpt
[
0
]
)
)
;
i
++
)
{
addr
=
(
(
intptr_t
)
&
pd
[
i
*
PAGE_SIZE
/
sizeof
(
pd
[
0
]
)
]
);
pdpt
[
i
]
=
(
addr
|
PG_P
);
}
/* Mark paging as available */
paging
=
1
;
}
/**
* Enable paging
*
* @v state Saved paging state to fill in
*/
void
enable_paging
(
struct
paging_state
*
state
)
{
unsigned
long
cr0
;
unsigned
long
cr3
;
unsigned
long
cr4
;
/* Do nothing if paging is unavailable */
if
(
!
paging
)
return
;
/* Save paging state */
__asm__
__volatile__
(
"mov %%cr0, %0
\n\t
"
"mov %%cr3, %1
\n\t
"
"mov %%cr4, %2
\n\t
"
:
"=r"
(
cr0
),
"=r"
(
cr3
),
"=r"
(
cr4
)
);
state
->
cr0
=
cr0
;
state
->
cr3
=
cr3
;
state
->
cr4
=
cr4
;
/* Disable any existing paging */
__asm__
__volatile__
(
"mov %0, %%cr0"
:
:
"r"
(
cr0
&
~
CR0_PG
)
);
/* Enable PAE */
__asm__
__volatile__
(
"mov %0, %%cr4"
:
:
"r"
(
cr4
|
CR4_PAE
)
);
/* Load page directory pointer table */
__asm__
__volatile__
(
"mov %0, %%cr3"
:
:
"r"
(
pdpt
)
);
/* Enable paging */
__asm__
__volatile__
(
"mov %0, %%cr0"
:
:
"r"
(
cr0
|
CR0_PG
)
);
}
/**
* Disable paging
*
* @v state Previously saved paging state
*/
void
disable_paging
(
struct
paging_state
*
state
)
{
unsigned
long
cr0
=
state
->
cr0
;
unsigned
long
cr3
=
state
->
cr3
;
unsigned
long
cr4
=
state
->
cr4
;
/* Do nothing if paging is unavailable */
if
(
!
paging
)
return
;
/* Disable paging */
__asm__
__volatile__
(
"mov %0, %%cr0"
:
:
"r"
(
cr0
&
~
CR0_PG
)
);
/* Restore saved paging state */
__asm__
__volatile__
(
"mov %2, %%cr4
\n\t
"
"mov %1, %%cr3
\n\t
"
"mov %0, %%cr0
\n\t
"
:
:
"r"
(
cr0
),
"r"
(
cr3
),
"r"
(
cr4
)
);
}
/**
* Relocate data out of 32-bit address space, if possible
*
* @v data Start of data
* @v len Length of data
* @ret start Physical start address
*/
uint64_t
relocate_memory_high
(
void
*
data
,
size_t
len
)
{
intptr_t
end
=
(
(
(
intptr_t
)
data
)
+
len
);
struct
e820_entry
*
e820
=
NULL
;
uint64_t
start
;
uint64_t
dest
;
size_t
offset
;
size_t
frag_len
;
/* Do nothing if paging is unavailable */
if
(
!
paging
)
return
(
(
intptr_t
)
data
);
/* Read system memory map */
while
(
(
e820
=
memmap_next
(
e820
)
)
!=
NULL
)
{
/* Find highest compatible placement within this region */
start
=
(
e820
->
start
+
e820
->
len
);
if
(
start
<
ADDR_4GB
)
continue
;
start
=
(
(
(
start
-
end
)
&
~
(
PAGE_SIZE_2MB
-
1
)
)
+
end
);
start
-=
len
;
if
(
start
<
e820
->
start
)
continue
;
if
(
start
<
ADDR_4GB
)
continue
;
/* Relocate to this region */
dest
=
start
;
while
(
len
)
{
/* Calculate length within this 2MB page */
offset
=
(
(
(
intptr_t
)
data
)
&
(
PAGE_SIZE_2MB
-
1
)
);
frag_len
=
(
PAGE_SIZE_2MB
-
offset
);
if
(
frag_len
>
len
)
frag_len
=
len
;
/* Map copy window to destination */
map_page
(
COPY_WINDOW
,
(
dest
&
~
(
PAGE_SIZE_2MB
-
1
)
)
);
/* Copy data through copy window */
memcpy
(
(
(
(
void
*
)
COPY_WINDOW
)
+
offset
),
data
,
frag_len
);
/* Map original page to destination */
map_page
(
(
(
(
intptr_t
)
data
)
-
offset
),
(
dest
&
~
(
PAGE_SIZE_2MB
-
1
)
)
);
/* Move to next 2MB page */
data
+=
frag_len
;
dest
+=
frag_len
;
len
-=
frag_len
;
}
/* Remap copy window */
map_page
(
COPY_WINDOW
,
COPY_WINDOW
);
return
start
;
}
/* Leave at original location */
return
(
(
intptr_t
)
data
);
}
wimboot/wimboot-2.7.3/src/paging.h
0 → 100644
View file @
93996cf7
#ifndef _PAGING_H
#define _PAGING_H
/*
* Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Paging
*
*/
#include <stddef.h>
/** Get CPU features */
#define CPUID_FEATURES 0x00000001
/** CPU supports PAE */
#define CPUID_FEATURE_EDX_PAE 0x00000040
/* CR0: paging */
#define CR0_PG 0x80000000
/* CR4: physical address extensions */
#define CR4_PAE 0x00000020
/* Page: present */
#define PG_P 0x01
/* Page: read/write */
#define PG_RW 0x02
/* Page: user/supervisor */
#define PG_US 0x04
/* Page: page size */
#define PG_PS 0x80
/** 2MB page size */
#define PAGE_SIZE_2MB 0x200000
/** 32-bit address space size */
#define ADDR_4GB 0x100000000ULL
/** Saved paging state */
struct
paging_state
{
/** Control register 0 */
unsigned
long
cr0
;
/** Control register 3 */
unsigned
long
cr3
;
/** Control register 4 */
unsigned
long
cr4
;
};
extern
int
paging
;
extern
void
init_paging
(
void
);
extern
void
enable_paging
(
struct
paging_state
*
state
);
extern
void
disable_paging
(
struct
paging_state
*
state
);
extern
uint64_t
relocate_memory_high
(
void
*
start
,
size_t
len
);
#endif
/* _PAGING_H */
wimboot/wimboot-2.7.3/src/pause.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Diagnostic pause
*
*/
#include <stdio.h>
#include "wimboot.h"
#include "cmdline.h"
#include "pause.h"
/**
* Pause before booting
*
*/
void
pause
(
void
)
{
/* Wait for keypress, prompting unless inhibited */
if
(
cmdline_pause_quiet
)
{
getchar
();
}
else
{
printf
(
"Press any key to continue booting..."
);
getchar
();
printf
(
"
\n
"
);
}
}
wimboot/wimboot-2.7.3/src/pause.h
0 → 100644
View file @
93996cf7
#ifndef _PAUSE_H
#define _PAUSE_H
/*
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Diagnostic pause
*
*/
extern
void
pause
(
void
);
#endif
/* _PAUSE_H */
wimboot/wimboot-2.7.3/src/peloader.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* PE image loader
*
*/
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "wimboot.h"
#include "peloader.h"
/**
* Load PE image into memory
*
* @v data PE image
* @v len Length of PE image
* @v pe Loaded PE structure to fill in
* @ret rc Return status code
*/
int
load_pe
(
const
void
*
data
,
size_t
len
,
struct
loaded_pe
*
pe
)
{
const
struct
mz_header
*
mzhdr
;
size_t
pehdr_offset
;
const
struct
pe_header
*
pehdr
;
size_t
opthdr_offset
;
const
struct
pe_optional_header
*
opthdr
;
size_t
section_offset
;
const
struct
coff_section
*
section
;
char
name
[
sizeof
(
section
->
name
)
+
1
/* NUL */
];
unsigned
int
i
;
void
*
section_base
;
size_t
filesz
;
size_t
memsz
;
void
*
end
;
void
*
raw_base
;
DBG2
(
"Loading PE executable...
\n
"
);
/* Parse PE header */
mzhdr
=
data
;
if
(
mzhdr
->
magic
!=
MZ_HEADER_MAGIC
)
{
DBG
(
"Bad MZ magic %04x
\n
"
,
mzhdr
->
magic
);
return
-
1
;
}
pehdr_offset
=
mzhdr
->
lfanew
;
if
(
pehdr_offset
>
len
)
{
DBG
(
"PE header outside file
\n
"
);
return
-
1
;
}
pehdr
=
(
data
+
pehdr_offset
);
if
(
pehdr
->
magic
!=
PE_HEADER_MAGIC
)
{
DBG
(
"Bad PE magic %08x
\n
"
,
pehdr
->
magic
);
return
-
1
;
}
opthdr_offset
=
(
pehdr_offset
+
sizeof
(
*
pehdr
)
);
opthdr
=
(
data
+
opthdr_offset
);
pe
->
base
=
(
(
void
*
)
(
intptr_t
)
(
opthdr
->
base
)
);
section_offset
=
(
opthdr_offset
+
pehdr
->
coff
.
opthdr_len
);
section
=
(
data
+
section_offset
);
/* Load header into memory */
DBG2
(
"...headers to %p+%#x
\n
"
,
pe
->
base
,
opthdr
->
header_len
);
memcpy
(
pe
->
base
,
data
,
opthdr
->
header_len
);
end
=
(
pe
->
base
+
opthdr
->
header_len
);
/* Load each section into memory */
for
(
i
=
0
;
i
<
pehdr
->
coff
.
num_sections
;
i
++
,
section
++
)
{
memset
(
name
,
0
,
sizeof
(
name
)
);
memcpy
(
name
,
section
->
name
,
sizeof
(
section
->
name
)
);
section_base
=
(
pe
->
base
+
section
->
virtual
);
filesz
=
section
->
raw_len
;
memsz
=
section
->
misc
.
virtual_len
;
DBG2
(
"...from %#05x to %p+%#zx/%#zx (%s)
\n
"
,
section
->
raw
,
section_base
,
filesz
,
memsz
,
name
);
memset
(
section_base
,
0
,
memsz
);
memcpy
(
section_base
,
(
data
+
section
->
raw
),
filesz
);
if
(
end
<
(
section_base
+
memsz
)
)
end
=
(
section_base
+
memsz
);
}
pe
->
len
=
(
(
(
end
-
pe
->
base
)
+
opthdr
->
section_align
-
1
)
&
~
(
opthdr
->
section_align
-
1
)
);
/* Load copy of raw image into memory immediately after loaded
* sections. This seems to be used for verification of X.509
* signatures.
*/
raw_base
=
(
pe
->
base
+
pe
->
len
);
memcpy
(
raw_base
,
data
,
len
);
pe
->
len
+=
len
;
DBG2
(
"...raw copy to %p+%#zx
\n
"
,
raw_base
,
len
);
/* Extract entry point */
pe
->
entry
=
(
pe
->
base
+
opthdr
->
entry
);
DBG2
(
"...entry point %p
\n
"
,
pe
->
entry
);
return
0
;
}
wimboot/wimboot-2.7.3/src/peloader.h
0 → 100644
View file @
93996cf7
#ifndef _PELOADER_H
#define _PELOADER_H
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* PE image loader
*
*/
#include <stdint.h>
#include "wimboot.h"
/** DOS MZ header */
struct
mz_header
{
/** Magic number */
uint16_t
magic
;
/** Bytes on last page of file */
uint16_t
cblp
;
/** Pages in file */
uint16_t
cp
;
/** Relocations */
uint16_t
crlc
;
/** Size of header in paragraphs */
uint16_t
cparhdr
;
/** Minimum extra paragraphs needed */
uint16_t
minalloc
;
/** Maximum extra paragraphs needed */
uint16_t
maxalloc
;
/** Initial (relative) SS value */
uint16_t
ss
;
/** Initial SP value */
uint16_t
sp
;
/** Checksum */
uint16_t
csum
;
/** Initial IP value */
uint16_t
ip
;
/** Initial (relative) CS value */
uint16_t
cs
;
/** File address of relocation table */
uint16_t
lfarlc
;
/** Overlay number */
uint16_t
ovno
;
/** Reserved words */
uint16_t
res
[
4
];
/** OEM identifier (for oeminfo) */
uint16_t
oemid
;
/** OEM information; oemid specific */
uint16_t
oeminfo
;
/** Reserved words */
uint16_t
res2
[
10
];
/** File address of new exe header */
uint32_t
lfanew
;
}
__attribute__
((
packed
));
/** MZ header magic */
#define MZ_HEADER_MAGIC 0x5a4d
/** COFF file header */
struct
coff_header
{
/** Magic number */
uint16_t
magic
;
/** Number of sections */
uint16_t
num_sections
;
/** Timestamp (seconds since the Epoch) */
uint32_t
timestamp
;
/** Offset to symbol table */
uint32_t
symtab
;
/** Number of symbol table entries */
uint32_t
num_syms
;
/** Length of optional header */
uint16_t
opthdr_len
;
/** Flags */
uint16_t
flags
;
}
__attribute__
((
packed
));
/** COFF section */
struct
coff_section
{
/** Section name */
char
name
[
8
];
/** Physical address or virtual length */
union
{
/** Physical address */
uint32_t
physical
;
/** Virtual length */
uint32_t
virtual_len
;
}
misc
;
/** Virtual address */
uint32_t
virtual
;
/** Length of raw data */
uint32_t
raw_len
;
/** Offset to raw data */
uint32_t
raw
;
/** Offset to relocations */
uint32_t
relocations
;
/** Offset to line numbers */
uint32_t
line_numbers
;
/** Number of relocations */
uint16_t
num_relocations
;
/** Number of line numbers */
uint16_t
num_line_numbers
;
/** Flags */
uint32_t
flags
;
}
__attribute__
((
packed
));
/** PE file header */
struct
pe_header
{
/** Magic number */
uint32_t
magic
;
/** COFF header */
struct
coff_header
coff
;
}
__attribute__
((
packed
));
/** PE header magic */
#define PE_HEADER_MAGIC 0x00004550
/** PE optional header */
struct
pe_optional_header
{
/** Magic number */
uint16_t
magic
;
/** Major linker version */
uint8_t
linker_major
;
/** Minor linker version */
uint8_t
linker_minor
;
/** Length of code */
uint32_t
text_len
;
/** Length of initialised data */
uint32_t
data_len
;
/** Length of uninitialised data */
uint32_t
bss_len
;
/** Entry point */
uint32_t
entry
;
/** Base of code */
uint32_t
text
;
/** Base of data */
uint32_t
data
;
/** Image base address */
uint32_t
base
;
/** Section alignment */
uint32_t
section_align
;
/** File alignment */
uint32_t
file_align
;
/** Major operating system version */
uint16_t
os_major
;
/** Minor operating system version */
uint16_t
os_minor
;
/** Major image version */
uint16_t
image_major
;
/** Minor image version */
uint16_t
image_minor
;
/** Major subsystem version */
uint16_t
subsystem_major
;
/** Minor subsystem version */
uint16_t
subsystem_minor
;
/** Win32 version */
uint32_t
win32_version
;
/** Size of image */
uint32_t
len
;
/** Size of headers */
uint32_t
header_len
;
/* Plus extra fields that we don't care about */
}
__attribute__
((
packed
));
/** A loaded PE image */
struct
loaded_pe
{
/** Base address */
void
*
base
;
/** Length */
size_t
len
;
/** Entry point */
void
(
*
entry
)
(
struct
bootapp_descriptor
*
bootapp
);
};
extern
int
load_pe
(
const
void
*
data
,
size_t
len
,
struct
loaded_pe
*
pe
);
#endif
/* _PELOADER_H */
wimboot/wimboot-2.7.3/src/rotate.h
0 → 100644
View file @
93996cf7
#ifndef _ROTATE_H
#define _ROTATE_H
/** @file
*
* Bit operations
*/
#include <stdint.h>
static
inline
__attribute__
((
always_inline
))
uint8_t
rol8
(
uint8_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
<<
rotation
)
|
(
data
>>
(
8
-
rotation
)
)
);
}
static
inline
__attribute__
((
always_inline
))
uint8_t
ror8
(
uint8_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
>>
rotation
)
|
(
data
<<
(
8
-
rotation
)
)
);
}
static
inline
__attribute__
((
always_inline
))
uint16_t
rol16
(
uint16_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
<<
rotation
)
|
(
data
>>
(
16
-
rotation
)
)
);
}
static
inline
__attribute__
((
always_inline
))
uint16_t
ror16
(
uint16_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
>>
rotation
)
|
(
data
<<
(
16
-
rotation
)
)
);
}
static
inline
__attribute__
((
always_inline
))
uint32_t
rol32
(
uint32_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
<<
rotation
)
|
(
data
>>
(
32
-
rotation
)
)
);
}
static
inline
__attribute__
((
always_inline
))
uint32_t
ror32
(
uint32_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
>>
rotation
)
|
(
data
<<
(
32
-
rotation
)
)
);
}
static
inline
__attribute__
((
always_inline
))
uint64_t
rol64
(
uint64_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
<<
rotation
)
|
(
data
>>
(
64
-
rotation
)
)
);
}
static
inline
__attribute__
((
always_inline
))
uint64_t
ror64
(
uint64_t
data
,
unsigned
int
rotation
)
{
return
(
(
data
>>
rotation
)
|
(
data
<<
(
64
-
rotation
)
)
);
}
#endif
/* _ROTATE_H */
wimboot/wimboot-2.7.3/src/script.lds
0 → 100644
View file @
93996cf7
SECTIONS {
/* Align sections to keep PE tools happy */
alignment = 16;
/* Virtual addresses start at 0x20000 */
. = 0x20000;
_start = .;
/* bzImage prefix */
_prefix_pos = 0;
.prefix : AT ( _prefix_pos ) {
_prefix = .;
*(.prefix)
*(.prefix.*)
. = ALIGN ( alignment );
_eprefix = .;
}
_prefix_len = ABSOLUTE ( _eprefix ) - ABSOLUTE ( _prefix );
/* Real-mode uninitialised data section */
.bss16 ( NOLOAD ) : {
_bss16 = .;
*(.stack16)
*(.stack16.*)
*(.bss16)
*(.bss16.*)
. = ALIGN ( alignment );
_ebss16 = .;
}
_bss16_len = ABSOLUTE ( _ebss16 ) - ABSOLUTE ( _bss16 );
/* Payload section */
_payload_pos = ( _prefix_pos + _prefix_len );
.payload : AT ( _payload_pos ) {
_payload = .;
/* Portions that must be accessible in 16-bit modes */
_text16 = .;
*(.text16)
*(.text16.*)
_etext16 = .;
_data16 = .;
*(.rodata16)
*(.rodata16.*)
*(.data16)
*(.data16.*)
_edata16 = .;
/* Portions that need not be accessible in 16-bit modes */
_text = .;
*(.text)
*(.text.*)
_etext = .;
_data = .;
*(.rodata)
*(.rodata.*)
*(.data)
*(.data.*)
. = ALIGN ( alignment );
_edata = .;
_epayload = .;
}
_text16_len = ABSOLUTE ( _etext16 ) - ABSOLUTE ( _text16 );
_data16_len = ABSOLUTE ( _edata16 ) - ABSOLUTE ( _data16 );
_text_len = ABSOLUTE ( _etext ) - ABSOLUTE ( _text );
_data_len = ABSOLUTE ( _edata ) - ABSOLUTE ( _data );
_payload_len = ABSOLUTE ( _epayload ) - ABSOLUTE ( _payload );
/* bootmgr.exe hardcodes the address 0x30000 for use as a
* buffer accessible by real-mode code. We can't fit our
* .text, .data, and .bss below this region, so explicitly
* place the .bss higher in memory.
*/
_forbidden_start = 0x30000;
_forbidden_end = 0x40000;
/* Uninitialised data section */
.bss ( NOLOAD ) : {
_bss = .;
ASSERT ( ABSOLUTE ( . ) <= ABSOLUTE ( _forbidden_start ),
"Binary is too large" );
. = ABSOLUTE ( _forbidden_end );
*(.bss)
*(.bss.*)
*(COMMON)
*(.stack)
*(.stack.*)
. = ALIGN ( alignment );
_ebss = .;
}
_bss_len = ABSOLUTE ( _ebss ) - ABSOLUTE ( _bss );
/* Relocations section */
_reloc_pos = ( _payload_pos + _payload_len );
_reloc = .;
_end = .;
_text_total_len = ( _text_len + _text16_len );
_data_total_len = ( _data_len + _data16_len );
_bss_total_len = ( _bss_len + _bss16_len );
/* Symbols required by i386.x86_64 objects */
__i386__start = _start;
__i386__end = _end;
/DISCARD/ : {
*(.comment)
*(.comment.*)
*(.note)
*(.note.*)
*(.eh_frame)
*(.eh_frame.*)
*(.rel)
*(.rel.*)
}
}
wimboot/wimboot-2.7.3/src/sha1.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
/**
* @file
*
* SHA-1 algorithm
*
*/
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <byteswap.h>
#include <assert.h>
#include "rotate.h"
#include "sha1.h"
/** SHA-1 variables */
struct
sha1_variables
{
/* This layout matches that of struct sha1_digest_data,
* allowing for efficient endianness-conversion,
*/
uint32_t
a
;
uint32_t
b
;
uint32_t
c
;
uint32_t
d
;
uint32_t
e
;
uint32_t
w
[
80
];
}
__attribute__
((
packed
));
/**
* f(a,b,c,d) for steps 0 to 19
*
* @v v SHA-1 variables
* @ret f f(a,b,c,d)
*/
static
uint32_t
sha1_f_0_19
(
struct
sha1_variables
*
v
)
{
return
(
(
v
->
b
&
v
->
c
)
|
(
(
~
v
->
b
)
&
v
->
d
)
);
}
/**
* f(a,b,c,d) for steps 20 to 39 and 60 to 79
*
* @v v SHA-1 variables
* @ret f f(a,b,c,d)
*/
static
uint32_t
sha1_f_20_39_60_79
(
struct
sha1_variables
*
v
)
{
return
(
v
->
b
^
v
->
c
^
v
->
d
);
}
/**
* f(a,b,c,d) for steps 40 to 59
*
* @v v SHA-1 variables
* @ret f f(a,b,c,d)
*/
static
uint32_t
sha1_f_40_59
(
struct
sha1_variables
*
v
)
{
return
(
(
v
->
b
&
v
->
c
)
|
(
v
->
b
&
v
->
d
)
|
(
v
->
c
&
v
->
d
)
);
}
/** An SHA-1 step function */
struct
sha1_step
{
/**
* Calculate f(a,b,c,d)
*
* @v v SHA-1 variables
* @ret f f(a,b,c,d)
*/
uint32_t
(
*
f
)
(
struct
sha1_variables
*
v
);
/** Constant k */
uint32_t
k
;
};
/** SHA-1 steps */
static
struct
sha1_step
sha1_steps
[
4
]
=
{
/** 0 to 19 */
{
.
f
=
sha1_f_0_19
,
.
k
=
0x5a827999
},
/** 20 to 39 */
{
.
f
=
sha1_f_20_39_60_79
,
.
k
=
0x6ed9eba1
},
/** 40 to 59 */
{
.
f
=
sha1_f_40_59
,
.
k
=
0x8f1bbcdc
},
/** 60 to 79 */
{
.
f
=
sha1_f_20_39_60_79
,
.
k
=
0xca62c1d6
},
};
/**
* Initialise SHA-1 algorithm
*
* @v ctx SHA-1 context
*/
void
sha1_init
(
void
*
ctx
)
{
struct
sha1_context
*
context
=
ctx
;
context
->
ddd
.
dd
.
digest
.
h
[
0
]
=
cpu_to_be32
(
0x67452301
);
context
->
ddd
.
dd
.
digest
.
h
[
1
]
=
cpu_to_be32
(
0xefcdab89
);
context
->
ddd
.
dd
.
digest
.
h
[
2
]
=
cpu_to_be32
(
0x98badcfe
);
context
->
ddd
.
dd
.
digest
.
h
[
3
]
=
cpu_to_be32
(
0x10325476
);
context
->
ddd
.
dd
.
digest
.
h
[
4
]
=
cpu_to_be32
(
0xc3d2e1f0
);
context
->
len
=
0
;
}
/**
* Calculate SHA-1 digest of accumulated data
*
* @v context SHA-1 context
*/
static
void
sha1_digest
(
struct
sha1_context
*
context
)
{
union
{
union
sha1_digest_data_dwords
ddd
;
struct
sha1_variables
v
;
}
u
;
uint32_t
*
a
=
&
u
.
v
.
a
;
uint32_t
*
b
=
&
u
.
v
.
b
;
uint32_t
*
c
=
&
u
.
v
.
c
;
uint32_t
*
d
=
&
u
.
v
.
d
;
uint32_t
*
e
=
&
u
.
v
.
e
;
uint32_t
*
w
=
u
.
v
.
w
;
uint32_t
f
;
uint32_t
k
;
uint32_t
temp
;
struct
sha1_step
*
step
;
unsigned
int
i
;
/* Convert h[0..4] to host-endian, and initialise a, b, c, d,
* e, and w[0..15]
*/
for
(
i
=
0
;
i
<
(
sizeof
(
u
.
ddd
.
dword
)
/
sizeof
(
u
.
ddd
.
dword
[
0
]
)
)
;
i
++
)
{
be32_to_cpus
(
&
context
->
ddd
.
dword
[
i
]
);
u
.
ddd
.
dword
[
i
]
=
context
->
ddd
.
dword
[
i
];
}
/* Initialise w[16..79] */
for
(
i
=
16
;
i
<
80
;
i
++
)
w
[
i
]
=
rol32
(
(
w
[
i
-
3
]
^
w
[
i
-
8
]
^
w
[
i
-
14
]
^
w
[
i
-
16
]
),
1
);
/* Main loop */
for
(
i
=
0
;
i
<
80
;
i
++
)
{
step
=
&
sha1_steps
[
i
/
20
];
f
=
step
->
f
(
&
u
.
v
);
k
=
step
->
k
;
temp
=
(
rol32
(
*
a
,
5
)
+
f
+
*
e
+
k
+
w
[
i
]
);
*
e
=
*
d
;
*
d
=
*
c
;
*
c
=
rol32
(
*
b
,
30
);
*
b
=
*
a
;
*
a
=
temp
;
}
/* Add chunk to hash and convert back to big-endian */
for
(
i
=
0
;
i
<
5
;
i
++
)
{
context
->
ddd
.
dd
.
digest
.
h
[
i
]
=
cpu_to_be32
(
context
->
ddd
.
dd
.
digest
.
h
[
i
]
+
u
.
ddd
.
dd
.
digest
.
h
[
i
]
);
}
}
/**
* Accumulate data with SHA-1 algorithm
*
* @v ctx SHA-1 context
* @v data Data
* @v len Length of data
*/
void
sha1_update
(
void
*
ctx
,
const
void
*
data
,
size_t
len
)
{
struct
sha1_context
*
context
=
ctx
;
const
uint8_t
*
byte
=
data
;
size_t
offset
;
/* Accumulate data a byte at a time, performing the digest
* whenever we fill the data buffer
*/
while
(
len
--
)
{
offset
=
(
context
->
len
%
sizeof
(
context
->
ddd
.
dd
.
data
)
);
context
->
ddd
.
dd
.
data
.
byte
[
offset
]
=
*
(
byte
++
);
context
->
len
++
;
if
(
(
context
->
len
%
sizeof
(
context
->
ddd
.
dd
.
data
)
)
==
0
)
sha1_digest
(
context
);
}
}
/**
* Generate SHA-1 digest
*
* @v ctx SHA-1 context
* @v out Output buffer
*/
void
sha1_final
(
void
*
ctx
,
void
*
out
)
{
struct
sha1_context
*
context
=
ctx
;
uint64_t
len_bits
;
uint8_t
pad
;
/* Record length before pre-processing */
len_bits
=
cpu_to_be64
(
(
(
uint64_t
)
context
->
len
)
*
8
);
/* Pad with a single "1" bit followed by as many "0" bits as required */
pad
=
0x80
;
do
{
sha1_update
(
ctx
,
&
pad
,
sizeof
(
pad
)
);
pad
=
0x00
;
}
while
(
(
context
->
len
%
sizeof
(
context
->
ddd
.
dd
.
data
)
)
!=
offsetof
(
typeof
(
context
->
ddd
.
dd
.
data
),
final
.
len
)
);
/* Append length (in bits) */
sha1_update
(
ctx
,
&
len_bits
,
sizeof
(
len_bits
)
);
assert
(
(
context
->
len
%
sizeof
(
context
->
ddd
.
dd
.
data
)
)
==
0
);
/* Copy out final digest */
memcpy
(
out
,
&
context
->
ddd
.
dd
.
digest
,
sizeof
(
context
->
ddd
.
dd
.
digest
)
);
}
wimboot/wimboot-2.7.3/src/sha1.h
0 → 100644
View file @
93996cf7
#ifndef _SHA1_H
#define _SHA1_H
/** @file
*
* SHA-1 algorithm
*
*/
#include <stdint.h>
/** An SHA-1 digest */
struct
sha1_digest
{
/** Hash output */
uint32_t
h
[
5
];
};
/** An SHA-1 data block */
union
sha1_block
{
/** Raw bytes */
uint8_t
byte
[
64
];
/** Raw dwords */
uint32_t
dword
[
16
];
/** Final block structure */
struct
{
/** Padding */
uint8_t
pad
[
56
];
/** Length in bits */
uint64_t
len
;
}
final
;
};
/** SHA-1 digest and data block
*
* The order of fields within this structure is designed to minimise
* code size.
*/
struct
sha1_digest_data
{
/** Digest of data already processed */
struct
sha1_digest
digest
;
/** Accumulated data */
union
sha1_block
data
;
}
__attribute__
((
packed
));
/** SHA-1 digest and data block */
union
sha1_digest_data_dwords
{
/** Digest and data block */
struct
sha1_digest_data
dd
;
/** Raw dwords */
uint32_t
dword
[
sizeof
(
struct
sha1_digest_data
)
/
sizeof
(
uint32_t
)
];
};
/** An SHA-1 context */
struct
sha1_context
{
/** Amount of accumulated data */
size_t
len
;
/** Digest and accumulated data */
union
sha1_digest_data_dwords
ddd
;
}
__attribute__
((
packed
));
/** SHA-1 context size */
#define SHA1_CTX_SIZE sizeof ( struct sha1_context )
/** SHA-1 digest size */
#define SHA1_DIGEST_SIZE sizeof ( struct sha1_digest )
extern
void
sha1_init
(
void
*
ctx
);
extern
void
sha1_update
(
void
*
ctx
,
const
void
*
data
,
size_t
len
);
extern
void
sha1_final
(
void
*
ctx
,
void
*
out
);
#endif
/* _SHA1_H */
wimboot/wimboot-2.7.3/src/stdarg.h
0 → 100644
View file @
93996cf7
#ifndef _STDARG_H
#define _STDARG_H
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Standard arguments
*
*/
typedef
__builtin_va_list
va_list
;
#define va_start( ap, last ) __builtin_va_start ( ap, last )
#define va_arg( ap, type ) __builtin_va_arg ( ap, type )
#define va_end( ap ) __builtin_va_end ( ap )
#define va_copy( dest, src ) __builtin_va_copy ( dest, src )
#endif
/* _STDARG_H */
wimboot/wimboot-2.7.3/src/stddef.h
0 → 100644
View file @
93996cf7
#ifndef _STDDEF_H
#define _STDDEF_H
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Standard definitions
*
*/
#include <stdint.h>
#define NULL ( ( void * ) 0 )
#define offsetof( type, member ) ( ( size_t ) &( ( type * ) NULL )->member )
#define container_of( ptr, type, member ) ( { \
const typeof ( ( ( type * ) NULL )->member ) *__mptr = (ptr); \
( type * ) ( ( void * ) __mptr - offsetof ( type, member ) ); } )
#endif
/* _STDDEF_H */
wimboot/wimboot-2.7.3/src/stdint.h
0 → 100644
View file @
93996cf7
#ifndef _STDINT_H
#define _STDINT_H
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Standard integer types
*
*/
typedef
unsigned
char
uint8_t
;
typedef
unsigned
short
uint16_t
;
typedef
unsigned
int
uint32_t
;
typedef
unsigned
long
long
uint64_t
;
typedef
signed
char
int8_t
;
typedef
signed
short
int16_t
;
typedef
signed
int
int32_t
;
typedef
signed
long
long
int64_t
;
typedef
unsigned
long
intptr_t
;
typedef
__SIZE_TYPE__
size_t
;
typedef
signed
long
ssize_t
;
typedef
__WCHAR_TYPE__
wchar_t
;
typedef
__WINT_TYPE__
wint_t
;
#endif
/* _STDINT_H */
wimboot/wimboot-2.7.3/src/stdio.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* @file
*
* Standard Input/Output
*
*/
#include <stdio.h>
#include <string.h>
#include "bootapp.h"
#include "wimboot.h"
#include "efi.h"
/**
* Print character to console
*
* @v character Character to print
*/
int
putchar
(
int
character
)
{
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*
conout
;
struct
bootapp_callback_params
params
;
wchar_t
wbuf
[
2
];
/* Convert LF to CR,LF */
if
(
character
==
'\n'
)
putchar
(
'\r'
);
/* Print character to bochs debug port */
__asm__
__volatile__
(
"outb %b0, $0xe9"
:
:
"a"
(
character
)
);
/* Print character to EFI/BIOS console as applicable */
if
(
efi_systab
)
{
conout
=
efi_systab
->
ConOut
;
wbuf
[
0
]
=
character
;
wbuf
[
1
]
=
0
;
conout
->
OutputString
(
conout
,
wbuf
);
}
else
{
memset
(
&
params
,
0
,
sizeof
(
params
)
);
params
.
vector
.
interrupt
=
0x10
;
params
.
eax
=
(
0x0e00
|
character
);
params
.
ebx
=
0x0007
;
call_interrupt
(
&
params
);
}
return
0
;
}
/**
* Get character from console
*
* @ret character Character
*/
int
getchar
(
void
)
{
EFI_BOOT_SERVICES
*
bs
;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*
conin
;
EFI_INPUT_KEY
key
;
UINTN
index
;
struct
bootapp_callback_params
params
;
int
character
;
/* Get character */
if
(
efi_systab
)
{
bs
=
efi_systab
->
BootServices
;
conin
=
efi_systab
->
ConIn
;
bs
->
WaitForEvent
(
1
,
&
conin
->
WaitForKey
,
&
index
);
conin
->
ReadKeyStroke
(
conin
,
&
key
);
character
=
key
.
UnicodeChar
;
}
else
{
memset
(
&
params
,
0
,
sizeof
(
params
)
);
params
.
vector
.
interrupt
=
0x16
;
call_interrupt
(
&
params
);
character
=
params
.
al
;
}
return
character
;
}
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment