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
3045 additions
and
0 deletions
+3045
-0
wimboot/wimboot-2.7.3/src/efiblock.c
wimboot/wimboot-2.7.3/src/efiblock.c
+307
-0
wimboot/wimboot-2.7.3/src/efiblock.h
wimboot/wimboot-2.7.3/src/efiblock.h
+38
-0
wimboot/wimboot-2.7.3/src/efiboot.c
wimboot/wimboot-2.7.3/src/efiboot.c
+157
-0
wimboot/wimboot-2.7.3/src/efiboot.h
wimboot/wimboot-2.7.3/src/efiboot.h
+38
-0
wimboot/wimboot-2.7.3/src/efifile.c
wimboot/wimboot-2.7.3/src/efifile.c
+201
-0
wimboot/wimboot-2.7.3/src/efifile.h
wimboot/wimboot-2.7.3/src/efifile.h
+39
-0
wimboot/wimboot-2.7.3/src/efiguid.c
wimboot/wimboot-2.7.3/src/efiguid.c
+53
-0
wimboot/wimboot-2.7.3/src/efimain.c
wimboot/wimboot-2.7.3/src/efimain.c
+105
-0
wimboot/wimboot-2.7.3/src/efipath.c
wimboot/wimboot-2.7.3/src/efipath.c
+46
-0
wimboot/wimboot-2.7.3/src/efipath.h
wimboot/wimboot-2.7.3/src/efipath.h
+89
-0
wimboot/wimboot-2.7.3/src/efireloc.c
wimboot/wimboot-2.7.3/src/efireloc.c
+556
-0
wimboot/wimboot-2.7.3/src/errno.h
wimboot/wimboot-2.7.3/src/errno.h
+30
-0
wimboot/wimboot-2.7.3/src/huffman.c
wimboot/wimboot-2.7.3/src/huffman.c
+209
-0
wimboot/wimboot-2.7.3/src/huffman.h
wimboot/wimboot-2.7.3/src/huffman.h
+110
-0
wimboot/wimboot-2.7.3/src/i386.i
wimboot/wimboot-2.7.3/src/i386.i
+1
-0
wimboot/wimboot-2.7.3/src/int13.c
wimboot/wimboot-2.7.3/src/int13.c
+225
-0
wimboot/wimboot-2.7.3/src/int13.h
wimboot/wimboot-2.7.3/src/int13.h
+120
-0
wimboot/wimboot-2.7.3/src/ipxe/vsprintf.c
wimboot/wimboot-2.7.3/src/ipxe/vsprintf.c
+466
-0
wimboot/wimboot-2.7.3/src/ipxe/vsprintf.h
wimboot/wimboot-2.7.3/src/ipxe/vsprintf.h
+74
-0
wimboot/wimboot-2.7.3/src/lznt1.c
wimboot/wimboot-2.7.3/src/lznt1.c
+181
-0
No files found.
wimboot/wimboot-2.7.3/src/efiblock.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
*
* EFI block device
*
*/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "wimboot.h"
#include "vdisk.h"
#include "efi.h"
#include "efipath.h"
#include "efiblock.h"
/** A block I/O device */
struct
efi_block
{
/** EFI block I/O protocol */
EFI_BLOCK_IO_PROTOCOL
block
;
/** Device path */
EFI_DEVICE_PATH_PROTOCOL
*
path
;
/** Starting LBA */
uint64_t
lba
;
/** Name */
const
char
*
name
;
};
/**
* Reset block I/O protocol
*
* @v this Block I/O protocol
* @v extended Perform extended verification
* @ret efirc EFI status code
*/
static
EFI_STATUS
EFIAPI
efi_reset_blocks
(
EFI_BLOCK_IO_PROTOCOL
*
this
,
BOOLEAN
extended
)
{
struct
efi_block
*
block
=
container_of
(
this
,
struct
efi_block
,
block
);
void
*
retaddr
=
__builtin_return_address
(
0
);
DBG2
(
"EFI %s %sreset -> %p
\n
"
,
block
->
name
,
(
extended
?
"extended "
:
""
),
retaddr
);
return
0
;
}
/**
* Read blocks
*
* @v this Block I/O protocol
* @v media Media ID
* @v lba Starting LBA
* @v len Length of data
* @v data Data buffer
* @ret efirc EFI status code
*/
static
EFI_STATUS
EFIAPI
efi_read_blocks
(
EFI_BLOCK_IO_PROTOCOL
*
this
,
UINT32
media
,
EFI_LBA
lba
,
UINTN
len
,
VOID
*
data
)
{
struct
efi_block
*
block
=
container_of
(
this
,
struct
efi_block
,
block
);
void
*
retaddr
=
__builtin_return_address
(
0
);
DBG2
(
"EFI %s read media %08x LBA %#llx to %p+%zx -> %p
\n
"
,
block
->
name
,
media
,
lba
,
data
,
(
(
size_t
)
len
),
retaddr
);
vdisk_read
(
(
lba
+
block
->
lba
),
(
len
/
VDISK_SECTOR_SIZE
),
data
);
return
0
;
}
/**
* Write blocks
*
* @v this Block I/O protocol
* @v media Media ID
* @v lba Starting LBA
* @v len Length of data
* @v data Data buffer
* @ret efirc EFI status code
*/
static
EFI_STATUS
EFIAPI
efi_write_blocks
(
EFI_BLOCK_IO_PROTOCOL
*
this
__unused
,
UINT32
media
__unused
,
EFI_LBA
lba
__unused
,
UINTN
len
__unused
,
VOID
*
data
__unused
)
{
struct
efi_block
*
block
=
container_of
(
this
,
struct
efi_block
,
block
);
void
*
retaddr
=
__builtin_return_address
(
0
);
DBG2
(
"EFI %s write media %08x LBA %#llx from %p+%zx -> %p
\n
"
,
block
->
name
,
media
,
lba
,
data
,
(
(
size_t
)
len
),
retaddr
);
return
EFI_WRITE_PROTECTED
;
}
/**
* Flush block operations
*
* @v this Block I/O protocol
* @ret efirc EFI status code
*/
static
EFI_STATUS
EFIAPI
efi_flush_blocks
(
EFI_BLOCK_IO_PROTOCOL
*
this
)
{
struct
efi_block
*
block
=
container_of
(
this
,
struct
efi_block
,
block
);
void
*
retaddr
=
__builtin_return_address
(
0
);
DBG2
(
"EFI %s flush -> %p
\n
"
,
block
->
name
,
retaddr
);
return
0
;
}
/** GUID used in vendor device path */
#define EFIBLOCK_GUID { \
0x1322d197, 0x15dc, 0x4a45, \
{ 0xa6, 0xa4, 0xfa, 0x57, 0x05, 0x4e, 0xa6, 0x14 } \
}
/**
* Initialise vendor device path
*
* @v name Variable name
*/
#define EFIBLOCK_DEVPATH_VENDOR_INIT( name ) { \
.Header = EFI_DEVPATH_INIT ( name, HARDWARE_DEVICE_PATH, \
HW_VENDOR_DP ), \
.Guid = EFIBLOCK_GUID, \
}
/**
* Initialise ATA device path
*
* @v name Variable name
*/
#define EFIBLOCK_DEVPATH_ATA_INIT( name ) { \
.Header = EFI_DEVPATH_INIT ( name, MESSAGING_DEVICE_PATH, \
MSG_ATAPI_DP ), \
.PrimarySecondary = 0, \
.SlaveMaster = 0, \
.Lun = 0, \
}
/**
* Initialise hard disk device path
*
* @v name Variable name
*/
#define EFIBLOCK_DEVPATH_HD_INIT( name ) { \
.Header = EFI_DEVPATH_INIT ( name, MEDIA_DEVICE_PATH, \
MEDIA_HARDDRIVE_DP ), \
.PartitionNumber = 1, \
.PartitionStart = VDISK_PARTITION_LBA, \
.PartitionSize = VDISK_PARTITION_COUNT, \
.Signature[0] = ( ( VDISK_MBR_SIGNATURE >> 0 ) & 0xff ), \
.Signature[1] = ( ( VDISK_MBR_SIGNATURE >> 8 ) & 0xff ), \
.Signature[2] = ( ( VDISK_MBR_SIGNATURE >> 16 ) & 0xff ), \
.Signature[3] = ( ( VDISK_MBR_SIGNATURE >> 24 ) & 0xff ), \
.MBRType = MBR_TYPE_PCAT, \
.SignatureType = SIGNATURE_TYPE_MBR, \
}
/** Virtual disk media */
static
EFI_BLOCK_IO_MEDIA
efi_vdisk_media
=
{
.
MediaId
=
VDISK_MBR_SIGNATURE
,
.
MediaPresent
=
TRUE
,
.
LogicalPartition
=
FALSE
,
.
ReadOnly
=
TRUE
,
.
BlockSize
=
VDISK_SECTOR_SIZE
,
.
LastBlock
=
(
VDISK_COUNT
-
1
),
};
/** Virtual disk device path */
static
struct
{
VENDOR_DEVICE_PATH
vendor
;
ATAPI_DEVICE_PATH
ata
;
EFI_DEVICE_PATH_PROTOCOL
end
;
}
__attribute__
((
packed
))
efi_vdisk_path
=
{
.
vendor
=
EFIBLOCK_DEVPATH_VENDOR_INIT
(
efi_vdisk_path
.
vendor
),
.
ata
=
EFIBLOCK_DEVPATH_ATA_INIT
(
efi_vdisk_path
.
ata
),
.
end
=
EFI_DEVPATH_END_INIT
(
efi_vdisk_path
.
end
),
};
/** Virtual disk device */
static
struct
efi_block
efi_vdisk
=
{
.
block
=
{
.
Revision
=
EFI_BLOCK_IO_PROTOCOL_REVISION
,
.
Media
=
&
efi_vdisk_media
,
.
Reset
=
efi_reset_blocks
,
.
ReadBlocks
=
efi_read_blocks
,
.
WriteBlocks
=
efi_write_blocks
,
.
FlushBlocks
=
efi_flush_blocks
,
},
.
path
=
&
efi_vdisk_path
.
vendor
.
Header
,
.
lba
=
0
,
.
name
=
"vdisk"
,
};
/** Virtual partition media */
static
EFI_BLOCK_IO_MEDIA
efi_vpartition_media
=
{
.
MediaId
=
VDISK_MBR_SIGNATURE
,
.
MediaPresent
=
TRUE
,
.
LogicalPartition
=
TRUE
,
.
ReadOnly
=
TRUE
,
.
BlockSize
=
VDISK_SECTOR_SIZE
,
.
LastBlock
=
(
VDISK_PARTITION_COUNT
-
1
),
};
/** Virtual partition device path */
static
struct
{
VENDOR_DEVICE_PATH
vendor
;
ATAPI_DEVICE_PATH
ata
;
HARDDRIVE_DEVICE_PATH
hd
;
EFI_DEVICE_PATH_PROTOCOL
end
;
}
__attribute__
((
packed
))
efi_vpartition_path
=
{
.
vendor
=
EFIBLOCK_DEVPATH_VENDOR_INIT
(
efi_vpartition_path
.
vendor
),
.
ata
=
EFIBLOCK_DEVPATH_ATA_INIT
(
efi_vpartition_path
.
ata
),
.
hd
=
EFIBLOCK_DEVPATH_HD_INIT
(
efi_vpartition_path
.
hd
),
.
end
=
EFI_DEVPATH_END_INIT
(
efi_vpartition_path
.
end
),
};
/** Virtual partition device */
static
struct
efi_block
efi_vpartition
=
{
.
block
=
{
.
Revision
=
EFI_BLOCK_IO_PROTOCOL_REVISION
,
.
Media
=
&
efi_vpartition_media
,
.
Reset
=
efi_reset_blocks
,
.
ReadBlocks
=
efi_read_blocks
,
.
WriteBlocks
=
efi_write_blocks
,
.
FlushBlocks
=
efi_flush_blocks
,
},
.
path
=
&
efi_vpartition_path
.
vendor
.
Header
,
.
lba
=
VDISK_PARTITION_LBA
,
.
name
=
"vpartition"
,
};
/**
* Install block I/O protocols
*
* @ret vdisk New virtual disk handle
* @ret vpartition New virtual partition handle
*/
void
efi_install
(
EFI_HANDLE
*
vdisk
,
EFI_HANDLE
*
vpartition
)
{
EFI_BOOT_SERVICES
*
bs
=
efi_systab
->
BootServices
;
EFI_STATUS
efirc
;
/* Install virtual disk */
if
(
(
efirc
=
bs
->
InstallMultipleProtocolInterfaces
(
vdisk
,
&
efi_block_io_protocol_guid
,
&
efi_vdisk
.
block
,
&
efi_device_path_protocol_guid
,
efi_vdisk
.
path
,
NULL
)
)
!=
0
)
{
die
(
"Could not install disk block I/O protocols: %#lx
\n
"
,
(
(
unsigned
long
)
efirc
)
);
}
/* Install virtual partition */
if
(
(
efirc
=
bs
->
InstallMultipleProtocolInterfaces
(
vpartition
,
&
efi_block_io_protocol_guid
,
&
efi_vpartition
.
block
,
&
efi_device_path_protocol_guid
,
efi_vpartition
.
path
,
NULL
)
)
!=
0
)
{
die
(
"Could not install partition block I/O protocols: %#lx
\n
"
,
(
(
unsigned
long
)
efirc
)
);
}
}
/** Boot image path */
static
struct
{
VENDOR_DEVICE_PATH
vendor
;
ATAPI_DEVICE_PATH
ata
;
HARDDRIVE_DEVICE_PATH
hd
;
struct
{
EFI_DEVICE_PATH
header
;
CHAR16
name
[
sizeof
(
EFI_REMOVABLE_MEDIA_FILE_NAME
)
/
sizeof
(
CHAR16
)
];
}
__attribute__
((
packed
))
file
;
EFI_DEVICE_PATH_PROTOCOL
end
;
}
__attribute__
((
packed
))
efi_bootmgfw_path
=
{
.
vendor
=
EFIBLOCK_DEVPATH_VENDOR_INIT
(
efi_bootmgfw_path
.
vendor
),
.
ata
=
EFIBLOCK_DEVPATH_ATA_INIT
(
efi_bootmgfw_path
.
ata
),
.
hd
=
EFIBLOCK_DEVPATH_HD_INIT
(
efi_bootmgfw_path
.
hd
),
.
file
=
{
.
header
=
EFI_DEVPATH_INIT
(
efi_bootmgfw_path
.
file
,
MEDIA_DEVICE_PATH
,
MEDIA_FILEPATH_DP
),
.
name
=
EFI_REMOVABLE_MEDIA_FILE_NAME
,
},
.
end
=
EFI_DEVPATH_END_INIT
(
efi_bootmgfw_path
.
end
),
};
/** Boot image path */
EFI_DEVICE_PATH_PROTOCOL
*
bootmgfw_path
=
&
efi_bootmgfw_path
.
vendor
.
Header
;
wimboot/wimboot-2.7.3/src/efiblock.h
0 → 100644
View file @
93996cf7
#ifndef _EFIBLOCK_H
#define _EFIBLOCK_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
*
* EFI block device
*
*/
#include "efi.h"
#include "efi/Protocol/BlockIo.h"
#include "efi/Protocol/DevicePath.h"
extern
void
efi_install
(
EFI_HANDLE
*
vdisk
,
EFI_HANDLE
*
vpartition
);
extern
EFI_DEVICE_PATH_PROTOCOL
*
bootmgfw_path
;
#endif
/* _EFIBLOCK_H */
wimboot/wimboot-2.7.3/src/efiboot.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
*
* EFI boot manager invocation
*
*/
#include <stdio.h>
#include <string.h>
#include "wimboot.h"
#include "cmdline.h"
#include "vdisk.h"
#include "pause.h"
#include "efi.h"
#include "efi/Protocol/GraphicsOutput.h"
#include "efipath.h"
#include "efiboot.h"
/** Original OpenProtocol() method */
static
EFI_OPEN_PROTOCOL
orig_open_protocol
;
/**
* Intercept OpenProtocol()
*
* @v handle EFI handle
* @v protocol Protocol GUID
* @v interface Opened interface
* @v agent_handle Agent handle
* @v controller_handle Controller handle
* @v attributes Attributes
* @ret efirc EFI status code
*/
static
EFI_STATUS
EFIAPI
efi_open_protocol_wrapper
(
EFI_HANDLE
handle
,
EFI_GUID
*
protocol
,
VOID
**
interface
,
EFI_HANDLE
agent_handle
,
EFI_HANDLE
controller_handle
,
UINT32
attributes
)
{
static
unsigned
int
count
;
EFI_STATUS
efirc
;
/* Open the protocol */
if
(
(
efirc
=
orig_open_protocol
(
handle
,
protocol
,
interface
,
agent_handle
,
controller_handle
,
attributes
)
)
!=
0
)
{
return
efirc
;
}
/* Block first attempt by bootmgfw.efi to open
* EFI_GRAPHICS_OUTPUT_PROTOCOL. This forces error messages
* to be displayed in text mode (thereby avoiding the totally
* blank error screen if the fonts are missing). We must
* allow subsequent attempts to succeed, otherwise the OS will
* fail to boot.
*/
if
(
(
memcmp
(
protocol
,
&
efi_graphics_output_protocol_guid
,
sizeof
(
*
protocol
)
)
==
0
)
&&
(
count
++
==
0
)
&&
(
!
cmdline_gui
)
)
{
DBG
(
"Forcing text mode output
\n
"
);
return
EFI_INVALID_PARAMETER
;
}
return
0
;
}
/**
* Boot from EFI device
*
* @v file Virtual file
* @v path Device path
* @v device Device handle
*/
void
efi_boot
(
struct
vdisk_file
*
file
,
EFI_DEVICE_PATH_PROTOCOL
*
path
,
EFI_HANDLE
device
)
{
EFI_BOOT_SERVICES
*
bs
=
efi_systab
->
BootServices
;
union
{
EFI_LOADED_IMAGE_PROTOCOL
*
image
;
void
*
intf
;
}
loaded
;
EFI_PHYSICAL_ADDRESS
phys
;
void
*
data
;
unsigned
int
pages
;
EFI_HANDLE
handle
;
EFI_STATUS
efirc
;
/* Allocate memory */
pages
=
(
(
file
->
len
+
PAGE_SIZE
-
1
)
/
PAGE_SIZE
);
if
(
(
efirc
=
bs
->
AllocatePages
(
AllocateAnyPages
,
EfiBootServicesData
,
pages
,
&
phys
)
)
!=
0
)
{
die
(
"Could not allocate %d pages: %#lx
\n
"
,
pages
,
(
(
unsigned
long
)
efirc
)
);
}
data
=
(
(
void
*
)
(
intptr_t
)
phys
);
/* Read image */
file
->
read
(
file
,
data
,
0
,
file
->
len
);
DBG
(
"Read %s
\n
"
,
file
->
name
);
/* Load image */
if
(
(
efirc
=
bs
->
LoadImage
(
FALSE
,
efi_image_handle
,
path
,
data
,
file
->
len
,
&
handle
)
)
!=
0
)
{
die
(
"Could not load %s: %#lx
\n
"
,
file
->
name
,
(
(
unsigned
long
)
efirc
)
);
}
DBG
(
"Loaded %s
\n
"
,
file
->
name
);
/* Get loaded image protocol */
if
(
(
efirc
=
bs
->
OpenProtocol
(
handle
,
&
efi_loaded_image_protocol_guid
,
&
loaded
.
intf
,
efi_image_handle
,
NULL
,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
))
!=
0
){
die
(
"Could not get loaded image protocol for %s: %#lx
\n
"
,
file
->
name
,
(
(
unsigned
long
)
efirc
)
);
}
/* Force correct device handle */
if
(
loaded
.
image
->
DeviceHandle
!=
device
)
{
DBG
(
"Forcing correct DeviceHandle (%p->%p)
\n
"
,
loaded
.
image
->
DeviceHandle
,
device
);
loaded
.
image
->
DeviceHandle
=
device
;
}
/* Intercept calls to OpenProtocol() */
orig_open_protocol
=
loaded
.
image
->
SystemTable
->
BootServices
->
OpenProtocol
;
loaded
.
image
->
SystemTable
->
BootServices
->
OpenProtocol
=
efi_open_protocol_wrapper
;
/* Start image */
if
(
cmdline_pause
)
pause
();
if
(
(
efirc
=
bs
->
StartImage
(
handle
,
NULL
,
NULL
)
)
!=
0
)
{
die
(
"Could not start %s: %#lx
\n
"
,
file
->
name
,
(
(
unsigned
long
)
efirc
)
);
}
die
(
"%s returned
\n
"
,
file
->
name
);
}
wimboot/wimboot-2.7.3/src/efiboot.h
0 → 100644
View file @
93996cf7
#ifndef _EFIBOOT_H
#define _EFIBOOT_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
*
* EFI boot manager invocation
*
*/
#include "efi.h"
#include "efi/Protocol/DevicePath.h"
struct
vdisk_file
;
extern
void
efi_boot
(
struct
vdisk_file
*
file
,
EFI_DEVICE_PATH_PROTOCOL
*
path
,
EFI_HANDLE
device
);
#endif
/* _EFIBOOT_H */
wimboot/wimboot-2.7.3/src/efifile.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
*
* EFI file system access
*
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <wchar.h>
#include "wimboot.h"
#include "vdisk.h"
#include "cmdline.h"
#include "wimpatch.h"
#include "wimfile.h"
#include "efi.h"
#include "efifile.h"
/** bootmgfw.efi path within WIM */
static
const
wchar_t
bootmgfw_path
[]
=
L"
\\
Windows
\\
Boot
\\
EFI
\\
bootmgfw.efi"
;
/** Other paths within WIM */
static
const
wchar_t
*
efi_wim_paths
[]
=
{
L"
\\
Windows
\\
Boot
\\
DVD
\\
EFI
\\
boot.sdi"
,
L"
\\
Windows
\\
Boot
\\
DVD
\\
EFI
\\
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
};
/** bootmgfw.efi file */
struct
vdisk_file
*
bootmgfw
;
/**
* Get architecture-specific boot filename
*
* @ret bootarch Architecture-specific boot filename
*/
static
const
CHAR16
*
efi_bootarch
(
void
)
{
static
const
CHAR16
bootarch_full
[]
=
EFI_REMOVABLE_MEDIA_FILE_NAME
;
const
CHAR16
*
tmp
;
const
CHAR16
*
bootarch
=
bootarch_full
;
for
(
tmp
=
bootarch_full
;
*
tmp
;
tmp
++
)
{
if
(
*
tmp
==
L'\\'
)
bootarch
=
(
tmp
+
1
);
}
return
bootarch
;
}
/**
* Read from EFI file
*
* @v vfile Virtual file
* @v data Data buffer
* @v offset Offset
* @v len Length
*/
static
void
efi_read_file
(
struct
vdisk_file
*
vfile
,
void
*
data
,
size_t
offset
,
size_t
len
)
{
#if 0
EFI_FILE_PROTOCOL *file = vfile->opaque;
UINTN size = len;
EFI_STATUS efirc;
/* Set file position */
if ( ( efirc = file->SetPosition ( file, offset ) ) != 0 ) {
die ( "Could not set file position: %#lx\n",
( ( unsigned long ) efirc ) );
}
/* Read from file */
if ( ( efirc = file->Read ( file, &size, data ) ) != 0 ) {
die ( "Could not read from file: %#lx\n",
( ( unsigned long ) efirc ) );
}
#endif /* #if 0 */
(
void
)
vfile
;
pfventoy_file_read
((
const
char
*
)
vfile
->
opaque
,
(
int
)
offset
,
(
int
)
len
,
data
);
}
/**
* Patch BCD file
*
* @v vfile Virtual file
* @v data Data buffer
* @v offset Offset
* @v len Length
*/
static
void
efi_patch_bcd
(
struct
vdisk_file
*
vfile
__unused
,
void
*
data
,
size_t
offset
,
size_t
len
)
{
static
const
wchar_t
search
[]
=
L".exe"
;
static
const
wchar_t
replace
[]
=
L".efi"
;
size_t
i
;
/* Do nothing if BCD patching is disabled */
if
(
cmdline_rawbcd
)
return
;
/* Patch any occurrences of ".exe" to ".efi". In the common
* simple cases, this allows the same BCD file to be used for
* both BIOS and UEFI systems.
*/
for
(
i
=
0
;
(
i
+
sizeof
(
search
)
)
<
len
;
i
++
)
{
if
(
wcscasecmp
(
(
data
+
i
),
search
)
==
0
)
{
memcpy
(
(
data
+
i
),
replace
,
sizeof
(
replace
)
);
DBG
(
"...patched BCD at %#zx:
\"
%ls
\"
to
\"
%ls
\"\n
"
,
(
offset
+
i
),
search
,
replace
);
}
}
}
/**
* Extract files from EFI file system
*
* @v handle Device handle
*/
void
efi_extract
(
EFI_HANDLE
handle
)
{
struct
vdisk_file
*
wim
=
NULL
;
struct
vdisk_file
*
vfile
;
CHAR16
wname
[
64
];
int
i
,
j
,
k
;
char
*
pos
;
size_t
len
=
0
;
(
void
)
handle
;
/* Read root directory */
for
(
i
=
0
;
i
<
cmdline_vf_num
;
i
++
)
{
pos
=
strchr
(
cmdline_vf_path
[
i
],
':'
);
*
pos
=
0
;
k
=
(
int
)
strlen
(
cmdline_vf_path
[
i
]);
memset
(
wname
,
0
,
sizeof
(
wname
));
for
(
j
=
0
;
j
<
k
;
j
++
)
{
wname
[
j
]
=
cmdline_vf_path
[
i
][
j
];
}
len
=
pfventoy_file_size
(
pos
+
1
);
vfile
=
vdisk_add_file
(
cmdline_vf_path
[
i
],
pos
+
1
,
len
,
efi_read_file
);
/* Check for special-case files */
if
(
(
wcscasecmp
(
wname
,
efi_bootarch
()
)
==
0
)
||
(
wcscasecmp
(
wname
,
L"bootmgfw.efi"
)
==
0
)
)
{
DBG
(
"...found bootmgfw.efi file %ls
\n
"
,
wname
);
bootmgfw
=
vfile
;
}
else
if
(
wcscasecmp
(
wname
,
L"BCD"
)
==
0
)
{
DBG
(
"...found BCD
\n
"
);
vdisk_patch_file
(
vfile
,
efi_patch_bcd
);
}
else
if
(
wcscasecmp
(
(
wname
+
(
wcslen
(
wname
)
-
4
)
),
L".wim"
)
==
0
)
{
DBG
(
"...found WIM file %ls
\n
"
,
wname
);
wim
=
vfile
;
}
}
/* Process WIM image */
if
(
wim
)
{
vdisk_patch_file
(
wim
,
patch_wim
);
if
(
(
!
bootmgfw
)
&&
(
bootmgfw
=
wim_add_file
(
wim
,
cmdline_index
,
bootmgfw_path
,
efi_bootarch
()
)
)
)
{
DBG
(
"...extracted %ls
\n
"
,
bootmgfw_path
);
}
wim_add_files
(
wim
,
cmdline_index
,
efi_wim_paths
);
}
/* Check that we have a boot file */
if
(
!
bootmgfw
)
{
die
(
"FATAL: no %ls or bootmgfw.efi found
\n
"
,
efi_bootarch
()
);
}
}
wimboot/wimboot-2.7.3/src/efifile.h
0 → 100644
View file @
93996cf7
#ifndef _EFIFILE_H
#define _EFIFILE_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
*
* EFI file system access
*
*/
#include "efi.h"
#include "efi/Protocol/SimpleFileSystem.h"
#include "efi/Guid/FileInfo.h"
struct
vdisk_file
;
extern
struct
vdisk_file
*
bootmgfw
;
extern
void
efi_extract
(
EFI_HANDLE
handle
);
#endif
/* _EFIFILE_H */
wimboot/wimboot-2.7.3/src/efiguid.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
*
* EFI GUIDs
*
*/
#include "wimboot.h"
#include "efi.h"
#include "efi/Protocol/BlockIo.h"
#include "efi/Protocol/DevicePath.h"
#include "efi/Protocol/GraphicsOutput.h"
#include "efi/Protocol/LoadedImage.h"
#include "efi/Protocol/SimpleFileSystem.h"
/** Block I/O protocol GUID */
EFI_GUID
efi_block_io_protocol_guid
=
EFI_BLOCK_IO_PROTOCOL_GUID
;
/** Device path protocol GUID */
EFI_GUID
efi_device_path_protocol_guid
=
EFI_DEVICE_PATH_PROTOCOL_GUID
;
/** Graphics output protocol GUID */
EFI_GUID
efi_graphics_output_protocol_guid
=
EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
;
/** Loaded image protocol GUID */
EFI_GUID
efi_loaded_image_protocol_guid
=
EFI_LOADED_IMAGE_PROTOCOL_GUID
;
/** Simple file system protocol GUID */
EFI_GUID
efi_simple_file_system_protocol_guid
=
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID
;
wimboot/wimboot-2.7.3/src/efimain.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
*
* EFI entry point
*
*/
#include <stdio.h>
#include "wimboot.h"
#include "cmdline.h"
#include "efi.h"
#include "efifile.h"
#include "efiblock.h"
#include "efiboot.h"
/**
* Process command line
*
* @v loaded Loaded image protocol
*/
static
void
efi_cmdline
(
EFI_LOADED_IMAGE_PROTOCOL
*
loaded
)
{
size_t
cmdline_len
=
(
loaded
->
LoadOptionsSize
/
sizeof
(
wchar_t
)
);
char
cmdline
[
cmdline_len
+
1
/* NUL */
];
const
wchar_t
*
wcmdline
=
loaded
->
LoadOptions
;
/* Convert command line to ASCII */
snprintf
(
cmdline
,
sizeof
(
cmdline
),
"%ls"
,
wcmdline
);
/* Process command line */
process_cmdline
(
cmdline
);
}
/**
* EFI entry point
*
* @v image_handle Image handle
* @v systab EFI system table
* @ret efirc EFI status code
*/
EFI_STATUS
EFIAPI
efi_main
(
EFI_HANDLE
image_handle
,
EFI_SYSTEM_TABLE
*
systab
)
{
EFI_BOOT_SERVICES
*
bs
;
union
{
EFI_LOADED_IMAGE_PROTOCOL
*
image
;
void
*
interface
;
}
loaded
;
EFI_HANDLE
vdisk
=
NULL
;
EFI_HANDLE
vpartition
=
NULL
;
EFI_STATUS
efirc
;
/* Record EFI handle and system table */
efi_image_handle
=
image_handle
;
efi_systab
=
systab
;
bs
=
systab
->
BootServices
;
/* 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" );
/* Get loaded image protocol */
if
(
(
efirc
=
bs
->
OpenProtocol
(
image_handle
,
&
efi_loaded_image_protocol_guid
,
&
loaded
.
interface
,
image_handle
,
NULL
,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
))
!=
0
){
die
(
"Could not open loaded image protocol: %#lx
\n
"
,
(
(
unsigned
long
)
efirc
)
);
}
/* Process command line */
efi_cmdline
(
loaded
.
image
);
/* Extract files from file system */
efi_extract
(
loaded
.
image
->
DeviceHandle
);
/* Install virtual disk */
efi_install
(
&
vdisk
,
&
vpartition
);
/* Invoke boot manager */
efi_boot
(
bootmgfw
,
bootmgfw_path
,
vpartition
);
return
0
;
}
wimboot/wimboot-2.7.3/src/efipath.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
*
* EFI device paths
*
*/
#include "wimboot.h"
#include "efi.h"
#include "efipath.h"
/**
* Find end of device path
*
* @v path Path to device
* @ret path_end End of device path
*/
EFI_DEVICE_PATH_PROTOCOL
*
efi_devpath_end
(
EFI_DEVICE_PATH_PROTOCOL
*
path
)
{
while
(
path
->
Type
!=
END_DEVICE_PATH_TYPE
)
{
path
=
(
(
(
void
*
)
path
)
+
/* There's this amazing new-fangled thing known as
* a UINT16, but who wants to use one of those? */
(
(
path
->
Length
[
1
]
<<
8
)
|
path
->
Length
[
0
]
)
);
}
return
path
;
}
wimboot/wimboot-2.7.3/src/efipath.h
0 → 100644
View file @
93996cf7
#ifndef _EFIPATH_H
#define _EFIPATH_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
*
* EFI device paths
*
*/
#include "efi.h"
#include "efi/Protocol/DevicePath.h"
/**
* Initialise device path
*
* @v name Variable name
* @v type Type
* @v subtype Subtype
*/
#define EFI_DEVPATH_INIT( name, type, subtype ) { \
.Type = (type), \
.SubType = (subtype), \
.Length[0] = ( sizeof (name) & 0xff ), \
.Length[1] = ( sizeof (name) >> 8 ), \
}
/**
* Initialise device path
*
* @v path Device path
* @v type Type
* @v subtype Subtype
* @v len Length
*/
static
inline
__attribute__
((
always_inline
))
void
efi_devpath_init
(
EFI_DEVICE_PATH_PROTOCOL
*
path
,
unsigned
int
type
,
unsigned
int
subtype
,
size_t
len
)
{
path
->
Type
=
type
;
path
->
SubType
=
subtype
;
path
->
Length
[
0
]
=
(
len
&
0xff
);
path
->
Length
[
1
]
=
(
len
>>
8
);
}
/**
* Initialise device path end
*
* @v name Variable name
*/
#define EFI_DEVPATH_END_INIT( name ) \
EFI_DEVPATH_INIT ( name, END_DEVICE_PATH_TYPE, \
END_ENTIRE_DEVICE_PATH_SUBTYPE )
/**
* Initialise device path end
*
* @v path Device path
*/
static
inline
__attribute__
((
always_inline
))
void
efi_devpath_end_init
(
EFI_DEVICE_PATH_PROTOCOL
*
path
)
{
efi_devpath_init
(
path
,
END_DEVICE_PATH_TYPE
,
END_ENTIRE_DEVICE_PATH_SUBTYPE
,
sizeof
(
*
path
)
);
}
extern
EFI_DEVICE_PATH_PROTOCOL
*
efi_devpath_end
(
EFI_DEVICE_PATH_PROTOCOL
*
path
);
#endif
/* _EFIPATH_H */
wimboot/wimboot-2.7.3/src/efireloc.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
*
* EFI relocations
*
* Derived from iPXE's elf2efi.c
*
*/
#define PACKAGE "wimboot"
#define PACKAGE_VERSION VERSION
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <getopt.h>
#include <bfd.h>
#include "efi.h"
#include "efi/IndustryStandard/PeImage.h"
#include "wimboot.h"
#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
/* Maintain compatibility with binutils 2.34 */
#ifndef bfd_get_section_vma
#define bfd_get_section_vma(bfd, ptr) bfd_section_vma(ptr)
#endif
#ifndef bfd_get_section_flags
#define bfd_get_section_flags(bfd, ptr) bfd_section_flags(ptr)
#endif
/** PE header maximum length
*
* This maximum length is guaranteed by the fact that the PE headers
* have to fit entirely before the start of the bzImage header.
*/
#define PE_HEADER_LEN 512
/** .reloc section index */
#define RELOC_SECTION_INDEX 3
/** PE relocations */
struct
pe_relocs
{
struct
pe_relocs
*
next
;
unsigned
long
start_rva
;
unsigned
int
used_relocs
;
unsigned
int
total_relocs
;
uint16_t
*
relocs
;
};
/** Command-line options */
struct
options
{
/** Verbosity */
int
verbosity
;
};
/**
* Allocate memory
*
* @v len Length of memory to allocate
* @ret ptr Pointer to allocated memory
*/
static
void
*
xmalloc
(
size_t
len
)
{
void
*
ptr
;
ptr
=
malloc
(
len
);
if
(
!
ptr
)
{
eprintf
(
"Could not allocate %zd bytes
\n
"
,
len
);
exit
(
1
);
}
return
ptr
;
}
/**
* Write to file
*
* @v fd File descriptor
* @v data Data
* @v len Length of data
*/
static
void
xwrite
(
int
fd
,
const
void
*
data
,
size_t
len
)
{
ssize_t
written
;
written
=
write
(
fd
,
data
,
len
);
if
(
written
<
0
)
{
eprintf
(
"Could not write %zd bytes: %s
\n
"
,
len
,
strerror
(
errno
)
);
exit
(
1
);
}
if
(
(
size_t
)
written
!=
len
)
{
eprintf
(
"Wrote only %zd of %zd bytes
\n
"
,
written
,
len
);
exit
(
1
);
}
}
/**
* Seek to file position
*
* @v fd File descriptor
* @v offset Offset
* @v whence Origin
*/
static
void
xlseek
(
int
fd
,
off_t
offset
,
int
whence
)
{
off_t
pos
;
pos
=
lseek
(
fd
,
offset
,
whence
);
if
(
pos
<
0
)
{
eprintf
(
"Could not seek: %s
\n
"
,
strerror
(
errno
)
);
exit
(
1
);
}
}
/**
* Close file
*
* @v fd File descriptor
*/
static
void
xclose
(
int
fd
)
{
if
(
close
(
fd
)
<
0
)
{
eprintf
(
"Could not close: %s
\n
"
,
strerror
(
errno
)
);
exit
(
1
);
}
}
/**
* Open input BFD file
*
* @v filename File name
* @ret ibfd BFD file
*/
static
bfd
*
open_input_bfd
(
const
char
*
filename
)
{
bfd
*
bfd
;
/* Open the file */
bfd
=
bfd_openr
(
filename
,
NULL
);
if
(
!
bfd
)
{
eprintf
(
"Cannot open %s: "
,
filename
);
bfd_perror
(
NULL
);
exit
(
1
);
}
/* The call to bfd_check_format() must be present, otherwise
* we get a segfault from later BFD calls.
*/
if
(
!
bfd_check_format
(
bfd
,
bfd_object
)
)
{
eprintf
(
"%s is not an object file: "
,
filename
);
bfd_perror
(
NULL
);
exit
(
1
);
}
return
bfd
;
}
/**
* Read symbol table
*
* @v bfd BFD file
*/
static
asymbol
**
read_symtab
(
bfd
*
bfd
)
{
long
symtab_size
;
asymbol
**
symtab
;
long
symcount
;
/* Get symbol table size */
symtab_size
=
bfd_get_symtab_upper_bound
(
bfd
);
if
(
symtab_size
<
0
)
{
bfd_perror
(
"Could not get symbol table upper bound"
);
exit
(
1
);
}
/* Allocate and read symbol table */
symtab
=
xmalloc
(
symtab_size
);
symcount
=
bfd_canonicalize_symtab
(
bfd
,
symtab
);
if
(
symcount
<
0
)
{
bfd_perror
(
"Cannot read symbol table"
);
exit
(
1
);
}
return
symtab
;
}
/**
* Read relocation table
*
* @v bfd BFD file
* @v symtab Symbol table
* @v section Section
* @v symtab Symbol table
* @ret reltab Relocation table
*/
static
arelent
**
read_reltab
(
bfd
*
bfd
,
asymbol
**
symtab
,
asection
*
section
)
{
long
reltab_size
;
arelent
**
reltab
;
long
numrels
;
/* Get relocation table size */
reltab_size
=
bfd_get_reloc_upper_bound
(
bfd
,
section
);
if
(
reltab_size
<
0
)
{
bfd_perror
(
"Could not get relocation table upper bound"
);
exit
(
1
);
}
/* Allocate and read relocation table */
reltab
=
xmalloc
(
reltab_size
);
numrels
=
bfd_canonicalize_reloc
(
bfd
,
section
,
reltab
,
symtab
);
if
(
numrels
<
0
)
{
bfd_perror
(
"Cannot read relocation table"
);
exit
(
1
);
}
return
reltab
;
}
/**
* Generate entry in PE relocation table
*
* @v pe_reltab PE relocation table
* @v rva RVA
* @v size Size of relocation entry
*/
static
void
generate_pe_reloc
(
struct
pe_relocs
**
pe_reltab
,
unsigned
long
rva
,
size_t
size
)
{
unsigned
long
start_rva
;
uint16_t
reloc
;
struct
pe_relocs
*
pe_rel
;
uint16_t
*
relocs
;
/* Construct */
start_rva
=
(
rva
&
~
0xfff
);
reloc
=
(
rva
&
0xfff
);
switch
(
size
)
{
case
8
:
reloc
|=
0xa000
;
break
;
case
4
:
reloc
|=
0x3000
;
break
;
case
2
:
reloc
|=
0x2000
;
break
;
default:
eprintf
(
"Unsupported relocation size %zd
\n
"
,
size
);
exit
(
1
);
}
/* Locate or create PE relocation table */
for
(
pe_rel
=
*
pe_reltab
;
pe_rel
;
pe_rel
=
pe_rel
->
next
)
{
if
(
pe_rel
->
start_rva
==
start_rva
)
break
;
}
if
(
!
pe_rel
)
{
pe_rel
=
xmalloc
(
sizeof
(
*
pe_rel
)
);
memset
(
pe_rel
,
0
,
sizeof
(
*
pe_rel
)
);
pe_rel
->
next
=
*
pe_reltab
;
*
pe_reltab
=
pe_rel
;
pe_rel
->
start_rva
=
start_rva
;
}
/* Expand relocation list if necessary */
if
(
pe_rel
->
used_relocs
<
pe_rel
->
total_relocs
)
{
relocs
=
pe_rel
->
relocs
;
}
else
{
pe_rel
->
total_relocs
=
(
pe_rel
->
total_relocs
?
(
pe_rel
->
total_relocs
*
2
)
:
256
);
relocs
=
xmalloc
(
pe_rel
->
total_relocs
*
sizeof
(
pe_rel
->
relocs
[
0
]
)
);
memset
(
relocs
,
0
,
pe_rel
->
total_relocs
*
sizeof
(
pe_rel
->
relocs
[
0
]
)
);
memcpy
(
relocs
,
pe_rel
->
relocs
,
pe_rel
->
used_relocs
*
sizeof
(
pe_rel
->
relocs
[
0
]
)
);
free
(
pe_rel
->
relocs
);
pe_rel
->
relocs
=
relocs
;
}
/* Store relocation */
pe_rel
->
relocs
[
pe_rel
->
used_relocs
++
]
=
reloc
;
}
/**
* Process relocation record
*
* @v bfd BFD file
* @v section Section
* @v rel Relocation entry
* @v pe_reltab PE relocation table to fill in
*/
static
void
process_reloc
(
bfd
*
bfd
__unused
,
asection
*
section
,
arelent
*
rel
,
struct
pe_relocs
**
pe_reltab
)
{
reloc_howto_type
*
howto
=
rel
->
howto
;
asymbol
*
sym
=
*
(
rel
->
sym_ptr_ptr
);
unsigned
long
offset
=
(
bfd_get_section_vma
(
bfd
,
section
)
+
rel
->
address
-
BASE_ADDRESS
);
if
(
bfd_is_abs_section
(
sym
->
section
)
)
{
/* Skip absolute symbols; the symbol value won't
* change when the object is loaded.
*/
}
else
if
(
strcmp
(
howto
->
name
,
"R_X86_64_64"
)
==
0
)
{
/* Generate an 8-byte PE relocation */
generate_pe_reloc
(
pe_reltab
,
offset
,
8
);
}
else
if
(
(
strcmp
(
howto
->
name
,
"R_386_32"
)
==
0
)
||
(
strcmp
(
howto
->
name
,
"R_X86_64_32"
)
==
0
)
||
(
strcmp
(
howto
->
name
,
"R_X86_64_32S"
)
==
0
)
)
{
/* Generate a 4-byte PE relocation */
generate_pe_reloc
(
pe_reltab
,
offset
,
4
);
}
else
if
(
(
strcmp
(
howto
->
name
,
"R_386_16"
)
==
0
)
||
(
strcmp
(
howto
->
name
,
"R_X86_64_16"
)
==
0
)
)
{
/* Generate a 2-byte PE relocation */
generate_pe_reloc
(
pe_reltab
,
offset
,
2
);
}
else
if
(
(
strcmp
(
howto
->
name
,
"R_386_PC32"
)
==
0
)
||
(
strcmp
(
howto
->
name
,
"R_X86_64_PC32"
)
==
0
)
||
(
strcmp
(
howto
->
name
,
"R_X86_64_PLT32"
)
==
0
)
)
{
/* Skip PC-relative relocations; all relative offsets
* remain unaltered when the object is loaded.
*/
}
else
{
eprintf
(
"Unrecognised relocation type %s
\n
"
,
howto
->
name
);
exit
(
1
);
}
}
/**
* Calculate size of binary PE relocation table
*
* @v fh File handle
* @v pe_reltab PE relocation table
* @ret size Size of binary table
*/
static
size_t
output_pe_reltab
(
int
fd
,
struct
pe_relocs
*
pe_reltab
)
{
EFI_IMAGE_BASE_RELOCATION
header
;
struct
pe_relocs
*
pe_rel
;
static
uint8_t
pad
[
16
];
unsigned
int
num_relocs
;
size_t
size
;
size_t
pad_size
;
size_t
total_size
=
0
;
for
(
pe_rel
=
pe_reltab
;
pe_rel
;
pe_rel
=
pe_rel
->
next
)
{
num_relocs
=
(
(
pe_rel
->
used_relocs
+
1
)
&
~
1
);
size
=
(
sizeof
(
header
)
+
(
num_relocs
*
sizeof
(
uint16_t
)
)
);
pad_size
=
(
(
-
size
)
&
(
sizeof
(
pad
)
-
1
)
);
size
+=
pad_size
;
header
.
VirtualAddress
=
pe_rel
->
start_rva
;
header
.
SizeOfBlock
=
size
;
xwrite
(
fd
,
&
header
,
sizeof
(
header
)
);
xwrite
(
fd
,
pe_rel
->
relocs
,
(
num_relocs
*
sizeof
(
uint16_t
)
)
);
xwrite
(
fd
,
pad
,
pad_size
);
total_size
+=
size
;
}
return
total_size
;
}
/**
* Add relocation information
*
* @v elf_name ELF file name
* @v pe_name PE file name
*/
static
void
efireloc
(
const
char
*
elf_name
,
const
char
*
pe_name
)
{
struct
pe_relocs
*
pe_reltab
=
NULL
;
int
fd
;
EFI_IMAGE_DOS_HEADER
*
dos
;
EFI_IMAGE_OPTIONAL_HEADER_UNION
*
nt
;
EFI_IMAGE_DATA_DIRECTORY
*
data_dir
;
EFI_IMAGE_SECTION_HEADER
*
pe_sections
;
UINT32
*
image_size
;
bfd
*
bfd
;
asymbol
**
symtab
;
asection
*
section
;
arelent
**
reltab
;
arelent
**
rel
;
size_t
reloc_len
;
/* Open the output file */
fd
=
open
(
pe_name
,
O_RDWR
);
if
(
fd
<
0
)
{
eprintf
(
"Could not open %s: %s
\n
"
,
pe_name
,
strerror
(
errno
)
);
exit
(
1
);
}
/* Map the output file header */
dos
=
mmap
(
NULL
,
PE_HEADER_LEN
,
(
PROT_READ
|
PROT_WRITE
),
MAP_SHARED
,
fd
,
0
);
if
(
!
dos
)
{
eprintf
(
"Could not mmap %s: %s
\n
"
,
pe_name
,
strerror
(
errno
)
);
exit
(
1
);
}
/* Locate the modifiable fields within the output file header */
nt
=
(
(
(
void
*
)
dos
)
+
dos
->
e_lfanew
);
if
(
nt
->
Pe32
.
FileHeader
.
Machine
==
EFI_IMAGE_MACHINE_IA32
)
{
image_size
=
&
nt
->
Pe32
.
OptionalHeader
.
SizeOfImage
;
data_dir
=
nt
->
Pe32
.
OptionalHeader
.
DataDirectory
;
pe_sections
=
(
(
(
void
*
)
nt
)
+
sizeof
(
nt
->
Pe32
)
);
}
else
if
(
nt
->
Pe32Plus
.
FileHeader
.
Machine
==
EFI_IMAGE_MACHINE_X64
)
{
image_size
=
&
nt
->
Pe32Plus
.
OptionalHeader
.
SizeOfImage
;
data_dir
=
nt
->
Pe32Plus
.
OptionalHeader
.
DataDirectory
;
pe_sections
=
(
(
(
void
*
)
nt
)
+
sizeof
(
nt
->
Pe32Plus
)
);
}
else
{
eprintf
(
"Unrecognised machine type
\n
"
);
exit
(
1
);
}
/* Open the input file */
bfd
=
open_input_bfd
(
elf_name
);
symtab
=
read_symtab
(
bfd
);
/* For each input section, create the appropriate relocation records */
for
(
section
=
bfd
->
sections
;
section
;
section
=
section
->
next
)
{
/* Discard non-allocatable sections */
if
(
!
(
bfd_get_section_flags
(
bfd
,
section
)
&
SEC_ALLOC
)
)
continue
;
/* Add relocations from this section */
reltab
=
read_reltab
(
bfd
,
symtab
,
section
);
for
(
rel
=
reltab
;
*
rel
;
rel
++
)
process_reloc
(
bfd
,
section
,
*
rel
,
&
pe_reltab
);
free
(
reltab
);
}
/* Close input file */
bfd_close
(
bfd
);
/* Generate relocation section */
xlseek
(
fd
,
0
,
SEEK_END
);
reloc_len
=
output_pe_reltab
(
fd
,
pe_reltab
);
/* Modify image header */
*
image_size
+=
reloc_len
;
data_dir
[
EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
].
Size
=
reloc_len
;
pe_sections
[
RELOC_SECTION_INDEX
].
Misc
.
VirtualSize
=
reloc_len
;
pe_sections
[
RELOC_SECTION_INDEX
].
SizeOfRawData
=
reloc_len
;
/* Unmap output file header */
munmap
(
dos
,
PE_HEADER_LEN
);
/* Close output file */
xclose
(
fd
);
}
/**
* Print help
*
* @v program_name Program name
*/
static
void
print_help
(
const
char
*
program_name
)
{
eprintf
(
"Syntax: %s [-v|-q] infile outfile
\n
"
,
program_name
);
}
/**
* Parse command-line options
*
* @v argc Argument count
* @v argv Argument list
* @v opts Options structure to populate
*/
static
int
parse_options
(
const
int
argc
,
char
**
argv
,
struct
options
*
opts
)
{
int
c
;
while
(
1
)
{
int
option_index
=
0
;
static
struct
option
long_options
[]
=
{
{
"help"
,
0
,
NULL
,
'h'
},
{
"verbose"
,
0
,
NULL
,
'v'
},
{
"quiet"
,
0
,
NULL
,
'q'
},
{
0
,
0
,
0
,
0
}
};
if
(
(
c
=
getopt_long
(
argc
,
argv
,
"hvq"
,
long_options
,
&
option_index
)
)
==
-
1
)
{
break
;
}
switch
(
c
)
{
case
'v'
:
opts
->
verbosity
++
;
break
;
case
'q'
:
if
(
opts
->
verbosity
)
opts
->
verbosity
--
;
break
;
case
'h'
:
print_help
(
argv
[
0
]
);
exit
(
0
);
case
'?'
:
default:
exit
(
2
);
}
}
return
optind
;
}
/**
* Main program
*
* @v argc Number of arguments
* @v argv Command-line arguments
* @ret rc Return status code
*/
int
main
(
int
argc
,
char
**
argv
)
{
struct
options
opts
=
{
.
verbosity
=
0
,
};
int
infile_index
;
const
char
*
infile
;
const
char
*
outfile
;
/* Initialise libbfd */
bfd_init
();
/* Parse command-line arguments */
infile_index
=
parse_options
(
argc
,
argv
,
&
opts
);
if
(
argc
!=
(
infile_index
+
2
)
)
{
print_help
(
argv
[
0
]
);
exit
(
2
);
}
infile
=
argv
[
infile_index
];
outfile
=
argv
[
infile_index
+
1
];
/* Add relocation information */
efireloc
(
infile
,
outfile
);
return
0
;
}
wimboot/wimboot-2.7.3/src/errno.h
0 → 100644
View file @
93996cf7
#ifndef _ERRNO_H
#define _ERRNO_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
*
* Error numbers
*
*/
#endif
/* _ERRNO_H */
wimboot/wimboot-2.7.3/src/huffman.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
*
* Huffman alphabets
*
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "wimboot.h"
#include "huffman.h"
/**
* Transcribe binary value (for debugging)
*
* @v value Value
* @v bits Length of value (in bits)
* @ret string Transcribed value
*/
static
const
char
*
huffman_bin
(
unsigned
long
value
,
unsigned
int
bits
)
{
static
char
buf
[
(
8
*
sizeof
(
value
)
)
+
1
/* NUL */
];
char
*
out
=
buf
;
/* Sanity check */
assert
(
bits
<
sizeof
(
buf
)
);
/* Transcribe value */
while
(
bits
--
)
*
(
out
++
)
=
(
(
value
&
(
1
<<
bits
)
)
?
'1'
:
'0'
);
*
out
=
'\0'
;
return
buf
;
}
/**
* Dump Huffman alphabet (for debugging)
*
* @v alphabet Huffman alphabet
*/
static
void
__attribute__
((
unused
))
huffman_dump_alphabet
(
struct
huffman_alphabet
*
alphabet
)
{
struct
huffman_symbols
*
sym
;
unsigned
int
bits
;
unsigned
int
huf
;
unsigned
int
i
;
/* Dump symbol table for each utilised length */
for
(
bits
=
1
;
bits
<=
(
sizeof
(
alphabet
->
huf
)
/
sizeof
(
alphabet
->
huf
[
0
]
)
)
;
bits
++
)
{
sym
=
&
alphabet
->
huf
[
bits
-
1
];
if
(
sym
->
freq
==
0
)
continue
;
huf
=
(
sym
->
start
>>
sym
->
shift
);
DBG
(
"Huffman length %d start
\"
%s
\"
freq %d:"
,
bits
,
huffman_bin
(
huf
,
sym
->
bits
),
sym
->
freq
);
for
(
i
=
0
;
i
<
sym
->
freq
;
i
++
)
{
DBG
(
" %03x"
,
sym
->
raw
[
huf
+
i
]
);
}
DBG
(
"
\n
"
);
}
/* Dump quick lookup table */
DBG
(
"Huffman quick lookup:"
);
for
(
i
=
0
;
i
<
(
sizeof
(
alphabet
->
lookup
)
/
sizeof
(
alphabet
->
lookup
[
0
]
)
)
;
i
++
)
{
DBG
(
" %d"
,
(
alphabet
->
lookup
[
i
]
+
1
)
);
}
DBG
(
"
\n
"
);
}
/**
* Construct Huffman alphabet
*
* @v alphabet Huffman alphabet
* @v lengths Symbol length table
* @v count Number of symbols
* @ret rc Return status code
*/
int
huffman_alphabet
(
struct
huffman_alphabet
*
alphabet
,
uint8_t
*
lengths
,
unsigned
int
count
)
{
struct
huffman_symbols
*
sym
;
unsigned
int
huf
;
unsigned
int
cum_freq
;
unsigned
int
bits
;
unsigned
int
raw
;
unsigned
int
adjustment
;
unsigned
int
prefix
;
int
empty
;
int
complete
;
/* Clear symbol table */
memset
(
alphabet
->
huf
,
0
,
sizeof
(
alphabet
->
huf
)
);
/* Count number of symbols with each Huffman-coded length */
empty
=
1
;
for
(
raw
=
0
;
raw
<
count
;
raw
++
)
{
bits
=
lengths
[
raw
];
if
(
bits
)
{
alphabet
->
huf
[
bits
-
1
].
freq
++
;
empty
=
0
;
}
}
/* In the degenerate case of having no symbols (i.e. an unused
* alphabet), generate a trivial alphabet with exactly two
* single-bit codes. This allows callers to avoid having to
* check for this special case.
*/
if
(
empty
)
alphabet
->
huf
[
0
].
freq
=
2
;
/* Populate Huffman-coded symbol table */
huf
=
0
;
cum_freq
=
0
;
for
(
bits
=
1
;
bits
<=
(
sizeof
(
alphabet
->
huf
)
/
sizeof
(
alphabet
->
huf
[
0
]
)
)
;
bits
++
)
{
sym
=
&
alphabet
->
huf
[
bits
-
1
];
sym
->
bits
=
bits
;
sym
->
shift
=
(
HUFFMAN_BITS
-
bits
);
sym
->
start
=
(
huf
<<
sym
->
shift
);
sym
->
raw
=
&
alphabet
->
raw
[
cum_freq
];
huf
+=
sym
->
freq
;
if
(
huf
>
(
1U
<<
bits
)
)
{
DBG
(
"Huffman alphabet has too many symbols with "
"lengths <=%d
\n
"
,
bits
);
return
-
1
;
}
huf
<<=
1
;
cum_freq
+=
sym
->
freq
;
}
complete
=
(
huf
==
(
1U
<<
bits
)
);
/* Populate raw symbol table */
for
(
raw
=
0
;
raw
<
count
;
raw
++
)
{
bits
=
lengths
[
raw
];
if
(
bits
)
{
sym
=
&
alphabet
->
huf
[
bits
-
1
];
*
(
sym
->
raw
++
)
=
raw
;
}
}
/* Adjust Huffman-coded symbol table raw pointers and populate
* quick lookup table.
*/
for
(
bits
=
1
;
bits
<=
(
sizeof
(
alphabet
->
huf
)
/
sizeof
(
alphabet
->
huf
[
0
]
)
)
;
bits
++
)
{
sym
=
&
alphabet
->
huf
[
bits
-
1
];
/* Adjust raw pointer */
sym
->
raw
-=
sym
->
freq
;
/* Reset to first symbol */
adjustment
=
(
sym
->
start
>>
sym
->
shift
);
sym
->
raw
-=
adjustment
;
/* Adjust for quick indexing */
/* Populate quick lookup table */
for
(
prefix
=
(
sym
->
start
>>
HUFFMAN_QL_SHIFT
)
;
prefix
<
(
1
<<
HUFFMAN_QL_BITS
)
;
prefix
++
)
{
alphabet
->
lookup
[
prefix
]
=
(
bits
-
1
);
}
}
/* Check that there are no invalid codes */
if
(
!
complete
)
{
DBG
(
"Huffman alphabet is incomplete
\n
"
);
return
-
1
;
}
return
0
;
}
/**
* Get Huffman symbol set
*
* @v alphabet Huffman alphabet
* @v huf Raw input value (normalised to HUFFMAN_BITS bits)
* @ret sym Huffman symbol set
*/
struct
huffman_symbols
*
huffman_sym
(
struct
huffman_alphabet
*
alphabet
,
unsigned
int
huf
)
{
struct
huffman_symbols
*
sym
;
unsigned
int
lookup_index
;
/* Find symbol set for this length */
lookup_index
=
(
huf
>>
HUFFMAN_QL_SHIFT
);
sym
=
&
alphabet
->
huf
[
alphabet
->
lookup
[
lookup_index
]
];
while
(
huf
<
sym
->
start
)
sym
--
;
return
sym
;
}
wimboot/wimboot-2.7.3/src/huffman.h
0 → 100644
View file @
93996cf7
#ifndef _HUFFMAN_H
#define _HUFFMAN_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
*
* Huffman alphabets
*
*/
#include <stdint.h>
/** Maximum length of a Huffman symbol (in bits) */
#define HUFFMAN_BITS 16
/** Raw huffman symbol */
typedef
uint16_t
huffman_raw_symbol_t
;
/** Quick lookup length for a Huffman symbol (in bits)
*
* This is a policy decision.
*/
#define HUFFMAN_QL_BITS 7
/** Quick lookup shift */
#define HUFFMAN_QL_SHIFT ( HUFFMAN_BITS - HUFFMAN_QL_BITS )
/** A Huffman-coded set of symbols of a given length */
struct
huffman_symbols
{
/** Length of Huffman-coded symbols (in bits) */
uint8_t
bits
;
/** Shift to normalise symbols of this length to HUFFMAN_BITS bits */
uint8_t
shift
;
/** Number of Huffman-coded symbols having this length */
uint16_t
freq
;
/** First symbol of this length (normalised to HUFFMAN_BITS bits)
*
* Stored as a 32-bit value to allow the value
* (1<<HUFFMAN_BITS ) to be used for empty sets of symbols
* longer than the maximum utilised length.
*/
uint32_t
start
;
/** Raw symbols having this length */
huffman_raw_symbol_t
*
raw
;
};
/** A Huffman-coded alphabet */
struct
huffman_alphabet
{
/** Huffman-coded symbol set for each length */
struct
huffman_symbols
huf
[
HUFFMAN_BITS
];
/** Quick lookup table */
uint8_t
lookup
[
1
<<
HUFFMAN_QL_BITS
];
/** Raw symbols
*
* Ordered by Huffman-coded symbol length, then by symbol
* value. This field has a variable length.
*/
huffman_raw_symbol_t
raw
[
0
];
};
/**
* Get Huffman symbol length
*
* @v sym Huffman symbol set
* @ret len Length (in bits)
*/
static
inline
__attribute__
((
always_inline
))
unsigned
int
huffman_len
(
struct
huffman_symbols
*
sym
)
{
return
sym
->
bits
;
}
/**
* Get Huffman symbol value
*
* @v sym Huffman symbol set
* @v huf Raw input value (normalised to HUFFMAN_BITS bits)
* @ret raw Raw symbol value
*/
static
inline
__attribute__
((
always_inline
))
huffman_raw_symbol_t
huffman_raw
(
struct
huffman_symbols
*
sym
,
unsigned
int
huf
)
{
return
sym
->
raw
[
huf
>>
sym
->
shift
];
}
extern
int
huffman_alphabet
(
struct
huffman_alphabet
*
alphabet
,
uint8_t
*
lengths
,
unsigned
int
count
);
extern
struct
huffman_symbols
*
huffman_sym
(
struct
huffman_alphabet
*
alphabet
,
unsigned
int
huf
);
#endif
/* _HUFFMAN_H */
wimboot/wimboot-2.7.3/src/i386.i
0 → 100644
View file @
93996cf7
.
code32
wimboot/wimboot-2.7.3/src/int13.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
*
* INT 13 emulation
*
*/
#include <string.h>
#include <stdio.h>
#include "wimboot.h"
#include "int13.h"
#include "vdisk.h"
/** Emulated drive number */
static
int
vdisk_drive
;
/**
* Initialise emulation
*
* @ret drive Emulated drive number
*/
int
initialise_int13
(
void
)
{
/* Determine drive number */
vdisk_drive
=
(
0x80
|
INT13_DRIVE_COUNT
++
);
DBG
(
"Emulating drive %#02x
\n
"
,
vdisk_drive
);
return
vdisk_drive
;
}
/**
* INT 13, 08 - Get drive parameters
*
* @ret ch Low bits of maximum cylinder number
* @ret cl (bits 7:6) High bits of maximum cylinder number
* @ret cl (bits 5:0) Maximum sector number
* @ret dh Maximum head number
* @ret dl Number of drives
* @ret ah Status code
*/
static
void
int13_get_parameters
(
struct
bootapp_callback_params
*
params
)
{
unsigned
int
max_cylinder
=
(
VDISK_CYLINDERS
-
1
);
unsigned
int
max_head
=
(
VDISK_HEADS
-
1
);
unsigned
int
max_sector
=
(
VDISK_SECTORS_PER_TRACK
-
0
/* sic */
);
unsigned
int
num_drives
;
unsigned
int
min_num_drives
;
/* Calculate number of drives to report */
num_drives
=
INT13_DRIVE_COUNT
;
min_num_drives
=
(
(
vdisk_drive
&
0x7f
)
+
1
);
if
(
num_drives
<
min_num_drives
)
num_drives
=
min_num_drives
;
/* Fill in drive parameters */
params
->
ch
=
(
max_cylinder
&
0xff
);
params
->
cl
=
(
(
(
max_cylinder
>>
8
)
<<
6
)
|
max_sector
);
params
->
dh
=
max_head
;
params
->
dl
=
num_drives
;
DBG2
(
"Get parameters: C/H/S = %d/%d/%d, drives = %d
\n
"
,
(
max_cylinder
+
1
),
(
max_head
+
1
),
max_sector
,
num_drives
);
/* Success */
params
->
ah
=
0
;
}
/**
* INT 13, 15 - Get disk type
*
* @ret cx:dx Sector count
* @ret ah Type code
*/
static
void
int13_get_disk_type
(
struct
bootapp_callback_params
*
params
)
{
uint32_t
sector_count
=
VDISK_COUNT
;
uint8_t
drive_type
=
INT13_DISK_TYPE_HDD
;
/* Fill in disk type */
params
->
cx
=
(
sector_count
>>
16
);
params
->
dx
=
(
sector_count
&
0xffff
);
params
->
ah
=
drive_type
;
DBG2
(
"Get disk type: sectors = %#08x, type = %d
\n
"
,
sector_count
,
drive_type
);
}
/**
* INT 13, 41 - Extensions installation check
*
* @v bx 0x55aa
* @ret bx 0xaa55
* @ret cx Extensions API support bitmap
* @ret ah API version
*/
static
void
int13_extension_check
(
struct
bootapp_callback_params
*
params
)
{
/* Fill in extension information */
params
->
bx
=
0xaa55
;
params
->
cx
=
INT13_EXTENSION_LINEAR
;
params
->
ah
=
INT13_EXTENSION_VER_1_X
;
DBG2
(
"Extensions installation check
\n
"
);
}
/**
* INT 13, 48 - Get extended parameters
*
* @v ds:si Drive parameter table
* @ret ah Status code
*/
static
void
int13_get_extended_parameters
(
struct
bootapp_callback_params
*
params
)
{
struct
int13_disk_parameters
*
disk_params
;
/* Fill in extended parameters */
disk_params
=
REAL_PTR
(
params
->
ds
,
params
->
si
);
memset
(
disk_params
,
0
,
sizeof
(
*
disk_params
)
);
disk_params
->
bufsize
=
sizeof
(
*
disk_params
);
disk_params
->
flags
=
INT13_FL_DMA_TRANSPARENT
;
disk_params
->
cylinders
=
VDISK_CYLINDERS
;
disk_params
->
heads
=
VDISK_HEADS
;
disk_params
->
sectors_per_track
=
VDISK_SECTORS_PER_TRACK
;
disk_params
->
sectors
=
VDISK_COUNT
;
disk_params
->
sector_size
=
VDISK_SECTOR_SIZE
;
DBG2
(
"Get extended parameters: C/H/S = %d/%d/%d, sectors = %#08llx "
"(%d bytes)
\n
"
,
disk_params
->
cylinders
,
disk_params
->
heads
,
disk_params
->
sectors_per_track
,
disk_params
->
sectors
,
disk_params
->
sector_size
);
/* Success */
params
->
ah
=
0
;
}
/**
* INT 13, 42 - Extended read
*
* @v ds:si Disk address packet
* @ret ah Status code
*/
static
void
int13_extended_read
(
struct
bootapp_callback_params
*
params
)
{
struct
int13_disk_address
*
disk_address
;
void
*
data
;
/* Read from emulated disk */
disk_address
=
REAL_PTR
(
params
->
ds
,
params
->
si
);
data
=
REAL_PTR
(
disk_address
->
buffer
.
segment
,
disk_address
->
buffer
.
offset
);
vdisk_read
(
disk_address
->
lba
,
disk_address
->
count
,
data
);
/* Success */
params
->
ah
=
0
;
}
/**
* Emulate INT 13 drive
*
* @v params Parameters
*/
void
emulate_int13
(
struct
bootapp_callback_params
*
params
)
{
int
command
=
params
->
ah
;
int
drive
=
params
->
dl
;
int
min_num_drives
;
unsigned
long
eflags
;
if
(
drive
==
vdisk_drive
)
{
/* Emulated drive - handle internally */
/* Populate eflags with a sensible starting value */
__asm__
(
"pushf
\n\t
"
"pop %0
\n\t
"
:
"=r"
(
eflags
)
);
params
->
eflags
=
(
eflags
&
~
CF
);
/* Handle command */
switch
(
command
)
{
case
INT13_GET_PARAMETERS
:
int13_get_parameters
(
params
);
break
;
case
INT13_GET_DISK_TYPE
:
int13_get_disk_type
(
params
);
break
;
case
INT13_EXTENSION_CHECK
:
int13_extension_check
(
params
);
break
;
case
INT13_GET_EXTENDED_PARAMETERS
:
int13_get_extended_parameters
(
params
);
break
;
case
INT13_EXTENDED_READ
:
int13_extended_read
(
params
);
break
;
default:
DBG
(
"Unrecognised INT 13,%02x
\n
"
,
command
);
params
->
eflags
|=
CF
;
break
;
}
}
else
{
/* Pass through command to underlying INT 13 */
call_interrupt
(
params
);
/* Modify drive count, if applicable */
if
(
command
==
INT13_GET_PARAMETERS
)
{
min_num_drives
=
(
(
vdisk_drive
&
0x7f
)
+
1
);
if
(
params
->
dl
<
min_num_drives
)
params
->
dl
=
min_num_drives
;
}
}
}
wimboot/wimboot-2.7.3/src/int13.h
0 → 100644
View file @
93996cf7
#ifndef _INT13_H
#define _INT13_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
*
* INT 13 emulation
*
*/
/** Construct a pointer from a real-mode segment:offset address */
#define REAL_PTR( segment, offset ) \
( ( void * ) ( intptr_t ) ( ( (segment) << 4 ) + offset ) )
/** Get drive parameters */
#define INT13_GET_PARAMETERS 0x08
/** Get disk type */
#define INT13_GET_DISK_TYPE 0x15
/** Extensions installation check */
#define INT13_EXTENSION_CHECK 0x41
/** Extended read */
#define INT13_EXTENDED_READ 0x42
/** Get extended drive parameters */
#define INT13_GET_EXTENDED_PARAMETERS 0x48
/** Operation completed successfully */
#define INT13_STATUS_SUCCESS 0x00
/** Invalid function or parameter */
#define INT13_STATUS_INVALID 0x01
/** Read error */
#define INT13_STATUS_READ_ERROR 0x04
/** Reset failed */
#define INT13_STATUS_RESET_FAILED 0x05
/** Write error */
#define INT13_STATUS_WRITE_ERROR 0xcc
/** No such drive */
#define INT13_DISK_TYPE_NONE 0x00
/** Floppy without change-line support */
#define INT13_DISK_TYPE_FDD 0x01
/** Floppy with change-line support */
#define INT13_DISK_TYPE_FDD_CL 0x02
/** Hard disk */
#define INT13_DISK_TYPE_HDD 0x03
/** Extended disk access functions supported */
#define INT13_EXTENSION_LINEAR 0x01
/** INT13 extensions version 1.x */
#define INT13_EXTENSION_VER_1_X 0x01
/** DMA boundary errors handled transparently */
#define INT13_FL_DMA_TRANSPARENT 0x01
/** BIOS drive counter */
#define INT13_DRIVE_COUNT ( *( ( ( uint8_t * ) REAL_PTR ( 0x40, 0x75 ) ) ) )
/** An INT 13 disk address packet */
struct
int13_disk_address
{
/** Size of the packet, in bytes */
uint8_t
bufsize
;
/** Reserved */
uint8_t
reserved_a
;
/** Block count */
uint8_t
count
;
/** Reserved */
uint8_t
reserved_b
;
/** Data buffer */
struct
segoff
buffer
;
/** Starting block number */
uint64_t
lba
;
/** Data buffer (EDD 3.0+ only) */
uint64_t
buffer_phys
;
/** Block count (EDD 4.0+ only) */
uint32_t
long_count
;
/** Reserved */
uint32_t
reserved_c
;
}
__attribute__
((
packed
));
/** INT 13 disk parameters */
struct
int13_disk_parameters
{
/** Size of this structure */
uint16_t
bufsize
;
/** Flags */
uint16_t
flags
;
/** Number of cylinders */
uint32_t
cylinders
;
/** Number of heads */
uint32_t
heads
;
/** Number of sectors per track */
uint32_t
sectors_per_track
;
/** Total number of sectors on drive */
uint64_t
sectors
;
/** Bytes per sector */
uint16_t
sector_size
;
}
__attribute__
((
packed
));
extern
int
initialise_int13
(
void
);
extern
void
emulate_int13
(
struct
bootapp_callback_params
*
params
);
#endif
/* _INT13_H */
wimboot/wimboot-2.7.3/src/ipxe/vsprintf.c
0 → 100644
View file @
93996cf7
/*
* Copyright (C) 2006 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.
*/
FILE_LICENCE
(
GPL2_OR_LATER
);
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include <wchar.h>
#include <ipxe/vsprintf.h>
/** @file */
#define CHAR_LEN 0
/**< "hh" length modifier */
#define SHORT_LEN 1
/**< "h" length modifier */
#define INT_LEN 2
/**< no length modifier */
#define LONG_LEN 3
/**< "l" length modifier */
#define LONGLONG_LEN 4
/**< "ll" length modifier */
#define SIZE_T_LEN 5
/**< "z" length modifier */
static
uint8_t
type_sizes
[]
=
{
[
CHAR_LEN
]
=
sizeof
(
char
),
[
SHORT_LEN
]
=
sizeof
(
short
),
[
INT_LEN
]
=
sizeof
(
int
),
[
LONG_LEN
]
=
sizeof
(
long
),
[
LONGLONG_LEN
]
=
sizeof
(
long
long
),
[
SIZE_T_LEN
]
=
sizeof
(
size_t
),
};
/**
* Use lower-case for hexadecimal digits
*
* Note that this value is set to 0x20 since that makes for very
* efficient calculations. (Bitwise-ORing with @c LCASE converts to a
* lower-case character, for example.)
*/
#define LCASE 0x20
/**
* Use "alternate form"
*
* For hexadecimal numbers, this means to add a "0x" or "0X" prefix to
* the number.
*/
#define ALT_FORM 0x02
/**
* Use zero padding
*
* Note that this value is set to 0x10 since that allows the pad
* character to be calculated as @c 0x20|(flags&ZPAD)
*/
#define ZPAD 0x10
/**
* Format a hexadecimal number
*
* @v end End of buffer to contain number
* @v num Number to format
* @v width Minimum field width
* @v flags Format flags
* @ret ptr End of buffer
*
* Fills a buffer in reverse order with a formatted hexadecimal
* number. The number will be zero-padded to the specified width.
* Lower-case and "alternate form" (i.e. "0x" prefix) flags may be
* set.
*
* There must be enough space in the buffer to contain the largest
* number that this function can format.
*/
static
char
*
format_hex
(
char
*
end
,
unsigned
long
long
num
,
int
width
,
int
flags
)
{
char
*
ptr
=
end
;
int
case_mod
=
(
flags
&
LCASE
);
int
pad
=
(
(
flags
&
ZPAD
)
|
' '
);
/* Generate the number */
do
{
*
(
--
ptr
)
=
"0123456789ABCDEF"
[
num
&
0xf
]
|
case_mod
;
num
>>=
4
;
}
while
(
num
);
/* Pad to width */
while
(
(
end
-
ptr
)
<
width
)
*
(
--
ptr
)
=
pad
;
/* Add "0x" or "0X" if alternate form specified */
if
(
flags
&
ALT_FORM
)
{
*
(
--
ptr
)
=
'X'
|
case_mod
;
*
(
--
ptr
)
=
'0'
;
}
return
ptr
;
}
/**
* Format a decimal number
*
* @v end End of buffer to contain number
* @v num Number to format
* @v width Minimum field width
* @v flags Format flags
* @ret ptr End of buffer
*
* Fills a buffer in reverse order with a formatted decimal number.
* The number will be space-padded to the specified width.
*
* There must be enough space in the buffer to contain the largest
* number that this function can format.
*/
static
char
*
format_decimal
(
char
*
end
,
signed
long
num
,
int
width
,
int
flags
)
{
char
*
ptr
=
end
;
int
negative
=
0
;
int
zpad
=
(
flags
&
ZPAD
);
int
pad
=
(
zpad
|
' '
);
/* Generate the number */
if
(
num
<
0
)
{
negative
=
1
;
num
=
-
num
;
}
do
{
*
(
--
ptr
)
=
'0'
+
(
num
%
10
);
num
/=
10
;
}
while
(
num
);
/* Add "-" if necessary */
if
(
negative
&&
(
!
zpad
)
)
*
(
--
ptr
)
=
'-'
;
/* Pad to width */
while
(
(
end
-
ptr
)
<
width
)
*
(
--
ptr
)
=
pad
;
/* Add "-" if necessary */
if
(
negative
&&
zpad
)
*
ptr
=
'-'
;
return
ptr
;
}
/**
* Print character via a printf context
*
* @v ctx Context
* @v c Character
*
* Call's the printf_context::handler() method and increments
* printf_context::len.
*/
static
inline
void
cputchar
(
struct
printf_context
*
ctx
,
unsigned
int
c
)
{
ctx
->
handler
(
ctx
,
c
);
++
ctx
->
len
;
}
/**
* Write a formatted string to a printf context
*
* @v ctx Context
* @v fmt Format string
* @v args Arguments corresponding to the format string
* @ret len Length of formatted string
*/
size_t
vcprintf
(
struct
printf_context
*
ctx
,
const
char
*
fmt
,
va_list
args
)
{
int
flags
;
int
width
;
uint8_t
*
length
;
char
*
ptr
;
char
tmp_buf
[
32
];
/* 32 is enough for all numerical formats.
* Insane width fields could overflow this buffer. */
wchar_t
*
wptr
;
/* Initialise context */
ctx
->
len
=
0
;
for
(
;
*
fmt
;
fmt
++
)
{
/* Pass through ordinary characters */
if
(
*
fmt
!=
'%'
)
{
cputchar
(
ctx
,
*
fmt
);
continue
;
}
fmt
++
;
/* Process flag characters */
flags
=
0
;
for
(
;
;
fmt
++
)
{
if
(
*
fmt
==
'#'
)
{
flags
|=
ALT_FORM
;
}
else
if
(
*
fmt
==
'0'
)
{
flags
|=
ZPAD
;
}
else
{
/* End of flag characters */
break
;
}
}
/* Process field width */
width
=
0
;
for
(
;
;
fmt
++
)
{
if
(
(
(
unsigned
)
(
*
fmt
-
'0'
)
)
<
10
)
{
width
=
(
width
*
10
)
+
(
*
fmt
-
'0'
);
}
else
{
break
;
}
}
/* We don't do floating point */
/* Process length modifier */
length
=
&
type_sizes
[
INT_LEN
];
for
(
;
;
fmt
++
)
{
if
(
*
fmt
==
'h'
)
{
length
--
;
}
else
if
(
*
fmt
==
'l'
)
{
length
++
;
}
else
if
(
*
fmt
==
'z'
)
{
length
=
&
type_sizes
[
SIZE_T_LEN
];
}
else
{
break
;
}
}
/* Process conversion specifier */
ptr
=
tmp_buf
+
sizeof
(
tmp_buf
)
-
1
;
*
ptr
=
'\0'
;
wptr
=
NULL
;
if
(
*
fmt
==
'c'
)
{
if
(
length
<
&
type_sizes
[
LONG_LEN
]
)
{
cputchar
(
ctx
,
va_arg
(
args
,
unsigned
int
)
);
}
else
{
wchar_t
wc
;
size_t
len
;
wc
=
va_arg
(
args
,
wint_t
);
len
=
wcrtomb
(
tmp_buf
,
wc
,
NULL
);
tmp_buf
[
len
]
=
'\0'
;
ptr
=
tmp_buf
;
}
}
else
if
(
*
fmt
==
's'
)
{
if
(
length
<
&
type_sizes
[
LONG_LEN
]
)
{
ptr
=
va_arg
(
args
,
char
*
);
}
else
{
wptr
=
va_arg
(
args
,
wchar_t
*
);
}
if
(
(
ptr
==
NULL
)
&&
(
wptr
==
NULL
)
)
ptr
=
"<NULL>"
;
}
else
if
(
*
fmt
==
'p'
)
{
intptr_t
ptrval
;
ptrval
=
(
intptr_t
)
va_arg
(
args
,
void
*
);
ptr
=
format_hex
(
ptr
,
ptrval
,
width
,
(
ALT_FORM
|
LCASE
)
);
}
else
if
(
(
*
fmt
&
~
0x20
)
==
'X'
)
{
unsigned
long
long
hex
;
flags
|=
(
*
fmt
&
0x20
);
/* LCASE */
if
(
*
length
>=
sizeof
(
unsigned
long
long
)
)
{
hex
=
va_arg
(
args
,
unsigned
long
long
);
}
else
if
(
*
length
>=
sizeof
(
unsigned
long
)
)
{
hex
=
va_arg
(
args
,
unsigned
long
);
}
else
{
hex
=
va_arg
(
args
,
unsigned
int
);
}
ptr
=
format_hex
(
ptr
,
hex
,
width
,
flags
);
}
else
if
(
(
*
fmt
==
'd'
)
||
(
*
fmt
==
'i'
)
){
signed
long
decimal
;
if
(
*
length
>=
sizeof
(
signed
long
)
)
{
decimal
=
va_arg
(
args
,
signed
long
);
}
else
{
decimal
=
va_arg
(
args
,
signed
int
);
}
ptr
=
format_decimal
(
ptr
,
decimal
,
width
,
flags
);
}
else
{
*
(
--
ptr
)
=
*
fmt
;
}
/* Write out conversion result */
if
(
wptr
==
NULL
)
{
for
(
;
*
ptr
;
ptr
++
)
{
cputchar
(
ctx
,
*
ptr
);
}
}
else
{
for
(
;
*
wptr
;
wptr
++
)
{
size_t
len
=
wcrtomb
(
tmp_buf
,
*
wptr
,
NULL
);
for
(
ptr
=
tmp_buf
;
len
--
;
ptr
++
)
{
cputchar
(
ctx
,
*
ptr
);
}
}
}
}
return
ctx
->
len
;
}
/** Context used by vsnprintf() and friends */
struct
sputc_context
{
struct
printf_context
ctx
;
/** Buffer for formatted string (used by printf_sputc()) */
char
*
buf
;
/** Buffer length (used by printf_sputc()) */
size_t
max_len
;
};
/**
* Write character to buffer
*
* @v ctx Context
* @v c Character
*/
static
void
printf_sputc
(
struct
printf_context
*
ctx
,
unsigned
int
c
)
{
struct
sputc_context
*
sctx
=
container_of
(
ctx
,
struct
sputc_context
,
ctx
);
if
(
ctx
->
len
<
sctx
->
max_len
)
sctx
->
buf
[
ctx
->
len
]
=
c
;
}
/**
* Write a formatted string to a buffer
*
* @v buf Buffer into which to write the string
* @v size Size of buffer
* @v fmt Format string
* @v args Arguments corresponding to the format string
* @ret len Length of formatted string
*
* If the buffer is too small to contain the string, the returned
* length is the length that would have been written had enough space
* been available.
*/
int
vsnprintf
(
char
*
buf
,
size_t
size
,
const
char
*
fmt
,
va_list
args
)
{
struct
sputc_context
sctx
;
size_t
len
;
size_t
end
;
/* Hand off to vcprintf */
sctx
.
ctx
.
handler
=
printf_sputc
;
sctx
.
buf
=
buf
;
sctx
.
max_len
=
size
;
len
=
vcprintf
(
&
sctx
.
ctx
,
fmt
,
args
);
/* Add trailing NUL */
if
(
size
)
{
end
=
size
-
1
;
if
(
len
<
end
)
end
=
len
;
buf
[
end
]
=
'\0'
;
}
return
len
;
}
/**
* Write a formatted string to a buffer
*
* @v buf Buffer into which to write the string
* @v size Size of buffer
* @v fmt Format string
* @v ... Arguments corresponding to the format string
* @ret len Length of formatted string
*/
int
snprintf
(
char
*
buf
,
size_t
size
,
const
char
*
fmt
,
...
)
{
va_list
args
;
int
i
;
va_start
(
args
,
fmt
);
i
=
vsnprintf
(
buf
,
size
,
fmt
,
args
);
va_end
(
args
);
return
i
;
}
/**
* Version of vsnprintf() that accepts a signed buffer size
*
* @v buf Buffer into which to write the string
* @v size Size of buffer
* @v fmt Format string
* @v args Arguments corresponding to the format string
* @ret len Length of formatted string
*/
int
vssnprintf
(
char
*
buf
,
ssize_t
ssize
,
const
char
*
fmt
,
va_list
args
)
{
/* Treat negative buffer size as zero buffer size */
if
(
ssize
<
0
)
ssize
=
0
;
/* Hand off to vsnprintf */
return
vsnprintf
(
buf
,
ssize
,
fmt
,
args
);
}
/**
* Version of vsnprintf() that accepts a signed buffer size
*
* @v buf Buffer into which to write the string
* @v size Size of buffer
* @v fmt Format string
* @v ... Arguments corresponding to the format string
* @ret len Length of formatted string
*/
int
ssnprintf
(
char
*
buf
,
ssize_t
ssize
,
const
char
*
fmt
,
...
)
{
va_list
args
;
int
len
;
/* Hand off to vssnprintf */
va_start
(
args
,
fmt
);
len
=
vssnprintf
(
buf
,
ssize
,
fmt
,
args
);
va_end
(
args
);
return
len
;
}
/**
* Write character to console
*
* @v ctx Context
* @v c Character
*/
static
void
printf_putchar
(
struct
printf_context
*
ctx
__unused
,
unsigned
int
c
)
{
putchar
(
c
);
}
/**
* Write a formatted string to the console
*
* @v fmt Format string
* @v args Arguments corresponding to the format string
* @ret len Length of formatted string
*/
int
vprintf
(
const
char
*
fmt
,
va_list
args
)
{
struct
printf_context
ctx
;
/* Hand off to vcprintf */
ctx
.
handler
=
printf_putchar
;
return
vcprintf
(
&
ctx
,
fmt
,
args
);
}
/**
* Write a formatted string to the console.
*
* @v fmt Format string
* @v ... Arguments corresponding to the format string
* @ret len Length of formatted string
*/
int
printf
(
const
char
*
fmt
,
...
)
{
va_list
args
;
int
i
;
va_start
(
args
,
fmt
);
i
=
vprintf
(
fmt
,
args
);
va_end
(
args
);
return
i
;
}
wimboot/wimboot-2.7.3/src/ipxe/vsprintf.h
0 → 100644
View file @
93996cf7
#ifndef _IPXE_VSPRINTF_H
#define _IPXE_VSPRINTF_H
/** @file
*
* printf() and friends
*
* Etherboot's printf() functions understand the following subset of
* the standard C printf()'s format specifiers:
*
* - Flag characters
* - '#' - Alternate form (i.e. "0x" prefix)
* - '0' - Zero-pad
* - Field widths
* - Length modifiers
* - 'hh' - Signed / unsigned char
* - 'h' - Signed / unsigned short
* - 'l' - Signed / unsigned long
* - 'll' - Signed / unsigned long long
* - 'z' - Signed / unsigned size_t
* - Conversion specifiers
* - 'd' - Signed decimal
* - 'x','X' - Unsigned hexadecimal
* - 'c' - Character
* - 's' - String
* - 'p' - Pointer
*
* Hexadecimal numbers are always zero-padded to the specified field
* width (if any); decimal numbers are always space-padded. Decimal
* long longs are not supported.
*
*/
FILE_LICENCE
(
GPL2_OR_LATER
);
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
/**
* A printf context
*
* Contexts are used in order to be able to share code between
* vprintf() and vsnprintf(), without requiring the allocation of a
* buffer for vprintf().
*/
struct
printf_context
{
/**
* Character handler
*
* @v ctx Context
* @v c Character
*
* This method is called for each character written to the
* formatted string.
*/
void
(
*
handler
)
(
struct
printf_context
*
ctx
,
unsigned
int
c
);
/** Length of formatted string
*
* When handler() is called, @len will be set to the number of
* characters written so far (i.e. zero for the first call to
* handler()).
*/
size_t
len
;
};
extern
size_t
vcprintf
(
struct
printf_context
*
ctx
,
const
char
*
fmt
,
va_list
args
);
extern
int
vssnprintf
(
char
*
buf
,
ssize_t
ssize
,
const
char
*
fmt
,
va_list
args
);
extern
int
__attribute__
((
format
(
printf
,
3
,
4
)
))
ssnprintf
(
char
*
buf
,
ssize_t
ssize
,
const
char
*
fmt
,
...
);
#endif
/* _IPXE_VSPRINTF_H */
wimboot/wimboot-2.7.3/src/lznt1.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
*
* LZNT1 decompression
*
*/
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "wimboot.h"
#include "lznt1.h"
/**
* Decompress LZNT1-compressed data block
*
* @v data Compressed data
* @v limit Length of compressed data up to end of block
* @v offset Starting offset within compressed data
* @v block Decompression buffer for this block, or NULL
* @ret out_len Length of decompressed block, or negative error
*/
static
ssize_t
lznt1_block
(
const
void
*
data
,
size_t
limit
,
size_t
offset
,
void
*
block
)
{
const
uint16_t
*
tuple
;
const
uint8_t
*
copy_src
;
uint8_t
*
copy_dest
=
block
;
size_t
copy_len
;
size_t
block_out_len
=
0
;
unsigned
int
split
=
12
;
unsigned
int
next_threshold
=
16
;
unsigned
int
tag_bit
=
0
;
unsigned
int
tag
=
0
;
while
(
offset
!=
limit
)
{
/* Extract tag */
if
(
tag_bit
==
0
)
{
tag
=
*
(
(
uint8_t
*
)
(
data
+
offset
)
);
offset
++
;
if
(
offset
==
limit
)
break
;
}
/* Calculate copy source and length */
if
(
tag
&
1
)
{
/* Compressed value */
if
(
offset
+
sizeof
(
*
tuple
)
>
limit
)
{
DBG
(
"LZNT1 compressed value overrun at "
"%#zx
\n
"
,
offset
);
return
-
1
;
}
tuple
=
(
data
+
offset
);
offset
+=
sizeof
(
*
tuple
);
copy_len
=
LZNT1_VALUE_LEN
(
*
tuple
,
split
);
block_out_len
+=
copy_len
;
if
(
copy_dest
)
{
copy_src
=
(
copy_dest
-
LZNT1_VALUE_OFFSET
(
*
tuple
,
split
)
);
while
(
copy_len
--
)
*
(
copy_dest
++
)
=
*
(
copy_src
++
);
}
}
else
{
/* Uncompressed value */
copy_src
=
(
data
+
offset
);
if
(
copy_dest
)
*
(
copy_dest
++
)
=
*
copy_src
;
offset
++
;
block_out_len
++
;
}
/* Update split, if applicable */
while
(
block_out_len
>
next_threshold
)
{
split
--
;
next_threshold
<<=
1
;
}
/* Move to next value */
tag
>>=
1
;
tag_bit
=
(
(
tag_bit
+
1
)
%
8
);
}
return
block_out_len
;
}
/**
* Decompress LZNT1-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
lznt1_decompress
(
const
void
*
data
,
size_t
len
,
void
*
buf
)
{
const
uint16_t
*
header
;
const
uint8_t
*
end
;
size_t
offset
=
0
;
ssize_t
out_len
=
0
;
size_t
block_len
;
size_t
limit
;
void
*
block
;
ssize_t
block_out_len
;
while
(
offset
!=
len
)
{
/* Check for end marker */
if
(
(
offset
+
sizeof
(
*
end
)
)
==
len
)
{
end
=
(
data
+
offset
);
if
(
*
end
==
0
)
break
;
}
/* Extract block header */
if
(
(
offset
+
sizeof
(
*
header
)
)
>
len
)
{
DBG
(
"LZNT1 block header overrun at %#zx
\n
"
,
offset
);
return
-
1
;
}
header
=
(
data
+
offset
);
offset
+=
sizeof
(
*
header
);
/* Process block */
block_len
=
LZNT1_BLOCK_LEN
(
*
header
);
if
(
LZNT1_BLOCK_COMPRESSED
(
*
header
)
)
{
/* Compressed block */
DBG2
(
"LZNT1 compressed block %#zx+%#zx
\n
"
,
offset
,
block_len
);
limit
=
(
offset
+
block_len
);
block
=
(
buf
?
(
buf
+
out_len
)
:
NULL
);
block_out_len
=
lznt1_block
(
data
,
limit
,
offset
,
block
);
if
(
block_out_len
<
0
)
return
block_out_len
;
offset
+=
block_len
;
out_len
+=
block_out_len
;
}
else
{
/* Uncompressed block */
if
(
(
offset
+
block_len
)
>
len
)
{
DBG
(
"LZNT1 uncompressed block overrun at "
"%#zx+%#zx
\n
"
,
offset
,
block_len
);
return
-
1
;
}
DBG2
(
"LZNT1 uncompressed block %#zx+%#zx
\n
"
,
offset
,
block_len
);
if
(
buf
)
{
memcpy
(
(
buf
+
out_len
),
(
data
+
offset
),
block_len
);
}
offset
+=
block_len
;
out_len
+=
block_len
;
}
}
return
out_len
;
}
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