pax_global_header 0000666 0000000 0000000 00000000064 15032005261 0014504 g ustar 00root root 0000000 0000000 52 comment=67a399476add05f29ef1ad722856728fb7639ba9
genimage-19/ 0000775 0000000 0000000 00000000000 15032005261 0013053 5 ustar 00root root 0000000 0000000 genimage-19/.clang-format 0000664 0000000 0000000 00000007525 15032005261 0015437 0 ustar 00root root 0000000 0000000 # SPDX-License-Identifier: GPL-2.0
#
# copied and modified from the Linux kernel.
#
# clang-format configuration file. Intended for clang-format >= 11.
#
# For more information, see:
#
# Documentation/dev-tools/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: false
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
ForEachMacros:
- 'hlist_for_each'
- 'hlist_for_each_entry'
- 'hlist_for_each_entry_continue'
- 'hlist_for_each_entry_from'
- 'hlist_for_each_entry_safe'
- 'hlist_for_each_safe'
- 'list_for_each'
- 'list_for_each_entry'
- 'list_for_each_entry_continue'
- 'list_for_each_entry_from'
- 'list_for_each_entry_reverse'
- 'list_for_each_entry_safe'
- 'list_for_each_entry_safe_continue'
- 'list_for_each_entry_safe_from'
- 'list_for_each_entry_safe_reverse'
- 'list_for_each_prev'
- 'list_for_each_safe'
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
# Taken from git's rules
PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptForEachMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
...
genimage-19/.github/ 0000775 0000000 0000000 00000000000 15032005261 0014413 5 ustar 00root root 0000000 0000000 genimage-19/.github/workflows/ 0000775 0000000 0000000 00000000000 15032005261 0016450 5 ustar 00root root 0000000 0000000 genimage-19/.github/workflows/format.yml 0000664 0000000 0000000 00000000477 15032005261 0020473 0 ustar 00root root 0000000 0000000 name: format
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v2
- name: Install required packages
run: |
sudo apt-get install clang-format-16
- name: Check format
run: |
clang-format-16 --dry-run --Werror *.c genimage.h
genimage-19/.github/workflows/tests.yml 0000664 0000000 0000000 00000002560 15032005261 0020340 0 ustar 00root root 0000000 0000000 name: tests
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-22.04
pkgs: device-tree-compiler rauc simg2img u-boot-tools f2fs-tools arm-trusted-firmware-tools mdadm
- os: ubuntu-22.04
pkgs: device-tree-compiler rauc simg2img u-boot-tools f2fs-tools arm-trusted-firmware-tools mdadm
fake: sudo rm /usr/include/linux/fiemap.h /usr/include/linux/fs.h
env: ac_cv_func_fallocate=no
- os: ubuntu-24.04
pkgs: device-tree-compiler rauc android-sdk-libsparse-utils u-boot-tools f2fs-tools arm-trusted-firmware-tools mdadm
steps:
- name: Inspect environment
run: |
whoami
lsb_release -a
gcc --version
- uses: actions/checkout@v3
- name: Install required packages
run: |
sudo apt-get update
sudo apt-get install btrfs-progs dosfstools fakeroot genext2fs genisoimage libconfuse-dev mtd-utils mtools qemu-utils qemu-utils squashfs-tools ${{ matrix.pkgs }}
${{ matrix.fake }}
- name: Build & Test (with ${{ matrix.options }})
run: |
./autogen.sh
./configure
${{ matrix.env }} M_COLOR_TESTS=always make distcheck
- name: Dump test log
if: ${{ failure() }}
run: |
find -name test-suite.log -print0 | xargs -0 cat
genimage-19/.gitignore 0000664 0000000 0000000 00000000260 15032005261 0015041 0 ustar 00root root 0000000 0000000 *.o
.deps/
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
build-aux/
config.h
config.h.in
config.log
config.status
configure
genimage
libtool
stamp-h1
/test/*.log
/test/*.trs
genimage-19/COPYING 0000664 0000000 0000000 00000043100 15032005261 0014104 0 ustar 00root root 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
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, see .
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Moe Ghoul, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
genimage-19/Makefile.am 0000664 0000000 0000000 00000010615 15032005261 0015112 0 ustar 00root root 0000000 0000000 if BUILD_SILENTLY
AM_MAKEFLAGS = --no-print-directory
endif
EXTRA_DIST = \
README.rst \
test.config \
flash.conf
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
AM_CPPFLAGS = \
-include $(top_builddir)/config.h
bin_PROGRAMS = genimage
genimage_SOURCES = \
genimage.c \
config.c \
util.c \
crc32.c \
image-android-sparse.c \
image-cpio.c \
image-cramfs.c \
image-custom.c \
image-erofs.c \
image-ext2.c \
image-f2fs.c \
image-mdraid.c \
image-btrfs.c \
image-file.c \
image-fip.c \
image-fit.c \
image-flash.c \
image-hd.c \
image-iso.c \
image-jffs2.c \
image-qemu.c \
image-rauc.c \
image-squashfs.c \
image-tar.c \
image-ubi.c \
image-ubifs.c \
image-vfat.c
genimage_CFLAGS = \
$(AM_CFLAGS) \
$(CONFUSE_CFLAGS)
genimage_LDADD = \
$(CONFUSE_LIBS)
noinst_HEADERS = \
genimage.h \
list.h
EXTRA_DIST += \
$(TESTS) \
test/test-setup.sh \
test/cpio.config \
test/cramfs.config \
test/custom.config \
test/erofs.old.config \
test/erofs.new.config \
test/erofs.dump.old \
test/erofs.dump.new \
test/exec-check.sh \
test/exec-fail.config \
test/exec.config \
test/ext2.config \
test/ext2test.0.dump \
test/ext2test.1.dump \
test/ext2test.2.dump \
test/ext2percent.config \
test/ext2test-percent.0.dump \
test/ext2test-percent.1.dump \
test/ext2test-percent.2.dump \
test/ext3.config \
test/ext3test.0.dump \
test/ext3test.1.dump \
test/ext3test.2.dump \
test/ext4.config \
test/ext4test.0.dump \
test/ext4test.1.dump \
test/ext4test.2.dump \
test/f2fs.config \
test/mdraid.config \
test/btrfs.config \
test/fip.config \
test/fip-size.config \
test/fit.its \
test/fit.config \
test/flash-types.config \
test/flash.config \
test/flash.md5 \
test/flash-fill.config \
test/flash-fill.md5 \
test/gpt-overlap1.config \
test/gpt-overlap2.config \
test/gpt-overlap3.config \
test/gpt-partition-types.config \
test/gpt-partition-types.fdisk \
test/gpt-invalid-partition-type1.config \
test/gpt-invalid-partition-type2.config \
test/hdimage.config \
test/hdimage2.config \
test/hdimage.fdisk \
test/hdimage.fdisk-2 \
test/hdimage4.config \
test/hdimage4.fdisk \
test/hdimage5.config \
test/hdimage5.fdisk \
test/hdimage6.config \
test/hdimage6.fdisk \
test/hdimage7.config \
test/hdimage7.fdisk \
test/hole.config \
test/hdimage-hybrid.config \
test/hdimage-hybrid.fdisk \
test/hdimage-fail1.config \
test/hdimage-fail2.config \
test/hdimage-fail3.config \
test/hdimage-fail4.config \
test/hdimage-fail5.config \
test/hdimage-fail6.config \
test/hdimage-fail7.config \
test/hdimage-fail8.config \
test/hdimage-fail9.config \
test/hdimage-fail10.config \
test/hdimage-fail11.config \
test/hdimage-nopart.config \
test/hdimage-nopart.hexdump \
test/hdimage-forced-primary.config \
test/hdimage-forced-primary.fdisk \
test/hdimage-sparse.config \
test/hdimage-imageoffset.config \
test/include-aaa.fdisk \
test/include-bbb.fdisk \
test/include-ccc.fdisk \
test/include-test.config \
test/include.config \
test/include/aaa/include-test.config \
test/include/bbb/include-test.config \
test/iso.config \
test/jffs2.config \
test/jffs2.md5 \
test/mke2fs.conf \
test/mke2fs.config \
test/mke2fs.0.dump \
test/mke2fs.1.dump \
test/mke2fs.2.dump \
test/mke2fs.3.dump \
test/qemu.config \
test/qemu.qcow.gz \
test/rauc-openssl-ca/ca.cert.pem \
test/rauc-openssl-ca/rauc.cert.pem \
test/rauc-openssl-ca/rauc.key.pem \
test/rauc.config \
test/sharness.sh \
test/sparse.config \
test/sparse-fill.config \
test/squashfs.config \
test/tar.config \
test/test.raucb.info.1 \
test/test.raucb.info.2 \
test/test.raucb.info.3 \
test/test.raucb.info.4 \
test/test2.raucb.info.1 \
test/test2.raucb.info.2 \
test/test2.raucb.info.3 \
test/test2.raucb.info.4 \
test/ubi.config \
test/ubifs.config \
test/vfat.config
TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/build-aux/tap-driver.sh
TEST_LOG_COMPILER = fakeroot
TESTS = \
test/genimage.test \
test/ext.test \
test/filesystem.test \
test/flash.test \
test/hdimage.test \
test/misc.test
# when "make clean" runs
CLEANFILES = \
test-results/*.test*.counts
# when "make distclean" runs
DISTCLEAN = \
Makefile
# when "make maintainer-clean" runs
MAINTAINERCLEANFILES = \
configure \
autoscan.log \
config.h.in~ \
config.h.in \
configure.scan \
configure.ac~ \
aclocal.m4 \
Makefile.in \
build-aux/depcomp \
build-aux/install-sh \
build-aux/missing \
$(DIST_ARCHIVES)
genimage-19/README.rst 0000664 0000000 0000000 00000102143 15032005261 0014543 0 ustar 00root root 0000000 0000000 ==================================
Genimage - The Image Creation Tool
==================================
genimage is a tool to generate multiple filesystem and flash/disk images
from a given root filesystem tree. genimage is intended to be run
in a fakeroot environment.
It also supports creating flash/disk images out of different file-system images and files.
Configuration is done in a config file parsed by libconfuse. Options
like the path to tools can be given via environment variables, the config
file or from commandline switches.
The Configuration File
======================
The config file of genimage uses a simple configuration language, provided by `libconfuse`_.
This supports nested sections, as well as simple key-value pairs.
.. _libconfuse: https://github.com/libconfuse/libconfuse
Single-line comments can be introduced with ``#`` or ``//``,
multi-line comments look like ``/* … */`` (as in C).
The config file is separated into the main sections ``image``, ``flash`` and ``config``,
and provides an ``include`` primitive.
The image section
-----------------
An image section describes a single filesystem or disk image to be built. It can be given
multiple times to generate multiple images. An image can also have multiple
partitions which refer to images themselves.
Each image must have a type which can have different suboptions depending on
the type.
Let's have a look at an example::
image nand-pcm038.img {
flash {
}
flashtype = "nand-64M-512"
partition barebox {
image = "barebox-pcm038.bin"
size = 512K
}
partition root {
image = "root-nand.jffs2"
size = 24M
}
}
This would generate a nand-pcm038.img which is a flash of type "nand-64M-512"
The image contains two partitions, "barebox-pcm038.bin" and "root-nand.jffs2"
which must refer to images described elsewhere in the config file. For example
"root-nand.jffs2" partition could be described like this::
image root-nand.jffs2 {
name = "root"
jffs2 {}
size = 24M
mountpoint = "/"
}
In this case a single jffs2 image is generated from the root mountpoint.
Here are all options for images:
:name: The name of this image. This is used for some image types
to set the name of the image.
:size: Size of this image in bytes. 'k', 'M' or 'G' can be used as
suffix to specify the size in multiple of 1024
etc. The suffix 's' specifies a multiple of the
(traditional) sector size of 512. If the image if
filled from a mountpoint then '%' as suffix indicates
a percentage. '200%' means the resulting filesystem
should be about 50% filled. Note that is is only a
rough estimate based on the original size of the
content.
:mountpoint: mountpoint if image refers to a filesystem image. The
default is "/". The content of "${rootpath}${mountpoint}"
will be used to fill the filesystem.
:srcpath: If this is set, specified path will be directly used
to fill the filesystem. Ignoring rootpath/mountpoint logic.
Path might be absolute or relative
to current working directory.
:empty: If this is set to true, then the specified rootpath and
mountpoint are ignored for this image and an empty
filesystem is created. This option is only used for
writeable filesystem types, such as extX, vfat, ubifs and
jffs2. This defaults to false.
:temporary: If this is set to true, the image is created in
``tmppath`` rather than ``outputpath``. This can be
useful for intermediate images defined in the
configuration file which are not needed by themselves
after the main image is created. This defaults to
false.
:exec-pre: Custom command to run before generating the image.
Available variables are documented in the `Environment
Variables`_ section below.
:exec-post: Custom command to run after generating the image.
:flashtype: refers to a flash section. Optional for non flash like images
like hd images
:partition: can be given multiple times and refers to a partition described
below
Additionally each image can have one of the following sections describing the
type of the image:
cpio, cramfs, custom, erofs, ext2, ext3, ext4, f2fs, file, flash, hdimage, iso,
jffs2, mdraid, qemu, squashfs, tar, ubi, ubifs, vfat.
Partition options:
:offset: The offset of this partition as a total offset to the beginning
of the device.
:size: The size of this partition in bytes. If the size and
autoresize are both not set then the size of the partition
image is used.
:align: Alignment value to use for automatic computation of ``offset``
and ``size``. Defaults to 1 for partitions not in the partition
table, otherwise to the image's ``align`` value.
:partition-type: Used by dos partition tables to specify the partition type.
:image: The image file this partition shall be filled with
:imageoffset: The offset within the partition image to start
reading from.
:fill: Boolean specifying that all bytes of the partition should be
explicitly initialized. Any bytes beyond the size of the specified
image will be set to 0.
:sparse: If true (the default) 'holes' in the input images are preserved
and the remaining free space in the partition is also a 'hole'.
If false, the 'holes' in the input image are explicitly
filled with zeros when the image is copied. If ``fill``
is specified as well then the remaining free space is
also filled with zeros.
:autoresize: Boolean specifying that the partition should be resized
automatically. For UBI volumes this means that the
``autoresize`` flag is set. Only one volume can have this flag.
For hd images this can be used for the last partition. If set
the partition will fill the remaining space of the image.
:bootable: Boolean specifying whether to set the bootable flag.
:hidden: Boolean specifying whether to set the hidden flag (only with GPT).
:no-automount: Boolean specifying whether to set the no-automount flag (only with GPT).
:read-only: Boolean specifying whether to set the read-only flag (only with GPT).
:in-partition-table: Boolean specifying whether to include this partition in
the partition table. Defaults to true.
:forced-primary: Force this partition to be a primary partition in the
MBR partition table, useful when the extended partition should be
followed by primary partitions. If there are more partitions
defined after the first forced-primary, they must be also defined
as forced-primary. Defaults to false.
:partition-uuid: UUID string used by GPT partition tables to specify the partition
id. Defaults to a random value.
:partition-type-uuid: String used by GPT partition tables to specify the partition type.
Either a UUID or a shortcut:
* ``L``, ``linux``, ``linux-generic``: Linux filesystem (0fc63daf-8483-4772-8e79-3d69d8477de4)
* ``S``, ``swap``: Swap (0657fd6d-a4ab-43c4-84e5-0933c84b4f4f)
* ``H``, ``home``: Home (933ac7e1-2eb4-4f13-b844-0e14e2aef915)
* ``U``, ``esp``, ``uefi``: EFI System Partition (c12a7328-f81f-11d2-ba4b-00a0c93ec93b)
* ``R``, ``raid``: Linux RAID (a19d880f-05fc-4d3b-a006-743f0f84911e)
* ``V``, ``lvm``: Linux LVM (e6d6d379-f507-44c2-a23c-238f2a3df928)
* ``F``, ``fat32``: FAT32 / Basic Data Partition (ebd0a0a2-b9e5-4433-87c0-68b6b72699c7)
* ``barebox-state`` (previously ``B``): Barebox State (4778ed65-bf42-45fa-9c5b-287a1dc4aab1)
* ``barebox-env``: Barebox Environment (6c3737f2-07f8-45d1-ad45-15d260aab24d)
* ``u-boot-env``: U-Boot Environment (3de21764-95bd-54bd-a5c3-4abe786f38a8)
Furthermore, for ``{arch}`` being one of ``alpha``,
``arc``, ``arm``, ``arm64``, ``ia64``, ``loongarch64``,
``mips``, ``mips64``, ``mips-le``, ``mips64-le``, ``parisc``, ``ppc``,
``ppc64``, ``ppc64-le``, ``riscv32``, ``riscv64``,
``s390``, ``s390x``, ``tilegx``, ``x86``, ``x86-64``,
the following shortcuts from the `Discoverable
Partitions Specification `_ are accepted (see the spec
for the respective UUIDs):
* ``root-{arch}``: Root Partition
* ``usr-{arch}``: /usr Partition
* ``root-{arch}-verity``: Root Verity Partition
* ``usr-{arch}-verity``: /usr Verity Partition
* ``root-{arch}-verity-sig``: Root Verity Signature Partition
* ``usr-{arch}-verity-sig``: /usr Verity Signature Partition
* ``xbootldr``: Extended Boot Loader Partition
* ``srv``: Server Data Partition
* ``var``: Variable Data Partition
* ``tmp``: Temporary Data Partition
* ``user-home``: Per-user Home Partition
Custom shortcuts can be defined in the global ``config`` section::
config {
gpt-shortcuts {
forty-two = "2a422a42-2a42-2a42-2a42-2a422a422a42"
}
}
Defaults to ``L``.
.. _dps-spec: https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
For each partition, its final alignment, offset and size are determined as follows:
* If the ``align`` option is not present, it defaults to the value of
the image's ``align`` option if the partition is in the partition
table, otherwise to 1.
* If the ``offset`` option is absent or zero, and
``in-partition-table`` is true, the partition is placed after the
end of all previously defined partitions, with the final offset
rounded up to the partition's ``align`` value.
* Otherwise, the ``offset`` option is used as-is. Note that if absent,
that option defaults to 0, so in practice one must specify an
``offset`` for any partition that is not in the partition table
(with at most one exception, e.g. a bootloader).
* If the partition has the ``autoresize`` flag set, its size is
computed as the space remaining in the image from its offset (for a
GPT image, space is reserved at the end for the backup GPT table),
rounded down to the partition's ``align`` value. If the partition
also has a ``size`` option, it is ensured that the computed value is
not less than that size.
* Otherwise, if the ``size`` option is present and non-zero, its value
is used as-is.
* Otherwise, if the partition has an ``image`` option, the size of
that image, rounded up to the partition's ``align`` value, is used
to determine the size of the partition.
The following sanity checks are done on these final values (in many
cases, these will automatically be satisfied when the value has been
determined via one of the above rules rather than given explicitly):
* For a partition in the partition table, the partition's ``align``
value must be greater than or equal to the image's ``align`` value.
* The partition's ``offset`` and ``size`` must both be multiples of
its ``align``.
* The size must not be 0.
* The partition must not overlap any other partition, or the areas
occupied by the partition table.
The image configuration options
-------------------------------
android-sparse
**************
Generate android sparse images. They are typically used by fastboot. Sparse
images encode "don't care" areas and areas that are filled with a single
32 bit value. As a result, they are often much smaller than raw disk
images.
Genimage assumes that all 'holes' in the input file are "don't care" areas.
This is a reasonable assumption: Tools to generate filesystems typically
operate on devices. So they only create holes in areas they don't care
about. Genimage itself operates the same way when generating HD images.
Options:
:image: The source image that will be converted.
:block-size: The granularity that the sparse image uses to
find "don't care" or "fill" blocks. The supported
block sizes depend on the user. The default is 4k.
:fill-holes: If enabled, 'holes' are filled with zero instead of
"don't care". Disabled by default.
:add-crc: Generate sparse comptible images containing the CRC. Ensure
that your sparse tool can handle CRC sparse images.
Defaults to false.
cpio
****
Generates cpio images.
Options:
:format: archive format. Passed to the ``-H`` option to the cpio command.
Valid options are ``bin``, ``odc``, ``newc``, ``crc``, ``tar``,
``ustar``, ``hpbin`` and ``hpodc``
:extraargs: Extra arguments passed to the cpio tool
:compress: If given, pipe image through compression tool. Valid options are
for example ``gzip``, ``lzop`` or any other tool that compresses
from stdin to stdout.
cramfs
******
Generates cramfs images.
Options:
:extraargs: Extra arguments passed to mkfs.cramfs
custom
******
Generate images with a custom command.
:exec: The command that creates the image.
If the image size is set, then image is created with the configured size
before the `exec` command is executed. Otherwise the file is removed and
the size is queried after the command is executed.
The image file that should be generated is defined in the environment
variable $IMAGEOUTFILE. It can be used directly in the ``exec`` command.
For more variables and pitfalls when using them, see the `Environment
Variables`_ section below.
erofs
******
Generates erofs images.
Options:
:extraargs: Extra arguments passed to mkfs.erofs.
ext2, ext3, ext4
****************
Generates ext* images.
Options:
:use-mke2fs: If set to true, then mke2fs is used to create the
image. Otherwise, genext2fs is used. Defaults to false.
:mke2fs-conf: mke2fs.conf that should be used. If unspecified, the system
default is used.
:extraargs: Extra arguments passed to genext2fs or mke2fs.
:features: Filesystem features. Passed to the ``-O`` option of tune2fs. This
is a comma separated list of enabled or disabled features. See
``man ext4`` for features.
For genext2fs all feature are specified. Default for ext3 images is
``has_journal``. Default for ext4 images is
``extents,uninit_bg,dir_index,has_journal``.
For mke2fs these features are added in addition to the default
features of the ext type. Already enabled features can be disabled
by prefixing the feature with ``^``.
:label: Specify the volume-label. Passed to the ``-L`` option of tune2fs
:fs-timestamp: Sets different timestamps in the image. Sets the given timestamp
using the debugfs commands ``set_current_time``,
``set_super_value mkfs_time`` and ``set_super_value lastcheck``
:root-owner: User and group IDs for the root directory. Defaults to ``0:0``.
Only valid with mke2fs.
:usage-type: Specify the usage type for the filesystem. Only valid with mke2fs.
More details can be found in the mke2fs man-page.
f2fs
****
Generates F2FS images.
Options:
:label: Specify the volume-label.
:extraargs: Extra arguments passed to mkfs.f2fs
file
****
This represents a pre-existing image which will be used as-is. When a
partition section references an image that is not defined elsewhere in
the configuration file, a ``file`` rule is implicitly generated. It is
up to the user to ensure that the image exists in the input directory,
or to use an absolute path to the image.
It is possible to add a ``file`` image explicitly, which allows one to
provide ``genimage`` with some information about the image which can
not be deduced automatically. Currently, one such option exists:
:holes: A list of ``"(;)"`` pairs specifying ranges of the
file that do not contain meaningful data, and which can therefore
be allowed to overlap other partitions or image metadata.
For example::
image foo {
hdimage {
partition-table-type = "gpt"
gpt-location = 64K
}
partition bootloader {
in-partition-table = false
offset = 0
image = "/path/to/bootloader.img"
}
partition rootfs {
offset = 1M
image = "rootfs.ext4"
}
}
image /path/to/bootloader.img {
file {
holes = {"(440; 1K)", "(64K; 80K)"}
}
}
This tells ``genimage`` that despite the ``bootloader`` partition
overlapping both the last 72 bytes of the MBR (where the DOS partition
table is located) and the GPT header occupying the sector starting at
offset 512, this is all OK because ``bootloader.img`` does not contain
useful data in that range. Further, in this example, the bootloader
image has been carefully crafted to also allow placing the GPT array
at offset 64K (the GPT header is always at offset 512).
If the bootloader image is not declared explicitly and only used once then
the holes can also be configured in the partition. This simplifies the
config file for simple use-cases.
For example::
image bar {
hdimage {}
partition bootloader {
in-partition-table = false
offset = 0
image = "/path/to/bootloader.img"
holes = {"(440; 512)"}
}
partition rootfs {
offset = 1M
image = "rootfs.ext4"
}
}
FIT
***
Generates U-Boot FIT images.
Options:
:its: String option holding the path of the input its file
:keydir: String option holding the directory containing the keys
used for signing.
flash
*****
Generates flash images. These are basically the partition contents padded to the
partition sizes concatenated together. There is no partition table. Needs a valid
flashtype where the flash parameters are read from.
hdimage
*******
Generates DOS partition images.
Options:
:align: Partition alignment. Defaults to 512 bytes
:partition-table: Boolean. If true, writes a partition table. If false, no
partition table is generated. Defaults to true.
Deprecated: use ``partition-table-type`` instead.
:partition-table-type: Define what kind of partition table should be used.
Valid options are:
* ``none``: No partition table at all. In this case, the
``in-partition-table`` option for each partition is ignored.
* ``mbr``: Legacy DOS/MBR partition table
* ``gpt``: GUID Partition Table
* ``hybrid``: A hybrid MBR/GPT partition table. Partitions with
an explicit `partition-type` will be placed in in the MBR
table. At most 3 such partitions are allowed. This limit does
not effect the maximum number of GPT partition entries in the
same image.
:extended-partition: Number of the extended partition. Contains the number of the
extended partition between 1 and 4 or 0 for automatic. Defaults
to 0.
:disk-signature: 32 bit integer used as disk signature (offset 440 in the
MBR). Using a special value ``random`` will result in
using random 32 bit number.
:gpt: Boolean. If true, a GPT type partition table is written. If false
a DOS type partition table is written. Defaults to false.
Deprecated: use ``partition-table-type`` instead.
:gpt-location: Location of the GPT table. Occasionally useful for moving the GPT
table away from where a bootloader is placed due to hardware
requirements. All partitions in the table must begin after this
table. Regardless of this setting, the GPT header will still be
placed at 512 bytes (sector 1). Defaults to 1024 bytes (sector 2).
:gpt-no-backup: Boolean. If true, then the backup partition table at the end of
the image is not written.
:disk-uuid: UUID string used as disk id in GPT partitioning. Defaults to a
random value.
:fill: If this is set to true, then the image file will be filled
up to the end of the last partition. This might make the file
bigger. This is necessary if the image will be processed by
such tools as libvirt, libguestfs or parted.
GPT partition flags
~~~~~~~~~~~~~~~~~~~
A GPT partition table will translate the following partition configurations to
the respective GPT flags and set it in the GPT partiton table:
====================== ==============================
genimage configuration GPT FLAG
====================== ==============================
read-only GPT_PE_FLAG_READ_ONLY (Bit 60)
bootable GPT_PE_FLAG_BOOTABLE (Bit 2)
hidden GPT_PE_FLAG_HIDDEN (Bit 62)
no-automount GPT_PE_FLAG_NO_AUTO (Bit 63)
====================== ==============================
Other GPT Flags are currently not supported.
iso
***
Generates an ISO image.
Options:
:boot-image: Path to the El Torito boot image. Passed to the ``-b`` option
of genisofs
:bootargs: Bootargs for the El Torito boot image. Defaults to
``-no-emul-boot -boot-load-size 4 -boot-info-table -c boot.cat -hide boot.cat``
:extraargs: Extra arguments passed to genisofs
:input-charset: The input charset. Passed to the -input-charset option of genisofs.
Defaults to ``default``
:volume-id: Volume ID. Passed to the ``-V`` option of genisofs
jffs2
*****
Generates a JFFS image. Needs a valid flashtype where the flash parameters are
read from.
Options:
:extraargs: Extra arguments passed to mkfs.jffs2
mdraid
****
Generates MD RAID images.
Options:
:label: Optional hostname and name of array separated by colon, eg: ``any:42``.
Special hostname ``any`` can be used to make array local to machine with any hostname.
Name will be used by OS to name ``/dev/md/*`` device (as long as the hostname matches).
:level: RAID level, currently only level 1 (default) is supported
:devices: Number of devices in array (default 1)
:role: 0 based index of this image in whole array. (autoassigned by default)
:timestamp: Unix timestamp of array creation (current time by default, has to match across array devices)
:raid-uuid: UUID of whole array (has to be identical across all disks in array, random by default)
:disk-uuid: UUID of disk (has to be unique for each array member disk, random by default)
:image: Image of data to be preloaded into array (optional)
:parent: Image to inherit array identity/config from (when creating extra members of existing array).
Effectively overrides all array-wide options mentioned here and replaces them with values from parent.
For example here only the first image has configuration and the UUID/timestamp is generated on demand::
image mdraid-a.img {
mdraid {
level = 1
devices = 2
image = "mdraid-ext4.img"
}
}
Then to create second member to that array we just inherit config from the parent member::
image mdraid-b.img {
mdraid {
parent = "mdraid-a.img"
}
}
Default role number is 0 for the parent image and when other images inherit configuration from it, they are assigned roles from autoincrementing counter.
qemu
****
Generates a QEMU image. Needs at least one valid partition.
Options:
:format: A valid ``qemu-img`` like ``qcow``, ``qcow2``, ``parallels``, ``vdi``,
``vhdx`` or ``vmdk``. Check ``qemu-img convert --help`` for the complete
list of possible values. Defaults to ``qcow2``.
:extraargs: Extra arguments passed to ``qemu-img convert``
squashfs
********
Generates a squashfs image.
Options:
:extraargs: Extra arguments passed to mksquashfs
:compression: compression type for the image. Possible values are ``gzip``
(default), ``none`` and any other compressors supported by ``mksquashfs``
such as ``lzo``, ``lz4``, ``xz``, ``zstd`` or ``lzma``.
:block-size: Block size. Passed to the ``-b`` option of mksquashfs. Defaults
to 4096.
rauc
****
Generates a RAUC update bundle.
Options:
:extraargs: Extra arguments passed to RAUC
:file: Specify a file to be added into the RAUC bundle. Usage is:
``file foo { image = "bar" }`` which adds a file "foo" in the
RAUC bundle from then input file "bar"
:files: A list of filenames added into the RAUC bundle. Like **file**
above, but without the ability to add the files under different
name.
:key: Path to the key file or PKCS#11 URI. Passed to the ``--key`` option of
RAUC
:cert: Path to the certificate file or PKCS#11 URI. Passed to the ``--cert``
option of RAUC
:keyring: Optional path to the keyring file. Passed to the ``--keyring``
option of RAUC
:manifest: content of the manifest file
tar
***
Generates a tar image. The image will be compressed as defined by the filename suffix.
ubi
***
Generates an UBI image. Needs a valid flashtype where the flash parameters are
read from.
Options:
:extraargs: Extra arguments passed to ubinize
ubifs
*****
Generates a UBIFS image. Needs a valid flashtype where the flash parameters are
read from.
Options:
:extraargs: Extra arguments passed to mkubifs
:max-size: Maximum size of the UBIFS image
:space-fixup: Instructs the file-system free space to be freed up on first mount.
vfat
****
Generates a VFAT image.
Options:
:extraargs: Extra arguments passed to mkdosfs
:label: Specify the volume-label. Passed to the ``-n`` option of mkdosfs
:file: Specify a file to be added into the filesystem image. Usage is:
``file foo { image = "bar" }`` which adds a file "foo" in the
filesystem image from the input file "bar"
:files: A list of filenames added into the filesystem image. Like **file**
above, but without the ability to add the files under different
name.
Note: If no content is specified with ``file`` or ``files`` then
``rootpath`` and ``mountpoint`` are used to provide the content.
fip
***
Generates a Firmware Image Package (FIP). A format used to bundle
firmware to be loaded by ARM Trusted Firmware.
Options:
:extraargs: Extra arguments passed to fiptool
:fw-config: Firmware Configuration (device tree), usually provided by BL2 (Trusted Firmware)
:nt-fw: Non-Trusted Firmware (BL33)
:hw-config: Hardware Configuration (device tree), passed to BL33
:tos-fw: Trusted OS (BL32) binaries. Second and third binary are used as
extra1 and extra2 binaries if specified. Example:
``tos-fw = {"tee-header_v2.bin", "tee-pager_v2.bin", "tee-pageable_v2.bin"}``
:scp-fwu-cfg: SCP Firmware Updater Configuration FWU SCP_BL2U
:ap-fwu-cfg: AP Firmware Updater Configuration BL2U
:fwu: Firmware Updater NS_BL2U
:fwu-cert: Non-Trusted Firmware Updater certificate
:tb-fw: Trusted Boot Firmware BL2
:scp-fw: SCP Firmware SCP_BL2
:soc-fw: EL3 Runtime Firmware BL31
:tb-fw-config: TB_FW_CONFIG
:soc-fw-config: SOC_FW_CONFIG
:tos-fw-config: TOS_FW_CONFIG
:nt-fw-config: NT_FW_CONFIG
:rot-cert: Root Of Trust key certificate
:trusted-key-cert: Trusted key certificate
:scp-fw-key-cert: SCP Firmware key certificate
:soc-fw-key-cert: SoC Firmware key certificate
:tos-fw-key-cert: Trusted OS Firmware key certificate
:nt-fw-key-cert: Non-Trusted Firmware key certificate
:tb-fw-cert: Trusted Boot Firmware BL2 certificate
:scp-fw-cert: SCP Firmware content certificate
:soc-fw-cert: SoC Firmware content certificate
:tos-fw-cert: Trusted OS Firmware content certificate
:nt-fw-cert: Non-Trusted Firmware content certificate
:sip-sp-cert: SiP owned Secure Partition content certificate
:plat-sp-cert: Platform owned Secure Partition content certificate
The Flash Section
-----------------
The flash section can be given multiple times and each section describes a
flash chip. The option names are mostly derived from the UBI terminology.
There are the following options:
:pebsize: The size of a physical eraseblock in bytes
:lebsize: The size of a logical eraseblock in bytes (for ubifs)
:numpebs: Number of physical eraseblocks on this device. The total
size of the device is determined by pebsize * numpebs
:minimum-io-unit-size: The minimum size in bytes accessible on this device
:vid-header-offset: offset of the volume identifier header
:sub-page-size: The size of a sub page in bytes.
Several flash related image types need a valid flash section. From the image types
the flash type section is referred to using the ``flashtype`` option which contains
the name of the flash type to be used.
For more information of the meaning of these values see the ubi(fs) and mtd FAQs:
http://www.linux-mtd.infradead.org/faq/general.html
Example flash section::
flash nand-64M-512 {
pebsize = 16384
lebsize = 15360
numpebs = 4096
minimum-io-unit-size = 512
vid-header-offset = 512
sub-page-size = 512
}
...
image jffs2 {
flashtype = "nand-64M-512"
}
The config section
------------------
In this section the global behaviour of the program is
described. Except as noted below, all options here can be given from
either environment variables, the config file or command line
switches. For instance, a config option ``foo`` can be passed as a
``--foo`` command line switch or as a GENIMAGE_FOO environment
variable.
:config: default: ``genimage.cfg``
Path to the genimage config file.
:loglevel: default: 1
genimage log level.
:outputpath: default: images
Mandatory path where all images are written to (must exist).
:inputpath: default: input
This mandatory path is searched for input images, for example
bootloader binaries, kernel images (must exist).
:rootpath: default: root
Mandatory path to the root filesystem (must exist).
:tmppath: default: tmp
Optional path to a temporary directory. There must be enough space
available here to hold a copy of the root filesystem.
:includepath: Colon-separated list of directories to search for files
included via the ``include`` function. The current
directory is searched after these. Thus, if this
option is not given, only the current directory is
searched. This has no effect when given in the config file.
:configdump: File to write the final configuration to. This includes
the results of all ``include`` directives, expansions
of environment variables and application of default
values - think ``gcc -E``. Use ``-`` for stdout.
:cpio: path to the cpio program (default cpio)
:dd: path to the dd program (default dd)
:e2fsck: path to the e2fsck program (default e2fsck)
:genext2fs: path to the genext2fs program (default genext2fs)
:genisoimage: path to the genisoimage program (default genisoimage)
:mcopy: path to the mcopy program (default mcopy)
:mmd: path to the mmd program (default mmd)
:mkcramfs: path to the mkcramfs program (default mkfs.cramfs)
:mkdosfs: path to the mkdosfs program (default mkdosfs)
:mkfserofs: path to the mkfs.erofs program (default mkfs.erofs)
:mkfsf2fs: path to the mkfs.f2fs program (default mkfs.f2fs)
:mkfsjffs2: path to the mkfs.jffs2 program (default mkfs.jffs2)
:mkfsubifs: path to the mkfs.ubifs program (default mkfs.ubifs)
:mksquashfs: path to the mksquashfs program (default mksquashfs)
:qemu-img: path to the qemu-img program (default qemu-img)
:tar: path to the tar program (default tar)
:tune2fs: path to the tune2fs program (default tune2fs)
:ubinize: path to the ubinize program (default ubinize)
:fiptool: path to the fiptool utility (default fiptool)
Include Configurations Fragments
--------------------------------
To include a ``"foo.cfg"`` config file, use the following statement::
include("foo.cfg")
This allows to re-use, for example flash configuration files, across different image configurations.
Environment Variables
---------------------
The following environment variables are defined when the commands that
create images are executed. This includes the ``exec-pre``, ``exec-post``
commands and the ``exec`` command of the custom image type.
Warning: If an ``exec*`` command is quoted with double-quotes and a
variable is specified with curly braces then variables are substituted
when the config file is parsed. At that point variables defined by
genimage are not yet set.
So use single quotes instead.
Common Variables for all Images
*******************************
============== =============================================
**OUTPUTPATH** Directory where images are created
**INPUTPATH** Directory where input images are searched
**ROOTPATH** Root directory of the content for the images
**TMPPATH** Directory where temporary files are created
============== =============================================
Image Specific Variables
************************
=================== =============================================
**IMAGE** File name relative to $OUTPUTPATH
**IMAGEOUTFILE** Full path of the file
**IMAGENAME** Name of the image
**IMAGESIZE** Configured size
**IMAGEMOUNTPOINT** Absolute 'mountpoint' to use. It defines with
directory relative to $ROOTPATH should be used
**IMAGEMOUNTPATH** Full path to the data to use. This is effectively
$ROOTPATH/$IMAGEMOUNTPOINT
=================== =============================================
License and Developing
======================
To contribute to genimage please prepare a pull request on Github. To make
it possible to include your modifications it's required that your code
additions are licensed under the same terms as genimage itself. So you
are required to agree to the following document:
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
Your agreement is expressed by adding a sign-off line to each of your
commits (e.g. using ``git commit -s``) looking as follows:
Signed-off-by: Random J Developer
with your identity and email address matching the commit meta data.
Before creating pull request, please make sure your tree is passing
all unit tests by running ``make distcheck``.
genimage-19/autogen.sh 0000775 0000000 0000000 00000001100 15032005261 0015044 0 ustar 00root root 0000000 0000000 #!/bin/sh -e
if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \
chmod +x .git/hooks/pre-commit && \
echo "Activated pre-commit hook."
fi
autoreconf --install --symlink
args="--prefix=/usr"
echo
echo "----------------------------------------------------------------"
echo "Initialized build system. For a common configuration please run:"
echo "----------------------------------------------------------------"
echo
echo "./configure CFLAGS='-g -O0' $args"
echo
genimage-19/config.c 0000664 0000000 0000000 00000025333 15032005261 0014472 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include "genimage.h"
static LIST_HEAD(optlist);
static struct gpt_partition_type_shortcut_t *config_gpt_shortcuts;
struct config {
const char *name;
cfg_opt_t opt;
const char *env;
struct list_head list;
char *value;
char *def;
int hidden;
};
static void show_help(const char *cmd)
{
struct config *c;
printf("Usage %s [options]\n"
"Generate filesystem, disk and flash images defined in the\n"
"configuration file.\n\n"
"Valid options: [ default value ] (environment variable)\n"
" -h, --help\n"
" -v, --version\n",
cmd);
list_for_each_entry(c, &optlist, list) {
char opt[20], def[20];
if (c->hidden)
continue;
snprintf(opt, 20, "%s ", c->name);
snprintf(def, 20, "[ %s ]", c->def);
printf(" --%-20s %-20s (%s)\n", opt, c->def ? def : "", c->env);
}
printf("\n");
}
static void show_version(void)
{
printf(PACKAGE_VERSION "\n");
}
/*
* get the value of an option
*/
const char *get_opt(const char *name)
{
struct config *c;
list_for_each_entry(c, &optlist, list) {
if (!strcmp(c->name, name))
return c->value;
}
return NULL;
}
/*
* set option 'name' to 'value'
*/
static int set_opt(const char *name, const char *value)
{
struct config *c;
list_for_each_entry(c, &optlist, list) {
if (!strcmp(c->name, name)) {
free(c->value);
c->value = strdup(value);
return 0;
}
}
return -EINVAL;
}
const struct gpt_partition_type_shortcut_t *get_gpt_shortcuts(void)
{
return config_gpt_shortcuts;
}
/*
* convert all options from the options list to a cfg_opt_t
* array suitable for confuse
*/
cfg_opt_t *get_confuse_opts(void)
{
struct config *c;
int num_opts = 0;
cfg_opt_t *options;
int i = 0;
cfg_opt_t cfg_end[] = {
CFG_SEC("gpt-shortcuts", NULL, CFGF_KEYSTRVAL),
CFG_END()
};
list_for_each_entry(c, &optlist, list) {
if (c->opt.name)
num_opts++;
}
options = xzalloc(sizeof(cfg_opt_t) * (num_opts + sizeof(cfg_end) / sizeof(cfg_opt_t)));
list_for_each_entry(c, &optlist, list) {
if (c->opt.name) {
memcpy(&options[i], &c->opt, sizeof(cfg_opt_t));
i++;
}
}
memcpy(&options[i], cfg_end, sizeof(cfg_end));
return options;
}
/*
* Get an integer type option from confuse, but with an optional
* 'k', 'M', 'G' suffix
*/
unsigned long long cfg_getint_suffix(cfg_t *sec, const char *name)
{
const char *str = cfg_getstr(sec, name);
unsigned long long val = 0;
if (str)
val = strtoul_suffix(str, NULL, NULL);
return val;
}
/*
* Like cfg_getint_suffix() but allow '%' as suffix as well
*/
unsigned long long cfg_getint_suffix_percent(cfg_t *sec, const char *name,
cfg_bool_t *percent)
{
const char *str = cfg_getstr(sec, name);
unsigned long long val = 0;
if (str)
val = strtoul_suffix(str, NULL, percent);
return val;
}
/*
* Initialize all options in the following order:
*
* 1) default value
* 2) from environment
* 3) from config file
* 4) from command line switch
*
* may be called multiple times with cfg == NULL when
* config file is not yet available.
*/
int set_config_opts(int argc, char *argv[], cfg_t *cfg)
{
struct config *c;
cfg_t *cfgsec = NULL, *cfggpt;
int num_opts = 0, n, i;
static struct option *long_options = NULL;
int ret = 0;
if (cfg && (cfg_size(cfg, "config") > 0))
cfgsec = cfg_getsec(cfg, "config");
list_for_each_entry(c, &optlist, list) {
char *str;
num_opts++;
/* set from option default value */
if (c->def)
set_opt(c->name, c->def);
/* set from environment */
str = getenv(c->env);
if (str)
set_opt(c->name, str);
/* set from config file (if already available) */
if (cfgsec && c->opt.name) {
str = cfg_getstr(cfgsec, c->opt.name);
if (str)
set_opt(c->name, str);
}
}
if (cfgsec && (cfggpt = cfg_getsec(cfgsec, "gpt-shortcuts"))) {
int count = cfg_num(cfggpt);
config_gpt_shortcuts = xzalloc((count + 1) * sizeof(struct gpt_partition_type_shortcut_t));
for (i = 0; i < count; ++i) {
cfg_opt_t *opt = cfg_getnopt(cfggpt, i);
config_gpt_shortcuts[i].shortcut = cfg_opt_name(opt);
config_gpt_shortcuts[i].guid = cfg_opt_getstr(opt);
}
}
/* and last but not least from command line switches */
long_options = xzalloc(sizeof(struct option) * (num_opts + 3));
i = 0;
list_for_each_entry(c, &optlist, list) {
struct option *o = &long_options[i];
o->name = c->name;
o->has_arg = 1;
i++;
}
long_options[i].name = "help";
long_options[i].val = 'h';
long_options[i + 1].name = "version";
long_options[i + 1].val = 'v';
optind = 1;
while (1) {
int option_index = 0;
n = getopt_long(argc, argv, "hv",
long_options, &option_index);
if (n == -1)
break;
switch (n) {
case 0:
ret = set_opt(long_options[option_index].name, optarg);
if (ret)
goto err_out;
break;
case 'h':
show_help(argv[0]);
exit(0);
break;
case 'v':
show_version();
exit(0);
break;
default:
ret = -EINVAL;
goto err_out;
}
}
err_out:
free(long_options);
return ret;
}
static char *abspath(const char *path)
{
char *p;
if (*path == '/')
return strdup(path);
xasprintf(&p, "%s/%s", get_current_dir_name(), path);
return p;
}
const char *imagepath(void)
{
static const char *outputpath;
if (!outputpath)
outputpath = abspath(get_opt("outputpath"));
return outputpath;
}
const char *inputpath(void)
{
static const char *inputpath;
if (!inputpath)
inputpath = abspath(get_opt("inputpath"));
return inputpath;
}
static const char *cached_rootpath;
void disable_rootpath(void)
{
cached_rootpath = "";
}
const char *rootpath(void)
{
if (!cached_rootpath)
cached_rootpath = abspath(get_opt("rootpath"));
return cached_rootpath;
}
const char *tmppath(void)
{
static const char *tmppath;
if (!tmppath)
tmppath = abspath(get_opt("tmppath"));
return tmppath;
}
static struct config opts[] = {
{
.name = "loglevel",
.opt = CFG_STR("loglevel", NULL, CFGF_NONE),
.env = "GENIMAGE_LOGLEVEL",
.def = "1",
},
{
.name = "rootpath",
.opt = CFG_STR("rootpath", NULL, CFGF_NONE),
.env = "GENIMAGE_ROOTPATH",
.def = "root",
},
{
.name = "tmppath",
.opt = CFG_STR("tmppath", NULL, CFGF_NONE),
.env = "GENIMAGE_TMPPATH",
.def = "tmp",
},
{
.name = "inputpath",
.opt = CFG_STR("inputpath", NULL, CFGF_NONE),
.env = "GENIMAGE_INPUTPATH",
.def = "input",
},
{
.name = "outputpath",
.opt = CFG_STR("outputpath", NULL, CFGF_NONE),
.env = "GENIMAGE_OUTPUTPATH",
.def = "images",
},
{
.name = "includepath",
.opt = CFG_STR("includepath", NULL, CFGF_NONE),
.env = "GENIMAGE_INCLUDEPATH",
.def = NULL,
#ifndef HAVE_SEARCHPATH
.hidden = 1,
#endif
},
{
.name = "cpio",
.opt = CFG_STR("cpio", NULL, CFGF_NONE),
.env = "GENIMAGE_CPIO",
.def = "cpio",
},
{
.name = "dd",
.opt = CFG_STR("dd", NULL, CFGF_NONE),
.env = "GENIMAGE_DD",
.def = "dd",
},
{
.name = "debugfs",
.opt = CFG_STR("debugfs", NULL, CFGF_NONE),
.env = "GENIMAGE_DEBUGFS",
.def = "debugfs",
},
{
.name = "e2fsck",
.opt = CFG_STR("e2fsck", NULL, CFGF_NONE),
.env = "GENIMAGE_E2FSCK",
.def = "e2fsck",
},
{
.name = "genext2fs",
.opt = CFG_STR("genext2fs", NULL, CFGF_NONE),
.env = "GENIMAGE_GENEXT2FS",
.def = "genext2fs",
},
{
.name = "genisoimage",
.opt = CFG_STR("genisoimage", NULL, CFGF_NONE),
.env = "GENIMAGE_GENISOIMAGE",
.def = "genisoimage",
},
{
.name = "mcopy",
.opt = CFG_STR("mcopy", NULL, CFGF_NONE),
.env = "GENIMAGE_MCOPY",
.def = "mcopy",
},
{
.name = "mmd",
.opt = CFG_STR("mmd", NULL, CFGF_NONE),
.env = "GENIMAGE_MMD",
.def = "mmd",
},
{
.name = "mkcramfs",
.opt = CFG_STR("mkcramfs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKCRAMFS",
.def = "mkfs.cramfs",
},
{
.name = "mkdosfs",
.opt = CFG_STR("mkdosfs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKDOSFS",
.def = "mkdosfs",
},
{
.name = "mke2fs",
.opt = CFG_STR("mke2fs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKE2FS",
.def = "mke2fs",
},
{
.name = "mkfserofs",
.opt = CFG_STR("mkfserofs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKFSEROFS",
.def = "mkfs.erofs",
},
{
.name = "mkfsjffs2",
.opt = CFG_STR("mkfsjffs2", NULL, CFGF_NONE),
.env = "GENIMAGE_MKFJFFS2",
.def = "mkfs.jffs2",
},
{
.name = "mkfsf2fs",
.opt = CFG_STR("mkfsf2fs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKFSF2FS",
.def = "mkfs.f2fs",
},
{
.name = "mkfsbtrfs",
.opt = CFG_STR("mkfsfbtrfs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKFSBTRFS",
.def = "mkfs.btrfs",
},
{
.name = "sloadf2fs",
.opt = CFG_STR("sloadf2fs", NULL, CFGF_NONE),
.env = "GENIMAGE_SLOADF2FS",
.def = "sload.f2fs",
},
{
.name = "mkfsubifs",
.opt = CFG_STR("mkfsubifs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKFSUBIFS",
.def = "mkfs.ubifs",
},
{
.name = "mksquashfs",
.opt = CFG_STR("mksquashfs", NULL, CFGF_NONE),
.env = "GENIMAGE_MKSQUASHFS",
.def = "mksquashfs",
},
{
.name = "qemu-img",
.opt = CFG_STR("qemu-img", NULL, CFGF_NONE),
.env = "GENIMAGE_QEMU",
.def = "qemu-img",
},
{
.name = "rauc",
.opt = CFG_STR("rauc", NULL, CFGF_NONE),
.env = "GENIMAGE_RAUC",
.def = "rauc",
},
{
.name = "tar",
.opt = CFG_STR("tar", NULL, CFGF_NONE),
.env = "GENIMAGE_TAR",
.def = "tar",
},
{
.name = "tune2fs",
.opt = CFG_STR("tune2fs", NULL, CFGF_NONE),
.env = "GENIMAGE_TUNE2FS",
.def = "tune2fs",
},
{
.name = "ubinize",
.opt = CFG_STR("ubinize", NULL, CFGF_NONE),
.env = "GENIMAGE_UBINIZE",
.def = "ubinize",
},
{
.name = "mkimage",
.opt = CFG_STR("mkimage", NULL, CFGF_NONE),
.env = "GENIMAGE_MKIMAGE",
.def = "mkimage",
},
{
.name = "fiptool",
.opt = CFG_STR("fiptool", NULL, CFGF_NONE),
.env = "GENIMAGE_FIPTOOL",
.def = "fiptool",
},
{
.name = "config",
.env = "GENIMAGE_CONFIG",
.def = "genimage.cfg",
},
{
.name = "configdump",
.env = "GENIMAGE_CONFIGDUMP",
.def = NULL,
},
};
/*
* early setup: add all options from the array above to the
* list of options
*/
int init_config(void)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(opts); i++) {
struct config *c = &opts[i];
list_add_tail(&c->list, &optlist);
}
return 0;
}
genimage-19/configure.ac 0000664 0000000 0000000 00000012627 15032005261 0015351 0 ustar 00root root 0000000 0000000 AC_PREREQ(2.60)
AC_INIT([genimage],
[19],
[oss-tools@pengutronix.de],
[genimage],
[http://www.pengutronix.de/genimage/])
AC_CONFIG_SRCDIR([genimage.c])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects])
AC_PROG_CC
# If possible, enable extensions to Posix
AC_USE_SYSTEM_EXTENSIONS
AC_SYS_LARGEFILE
# where to put extension macros
AC_CONFIG_MACRO_DIR([m4])
# default is less output while building the package
AM_SILENT_RULES([yes])
# Help the generated libtool script understand the characteristics of the host
LT_INIT
# change if 'usr/local' as the default install path isn't a good choice
#AC_PREFIX_DEFAULT([/usr/local])
AC_CHECK_FUNCS([memset setenv strdup strcasecmp strerror strstr strtoull])
AC_C_INLINE
AC_FUNC_ERROR_AT_LINE
AC_FUNC_MALLOC
AC_TYPE_SIZE_T
AC_TYPE_UINT32_T
AC_CACHE_CHECK([whether linux/fs.h is available], [genimage_cv_header_linux_fs_h],
AC_CHECK_HEADERS([linux/fs.h], [genimage_cv_header_linux_fs_h=yes],
[genimage_cv_header_linux_fs_h=no]))
AC_CACHE_CHECK([whether linux/fiemap.h is available], [genimage_cv_header_fiemap_h],
AC_CHECK_HEADERS([linux/fiemap.h], [genimage_cv_header_fiemap_h=yes],
[genimage_cv_header_fiemap_h=no]))
if test "x$genimage_cv_header_linux_fs_h" = "xyes"; then
AC_DEFINE([HAVE_LINUX_FS_H], [1], [Define if linux/fs.h is available])
fi
if test "x$genimage_cv_header_fiemap_h" = "xyes" -a "x$genimage_cv_header_linux_fs_h" = "xyes"; then
AC_DEFINE([HAVE_FIEMAP], [1], [Define if fiemap can be used])
fi
AC_CHECK_FUNCS(fallocate)
# ----------- query user's settings ----------------------
AC_MSG_CHECKING([whether to enable debugging])
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--enable-debug],
[enable debug messages @<:@default=disabled@:>@]),
[],
[enable_debug=no])
AC_MSG_RESULT([${enable_debug}])
# should the executable export all symbols?
AC_MSG_CHECKING([whether to hide internal symbols])
AC_ARG_ENABLE([hide],
[AS_HELP_STRING([--disable-hide],
[do not hide all internal symbols @<:@default=enabled@:>@])],
[],
[enable_hide=yes])
# for debugging purposes we must disable the hiding feature
AS_IF([test "x${enable_debug}" = "xyes"],
[AC_MSG_RESULT([no (due to debug enabled)])
enable_hide=no],
[AC_MSG_RESULT([${enable_hide}])])
# ----------- autodetect some settings -------------------
# add as much warnings and features as possible, but check what the compiler
# is able to understand and use it only if possible
CC_CHECK_CFLAGS_SILENT([-pipe],[AM_CFLAGS="${AM_CFLAGS} -pipe"])
CC_CHECK_CFLAGS_SILENT([-Wall],[AM_CFLAGS="${AM_CFLAGS} -Wall"])
CC_CHECK_CFLAGS_SILENT([-Wextra],[AM_CFLAGS="${AM_CFLAGS} -Wextra"])
CC_CHECK_CFLAGS_SILENT([-Wmissing-declarations],[AM_CFLAGS="${AM_CFLAGS} -Wmissing-declarations"])
CC_CHECK_CFLAGS_SILENT([-Wmissing-prototypes],[AM_CFLAGS="${AM_CFLAGS} -Wmissing-prototypes"])
CC_CHECK_CFLAGS_SILENT([-Wnested-externs],[AM_CFLAGS="${AM_CFLAGS} -Wnested-externs"])
CC_CHECK_CFLAGS_SILENT([-Wpointer-arith],[AM_CFLAGS="${AM_CFLAGS} -Wpointer-arith"])
CC_CHECK_CFLAGS_SILENT([-Wsign-compare],[AM_CFLAGS="${AM_CFLAGS} -Wsign-compare"])
CC_CHECK_CFLAGS_SILENT([-Wchar-subscripts],[AM_CFLAGS="${AM_CFLAGS} -Wchar-subscripts"])
CC_CHECK_CFLAGS_SILENT([-Wstrict-prototypes],[AM_CFLAGS="${AM_CFLAGS} -Wstrict-prototypes"])
CC_CHECK_CFLAGS_SILENT([-Wshadow],[AM_CFLAGS="${AM_CFLAGS} -Wshadow"])
CC_CHECK_CFLAGS_SILENT([-Wformat-security],[AM_CFLAGS="${AM_CFLAGS} -Wformat-security"])
CC_CHECK_CFLAGS_SILENT([-Wtype-limits],[AM_CFLAGS="${AM_CFLAGS} -Wtype-limits"])
CC_CHECK_CFLAGS_SILENT([-Wunused-parameter],[AM_CFLAGS="${AM_CFLAGS} -Wno-unused-parameter"])
CC_CHECK_CFLAGS_SILENT([-ffunction-sections],[AM_CFLAGS="${AM_CFLAGS} -ffunction-sections"])
CC_CHECK_CFLAGS_SILENT([-fdata-sections],[AM_CFLAGS="${AM_CFLAGS} -fdata-sections"])
# Add only those libraries which are really used
CC_CHECK_LDFLAGS([-Wl,--as-needed], [AM_LDFLAGS="${AM_LDFLAGS} -Wl,--as-needed"],[])
CC_CHECK_LDFLAGS([-Wl,--gc-sections], [AM_LDFLAGS="${AM_LDFLAGS} -Wl,--gc-sections"],[])
PKG_CHECK_MODULES(CONFUSE, libconfuse >= 2.8,
[AC_DEFINE([HAVE_SEARCHPATH], [1], [Define if cfg_add_searchpath() is available])],
[PKG_CHECK_MODULES(CONFUSE, libconfuse)])
# ------- use all the settings ----------------------
AS_IF([test "x$enable_debug" = "xyes"], [
AC_DEFINE(ENABLE_DEBUG, [1], [Debug messages.])
])
# Enable "-fvisibility=hidden" only if the used gcc supports it
AS_IF([test "${enable_hide}" = "yes"],
[AC_MSG_CHECKING([whether the compiler supports -fvisibility=hidden])
CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], [], [enable_hide=no])
# still enabled?
if test "x${enable_hide}" = "xyes"; then
AC_DEFINE(DSO_HIDDEN, 1, [hide internal library symbols])
AM_CFLAGS="${AM_CFLAGS} -fvisibility=hidden"
fi
AC_MSG_RESULT([${enable_hide}])])
AC_SUBST(AM_CFLAGS)
# be very silent on request
AM_CONDITIONAL(BUILD_SILENTLY, test "x$AM_DEFAULT_VERBOSITY" = x0)
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_FILES([
Makefile
])
AC_REQUIRE_AUX_FILE([tap-driver.sh])
AC_OUTPUT
AC_MSG_RESULT([
$PACKAGE $VERSION
=====
prefix: ${prefix}
compiler: ${CC}
cflags: ${CFLAGS} ${AM_CFLAGS}
ldflags: ${LDFLAGS} ${AM_LDFLAGS}
debug: ${enable_debug}
hide symbols: ${enable_hide}
libconfuse: ${CONFUSE_LIBS}
])
genimage-19/crc32.c 0000664 0000000 0000000 00000006666 15032005261 0014151 0 ustar 00root root 0000000 0000000 #include
#include
#include "genimage.h"
static const uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t crc32_next(const void *data, size_t len, uint32_t last_crc)
{
uint32_t crc = ~last_crc;
const char *p = data;
while (len--)
crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return ~crc;
}
uint32_t crc32(const void *data, size_t len)
{
return crc32_next(data, len, 0);
}
genimage-19/flash.conf 0000664 0000000 0000000 00000000444 15032005261 0015021 0 ustar 00root root 0000000 0000000 flash nand-64M-512 {
pebsize = 16384
lebsize = 15360
numpebs = 4096
minimum-io-unit-size = 512
vid-header-offset = 512
sub-page-size = 512
}
flash nor-64M-128k {
pebsize = 131072
lebsize = 130944
numpebs = 256
minimum-io-unit-size = 1
vid-header-offset = 64
sub-page-size = 1
}
genimage-19/genimage.c 0000664 0000000 0000000 00000050050 15032005261 0014773 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "genimage.h"
/*
* TODO:
*
* - add documentation
* - implement missing image types (cpio, iso)
* - free memory after usage
* - make more failsafe (does flashtype exist where necessary)
* - implement command line switches (--verbose, --dry-run, --config=)
*
*/
static struct image_handler *handlers[] = {
&android_sparse_handler,
&cpio_handler,
&cramfs_handler,
&custom_handler,
&erofs_handler,
&ext2_handler,
&ext3_handler,
&ext4_handler,
&f2fs_handler,
&mdraid_handler,
&btrfs_handler,
&file_handler,
&fit_handler,
&fip_handler,
&flash_handler,
&hdimage_handler,
&iso_handler,
&jffs2_handler,
&qemu_handler,
&rauc_handler,
&squashfs_handler,
&tar_handler,
&ubi_handler,
&ubifs_handler,
&vfat_handler,
};
static int image_set_handler(struct image *image, cfg_t *cfg)
{
unsigned int i;
int num = 0, x;
for (i = 0; i < ARRAY_SIZE(handlers); i++) {
struct image_handler *handler = handlers[i];
x = cfg_size(cfg, handler->type);
if (x)
image->handler = handler;
num += x;
}
if (num > 1) {
image_error(image, "multiple image types given\n");
exit(1);
}
if (num < 1) {
image_error(image, "no image type given\n");
exit(1);
}
image->imagesec = cfg_getsec(cfg, image->handler->type);
return 0;
}
static cfg_opt_t partition_opts[] = {
CFG_STR("offset", NULL, CFGF_NONE),
CFG_STR("size", NULL, CFGF_NONE),
CFG_STR("align", NULL, CFGF_NONE),
CFG_INT("partition-type", 0, CFGF_NONE),
CFG_BOOL("bootable", cfg_false, CFGF_NONE),
CFG_BOOL("forced-primary", cfg_false, CFGF_NONE),
CFG_BOOL("read-only", cfg_false, CFGF_NONE),
CFG_BOOL("hidden", cfg_false, CFGF_NONE),
CFG_BOOL("no-automount", cfg_false, CFGF_NONE),
CFG_BOOL("fill", cfg_false, CFGF_NONE),
CFG_BOOL("sparse", cfg_true, CFGF_NONE),
CFG_STR("image", NULL, CFGF_NONE),
CFG_STR_LIST("holes", NULL, CFGF_NONE),
CFG_STR("imageoffset", NULL, CFGF_NONE),
CFG_BOOL("autoresize", 0, CFGF_NONE),
CFG_BOOL("in-partition-table", cfg_true, CFGF_NONE),
CFG_STR("partition-uuid", NULL, CFGF_NONE),
CFG_STR("partition-type-uuid", NULL, CFGF_NONE),
CFG_END()
};
static cfg_opt_t image_common_opts[] = {
CFG_STR("name", NULL, CFGF_NONE),
CFG_STR("size", NULL, CFGF_NONE),
CFG_STR("mountpoint", NULL, CFGF_NONE),
CFG_STR("srcpath", NULL, CFGF_NONE),
CFG_BOOL("empty", cfg_false, CFGF_NONE),
CFG_BOOL("temporary", cfg_false, CFGF_NONE),
CFG_STR("exec-pre", NULL, CFGF_NONE),
CFG_STR("exec-post", NULL, CFGF_NONE),
CFG_STR("flashtype", NULL, CFGF_NONE),
CFG_SEC("partition", partition_opts, CFGF_MULTI | CFGF_TITLE),
CFG_FUNC("include", &cfg_include),
};
static cfg_opt_t flashchip_opts[] = {
CFG_STR("pebsize", "", CFGF_NONE),
CFG_STR("lebsize", "", CFGF_NONE),
CFG_STR("numpebs", "", CFGF_NONE),
CFG_STR("minimum-io-unit-size", "", CFGF_NONE),
CFG_STR("vid-header-offset", "", CFGF_NONE),
CFG_STR("sub-page-size", "", CFGF_NONE),
CFG_END()
};
static LIST_HEAD(images);
/*
* find an image corresponding to a filename
*/
struct image *image_get(const char *filename)
{
struct image *image;
list_for_each_entry(image, &images, list) {
if (!strcmp(image->file, filename))
return image;
}
return NULL;
}
/*
* setup the images. Calls ->setup function for each
* image, recursively calls itself for resolving dependencies
*/
static int image_setup(struct image *image)
{
int ret = 0;
struct partition *part;
if (image->done < 0)
return 0;
if (image->seen < 0) {
image_error(image, "recursive dependency detected\n");
return -EINVAL;
}
image->seen = -1;
if (image->size_is_percent) {
image->size = image_dir_size(image) * image->size / 100;
image->size_is_percent = cfg_false;
}
list_for_each_entry(part, &image->partitions, list) {
struct image *child;
if (!part->image)
continue;
child = image_get(part->image);
if (!child) {
image_error(image, "could not find %s\n", part->image);
return -EINVAL;
}
ret = image_setup(child);
if (ret) {
image_error(image, "could not setup %s\n", child->file);
return ret;
}
}
if (image->handler->setup)
ret = image->handler->setup(image, image->imagesec);
if (ret)
return ret;
image->done = -1;
return 0;
}
static int overwriteenv(const char *name, const char *value)
{
int ret;
ret = setenv(name, value ?: "", 1);
if (ret)
return -errno;
return 0;
}
static int setenv_paths(void)
{
int ret;
ret = overwriteenv("OUTPUTPATH", imagepath());
if (ret)
return ret;
ret = overwriteenv("INPUTPATH", inputpath());
if (ret)
return ret;
ret = overwriteenv("ROOTPATH", rootpath());
if (ret)
return ret;
ret = overwriteenv("TMPPATH", tmppath());
if (ret)
return ret;
return 0;
}
static int setenv_image(const struct image *image)
{
int ret;
char sizestr[20];
snprintf(sizestr, sizeof(sizestr), "%llu", image->size);
ret = overwriteenv("IMAGE", image->file);
if (ret)
return ret;
ret = overwriteenv("IMAGEOUTFILE", imageoutfile(image));
if (ret)
return ret;
ret = overwriteenv("IMAGENAME", image->name);
if (ret)
return ret;
ret = overwriteenv("IMAGESIZE", sizestr);
if (ret)
return ret;
ret = overwriteenv("IMAGEMOUNTPOINT", image->mountpoint);
if (ret)
return ret;
ret = overwriteenv("IMAGEMOUNTPATH", image->empty ? NULL : mountpath(image));
if (ret)
return ret;
return 0;
}
/*
* generate the images. Calls ->generate function for each
* image, recursively calls itself for resolving dependencies
*/
static int image_generate(struct image *image)
{
int ret;
struct partition *part;
if (image->done > 0)
return 0;
if (image->seen > 0) {
image_error(image, "recursive dependency detected\n");
return -EINVAL;
}
image->seen = 1;
list_for_each_entry(part, &image->partitions, list) {
struct image *child;
if (!part->image)
continue;
child = image_get(part->image);
if (!child) {
image_error(image, "could not find %s\n", part->image);
return -EINVAL;
}
ret = image_generate(child);
if (ret) {
image_error(image, "could not generate %s\n", child->file);
return ret;
}
}
ret = setenv_image(image);
if (ret)
return ret;
if (image->exec_pre) {
ret = systemp(image, "%s", image->exec_pre);
if (ret)
return ret;
}
if (image->handler->generate) {
ret = image->handler->generate(image);
} else {
image_error(image, "no generate function for %s\n", image->file);
return -EINVAL;
}
if (ret) {
struct stat s;
if (lstat(imageoutfile(image), &s) != 0 ||
((s.st_mode & S_IFMT) == S_IFREG) ||
((s.st_mode & S_IFMT) == S_IFLNK))
systemp(image, "rm -f \"%s\"", imageoutfile(image));
return ret;
}
if (image->exec_post) {
ret = systemp(image, "%s", image->exec_post);
if (ret)
return ret;
}
image->done = 1;
return 0;
}
static LIST_HEAD(flashlist);
static int parse_flashes(cfg_t *cfg)
{
int num_flashes;
int i;
num_flashes = cfg_size(cfg, "flash");
for (i = 0; i < num_flashes; i++) {
cfg_t *flashsec = cfg_getnsec(cfg, "flash", i);
struct flash_type *flash = xzalloc(sizeof *flash);
flash->name = cfg_title(flashsec);
flash->pebsize = cfg_getint_suffix(flashsec, "pebsize");
flash->lebsize = cfg_getint_suffix(flashsec, "lebsize");
flash->numpebs = cfg_getint_suffix(flashsec, "numpebs");
flash->minimum_io_unit_size = cfg_getint_suffix(flashsec, "minimum-io-unit-size");
flash->vid_header_offset = cfg_getint_suffix(flashsec, "vid-header-offset");
flash->sub_page_size = cfg_getint_suffix(flashsec, "sub-page-size");
list_add_tail(&flash->list, &flashlist);
}
return 0;
}
struct flash_type *flash_type_get(const char *name)
{
struct flash_type *flash;
list_for_each_entry(flash, &flashlist, list) {
if (!strcmp(flash->name, name))
return flash;
}
return NULL;
}
static int parse_partitions(struct image *image, cfg_t *imagesec)
{
struct partition *part;
int num_partitions;
int i;
num_partitions = cfg_size(imagesec, "partition");
for (i = 0; i < num_partitions; i++) {
cfg_t *partsec = cfg_getnsec(imagesec, "partition", i);
part = xzalloc(sizeof *part);
part->cfg = partsec;
part->name = cfg_title(partsec);
list_add_tail(&part->list, &image->partitions);
part->size = cfg_getint_suffix(partsec, "size");
part->offset = cfg_getint_suffix(partsec, "offset");
part->align = cfg_getint_suffix(partsec, "align");
part->partition_type = cfg_getint(partsec, "partition-type");
part->bootable = cfg_getbool(partsec, "bootable");
part->forced_primary = cfg_getbool(partsec, "forced-primary");
part->read_only = cfg_getbool(partsec, "read-only");
part->hidden = cfg_getbool(partsec, "hidden");
part->no_automount = cfg_getbool(partsec, "no-automount");
part->fill = cfg_getbool(partsec, "fill");
part->sparse = cfg_getbool(partsec, "sparse");
part->image = cfg_getstr(partsec, "image");
part->imageoffset = cfg_getint_suffix(partsec, "imageoffset");
part->autoresize = cfg_getbool(partsec, "autoresize");
part->in_partition_table = cfg_getbool(partsec, "in-partition-table");
part->partition_type_uuid = cfg_getstr(partsec, "partition-type-uuid");
part->partition_uuid = cfg_getstr(partsec, "partition-uuid");
}
return 0;
}
static int set_flash_type(void)
{
struct image *image;
list_for_each_entry(image, &images, list) {
struct partition *part;
if (!image->flash_type)
continue;
list_for_each_entry(part, &image->partitions, list) {
struct image *i;
if (!part->image)
continue;
i = image_get(part->image);
if (!i)
return -EINVAL;
if (i->flash_type) {
if (i->flash_type != image->flash_type) {
image_error(i, "conflicting flash types: %s has flashtype %s whereas %s has flashtype %s\n",
i->file, i->flash_type->name, image->file, image->flash_type->name);
return -EINVAL;
}
} else {
i->flash_type = image->flash_type;
}
}
}
return 0;
}
static LIST_HEAD(mountpoints);
static struct mountpoint *get_mountpoint(const char *path)
{
struct mountpoint *mp;
list_for_each_entry(mp, &mountpoints, list) {
if (!strcmp(mp->path, path))
return mp;
}
return NULL;
}
char *sanitize_path(const char *path)
{
char *path_sanitized;
char *c;
path_sanitized = strdup(path);
c = path_sanitized;
while ((c = strchr(c, '/'))) {
*c = '-';
c++;
}
return path_sanitized;
}
static struct mountpoint *add_mountpoint(const char *path)
{
struct mountpoint *mp;
char *path_sanitized;
mp = get_mountpoint(path);
if (mp)
return mp;
path_sanitized = sanitize_path(path);
mp = xzalloc(sizeof(*mp));
mp->path = strdup(path);
xasprintf(&mp->mountpath, "%s/mp-%s", tmppath(), path_sanitized);
list_add_tail(&mp->list, &mountpoints);
free(path_sanitized);
return mp;
}
static void add_root_mountpoint(void)
{
struct mountpoint *mp;
mp = xzalloc(sizeof(*mp));
mp->path = strdup("");
xasprintf(&mp->mountpath, "%s/root", tmppath());
list_add_tail(&mp->list, &mountpoints);
}
static int collect_mountpoints(void)
{
struct image *image;
struct mountpoint *mp;
int ret, need_mtime_fixup = 0, need_root = 0;
list_for_each_entry(image, &images, list) {
if (!(image->empty || image->handler->no_rootpath || image->srcpath)) {
need_root = 1;
break;
}
}
if (!need_root) {
disable_rootpath();
return 0;
}
add_root_mountpoint();
ret = systemp(NULL, "mkdir -p \"%s\"", tmppath());
if (ret)
return ret;
ret = systemp(NULL, "cp -a \"%s\" \"%s/root\"", rootpath(), tmppath());
if (ret)
return ret;
list_for_each_entry(image, &images, list) {
if (image->mountpoint)
image->mp = add_mountpoint(image->mountpoint);
}
list_for_each_entry(mp, &mountpoints, list) {
if (!strlen(mp->path))
continue;
ret = systemp(NULL, "mv \"%s/root/%s\" \"%s\"", tmppath(), mp->path, mp->mountpath);
if (ret)
return ret;
ret = systemp(NULL, "mkdir \"%s/root/%s\"", tmppath(), mp->path);
if (ret)
return ret;
ret = systemp(NULL, "chmod --reference=\"%s\" \"%s/root/%s\"", mp->mountpath, tmppath(), mp->path);
if (ret)
return ret;
ret = systemp(NULL, "chown --reference=\"%s\" \"%s/root/%s\"", mp->mountpath, tmppath(), mp->path);
if (ret)
return ret;
need_mtime_fixup = 1;
}
/*
* After the mv/mkdir of the mountpoints the timestamps of the
* mountpoint and all parent dirs are changed. Fix that here.
*/
if (need_mtime_fixup)
ret = systemp(NULL,
"find '%s/root' -depth -type d -printf '%%P\\0' | xargs -0 -I {} touch -r '%s/{}' '%s/root/{}'",
tmppath(), rootpath(), tmppath());
return ret;
}
const char *mountpath(const struct image *image)
{
if (image->srcpath)
return image->srcpath;
struct mountpoint *mp;
if (image->empty || image->handler->no_rootpath)
return "";
mp = image->mp;
if (!mp)
mp = get_mountpoint("");
return mp->mountpath;
}
static enum {
TMPPATH_NONE,
TMPPATH_CHECKED,
TMPPATH_CREATED
} tmppath_generated;
static void check_tmp_path(void)
{
const char *tmp = tmppath();
int ret;
DIR *dir;
int i = 0;
if (!tmp) {
error("tmppath not set. aborting\n");
exit(1);
}
dir = opendir(tmp);
if (!dir) {
ret = systemp(NULL, "mkdir -p \"%s\"", tmppath());
if (ret)
exit(1);
tmppath_generated = TMPPATH_CREATED;
return;
}
while (1) {
if (!readdir(dir))
break;
i++;
if (i > 2) {
error("tmppath '%s' exists and is not empty\n", tmp);
exit(1);
}
}
tmppath_generated = TMPPATH_CHECKED;
closedir(dir);
}
static void cleanup(void)
{
switch (tmppath_generated) {
case TMPPATH_CREATED:
systemp(NULL, "rm -rf \"%s/\"", tmppath());
break;
case TMPPATH_CHECKED:
systemp(NULL, "rm -rf \"%s\"/*", tmppath());
break;
default:
break;
}
}
static cfg_opt_t top_opts[] = {
CFG_SEC("image", NULL, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("flash", flashchip_opts, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("config", NULL, CFGF_MULTI),
CFG_FUNC("include", &cfg_include),
CFG_END()
};
#ifdef HAVE_SEARCHPATH
static int add_searchpath(cfg_t *cfg, const char *dir)
{
if (cfg_add_searchpath(cfg, dir)) {
error("error adding %s to include search path", dir);
return -1;
}
return 0;
}
static int set_include_path(cfg_t *cfg, const char *path)
{
char *dup, *s, *e;
int ret;
e = dup = strdup(path);
do {
s = e;
e = strchr(s, ':');
if (e)
*e++ = '\0';
ret = add_searchpath(cfg, s);
if (ret)
goto out;
} while (e);
/* Make sure current directory is always searched. */
ret = add_searchpath(cfg, ".");
out:
free(dup);
return ret;
}
#endif
int main(int argc, char *argv[])
{
unsigned int i;
unsigned int num_images;
int ret;
cfg_opt_t *imageopts = xzalloc((ARRAY_SIZE(image_common_opts) +
ARRAY_SIZE(handlers) + 1) *
sizeof(cfg_opt_t));
int start;
struct image *image;
const char *str;
cfg_t *cfg;
struct partition *part;
cfg_opt_t image_end[] = {
CFG_END()
};
struct timeval tv;
/* Seed the rng */
gettimeofday(&tv, NULL);
srandom(tv.tv_usec);
memcpy(imageopts, image_common_opts, sizeof(image_common_opts));
start = ARRAY_SIZE(image_common_opts);
for (i = 0; i < ARRAY_SIZE(handlers); i++) {
struct image_handler *handler = handlers[i];
cfg_opt_t image_tmp[] = {
CFG_SEC("dummy", NULL, CFGF_MULTI),
};
image_tmp[0].name = handler->type;
image_tmp[0].subopts = handler->opts;
memcpy(&imageopts[start + i], image_tmp, sizeof(cfg_opt_t));
}
memcpy(&imageopts[start + i], &image_end[0], sizeof(cfg_opt_t));
top_opts[0].subopts = imageopts;
init_config();
top_opts[2].subopts = get_confuse_opts();
/* call set_config_opts to make get_opt("config") work */
set_config_opts(argc, argv, NULL);
cfg = cfg_init(top_opts, CFGF_NONE);
str = get_opt("includepath");
if (str) {
#ifdef HAVE_SEARCHPATH
ret = set_include_path(cfg, str);
if (ret)
goto cleanup;
#else
error("--includepath used, but genimage built with too old libconfuse\n");
ret = -1;
goto cleanup;
#endif
}
ret = cfg_parse(cfg, get_opt("config"));
switch (ret) {
case 0:
break;
case CFG_PARSE_ERROR:
goto cleanup;
case CFG_FILE_ERROR:
error("could not open config file '%s'\n", get_opt("config"));
goto cleanup;
}
/* again, with config file this time */
set_config_opts(argc, argv, cfg);
str = get_opt("configdump");
if (str) {
FILE *dump;
dump = (strcmp(str, "-")) ? fopen(str, "w") : stdout;
if (!dump) {
error("could not open dump file %s: %s", str, strerror(errno));
ret = -1;
goto cleanup;
}
cfg_print(cfg, dump);
if (dump != stdout)
fclose(dump);
}
check_tmp_path();
ret = systemp(NULL, "rm -rf \"%s\"/*", tmppath());
if (ret)
goto cleanup;
parse_flashes(cfg);
num_images = cfg_size(cfg, "image");
for (i = 0; i < num_images; i++) {
cfg_t *imagesec = cfg_getnsec(cfg, "image", i);
image = xzalloc(sizeof *image);
INIT_LIST_HEAD(&image->partitions);
list_add_tail(&image->list, &images);
image->file = cfg_title(imagesec);
image->name = cfg_getstr(imagesec, "name");
image->size = cfg_getint_suffix_percent(imagesec, "size",
&image->size_is_percent);
image->srcpath = cfg_getstr(imagesec, "srcpath");
image->mountpoint = cfg_getstr(imagesec, "mountpoint");
image->empty = cfg_getbool(imagesec, "empty");
image->temporary = cfg_getbool(imagesec, "temporary");
image->exec_pre = cfg_getstr(imagesec, "exec-pre");
image->exec_post = cfg_getstr(imagesec, "exec-post");
if (image->file[0] == '/')
image->outfile = strdup(image->file);
else
xasprintf(&image->outfile, "%s/%s",
image->temporary ? tmppath() : imagepath(),
image->file);
if (image->mountpoint && *image->mountpoint == '/')
image->mountpoint++;
if (image->srcpath && image->mountpoint && (strlen(image->mountpoint) > 0)) {
image_error(image, "Cannot specify both srcpath and mountpoint at the same time.");
goto cleanup;
}
str = cfg_getstr(imagesec, "flashtype");
if (str)
image->flash_type = flash_type_get(str);
image_set_handler(image, imagesec);
parse_partitions(image, imagesec);
if (image->handler->parse) {
ret = image->handler->parse(image, image->imagesec);
if (ret)
goto cleanup;
}
}
/* check if each partition has a corresponding image */
list_for_each_entry(image, &images, list) {
list_for_each_entry(part, &image->partitions, list) {
struct image *child;
if (!part->image) {
if (part->in_partition_table)
continue;
image_error(image, "no input file given\n");
ret = -EINVAL;
goto cleanup;
}
child = image_get(part->image);
if (child) {
if (cfg_size(part->cfg, "holes") > 0) {
image_error(image, "holes in partitions are only valid for implicit child images!\n");
ret = -EINVAL;
goto cleanup;
}
continue;
}
image_debug(image, "adding implicit file rule for '%s'\n", part->image);
child = xzalloc(sizeof *image);
INIT_LIST_HEAD(&child->partitions);
list_add_tail(&child->list, &images);
child->file = part->image;
child->handler = &file_handler;
if (child->handler->parse) {
ret = child->handler->parse(child, child->imagesec);
if (ret)
goto cleanup;
}
parse_holes(child, part->cfg);
}
}
/* propagate flash types to partitions */
ret = set_flash_type();
if (ret)
goto cleanup;
ret = collect_mountpoints();
if (ret)
goto cleanup;
list_for_each_entry(image, &images, list) {
ret = image_setup(image);
if (ret)
goto cleanup;
}
ret = setenv_paths();
if (ret)
goto cleanup;
ret = systemp(NULL, "mkdir -p \"%s\"", imagepath());
if (ret)
goto cleanup;
list_for_each_entry(image, &images, list) {
ret = image_generate(image);
if (ret) {
image_error(image, "failed to generate %s\n", image->file);
goto cleanup;
}
}
cleanup:
cleanup();
return ret ? 1 : 0;
}
genimage-19/genimage.h 0000664 0000000 0000000 00000015454 15032005261 0015011 0 ustar 00root root 0000000 0000000 #ifndef __PTX_IMAGE_H
#define __PTX_IMAGE_H
#include
#include
#include "list.h"
struct image_handler;
struct image *image_get(const char *filename);
int systemp(struct image *image, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void error(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void info(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void debug(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void image_error(struct image *image, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void image_info(struct image *image, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void image_debug(struct image *image, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void xasprintf(char **strp, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void xstrcatf(char **strp, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
unsigned long long roundup(unsigned long long value, unsigned long long align);
unsigned long long rounddown(unsigned long long value, unsigned long long align);
unsigned long long min_ull(unsigned long long x, unsigned long long y);
unsigned long long max_ull(unsigned long long x, unsigned long long y);
void disable_rootpath(void);
const char *imagepath(void);
const char *inputpath(void);
const char *rootpath(void);
const char *tmppath(void);
const char *mountpath(const struct image *);
struct flash_type;
struct mountpoint {
char *path;
struct list_head list;
char *mountpath;
};
struct partition {
unsigned long long offset;
unsigned long long size;
unsigned long long align;
unsigned char partition_type;
cfg_bool_t bootable;
cfg_bool_t logical;
cfg_bool_t forced_primary;
cfg_bool_t read_only;
cfg_bool_t hidden;
cfg_bool_t no_automount;
cfg_bool_t fill;
cfg_bool_t sparse;
const char *image;
unsigned long long imageoffset;
struct list_head list;
int autoresize;
int in_partition_table;
const char *name;
const char *partition_type_uuid;
const char *partition_uuid;
cfg_t *cfg;
};
struct image {
const char *name;
const char *file;
unsigned long long size;
struct extent *holes;
int n_holes;
cfg_bool_t size_is_percent;
const char *mountpoint;
const char *srcpath;
cfg_bool_t empty;
cfg_bool_t temporary;
const char *exec_pre;
const char *exec_post;
unsigned char partition_type;
void *handler_priv;
struct image_handler *handler;
struct list_head list;
int done;
struct flash_type *flash_type;
cfg_t *imagesec;
struct list_head partitions;
struct mountpoint *mp;
char *outfile;
int seen;
off_t last_offset;
};
struct image_handler {
char *type;
cfg_bool_t no_rootpath;
int (*parse)(struct image *i, cfg_t *cfg);
int (*setup)(struct image *i, cfg_t *cfg);
int (*generate)(struct image *i);
cfg_opt_t *opts;
};
struct flash_type {
const char *name;
int pebsize;
int lebsize;
int numpebs;
int minimum_io_unit_size;
int vid_header_offset;
int sub_page_size;
struct list_head list;
};
struct gpt_partition_type_shortcut_t {
const char *shortcut;
const char *guid;
};
struct flash_type *flash_type_get(const char *name);
extern struct image_handler android_sparse_handler;
extern struct image_handler cpio_handler;
extern struct image_handler cramfs_handler;
extern struct image_handler custom_handler;
extern struct image_handler erofs_handler;
extern struct image_handler ext2_handler;
extern struct image_handler ext3_handler;
extern struct image_handler ext4_handler;
extern struct image_handler f2fs_handler;
extern struct image_handler mdraid_handler;
extern struct image_handler btrfs_handler;
extern struct image_handler file_handler;
extern struct image_handler flash_handler;
extern struct image_handler hdimage_handler;
extern struct image_handler iso_handler;
extern struct image_handler jffs2_handler;
extern struct image_handler qemu_handler;
extern struct image_handler rauc_handler;
extern struct image_handler squashfs_handler;
extern struct image_handler tar_handler;
extern struct image_handler ubi_handler;
extern struct image_handler ubifs_handler;
extern struct image_handler vfat_handler;
extern struct image_handler fit_handler;
extern struct image_handler fip_handler;
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) ); })
void *xzalloc(size_t n);
void *xrealloc(void *ptr, size_t size);
unsigned long long strtoul_suffix(const char *str, char **endp,
cfg_bool_t *percent);
int init_config(void);
cfg_opt_t *get_confuse_opts(void);
const char *get_opt(const char *name);
const struct gpt_partition_type_shortcut_t *get_gpt_shortcuts(void);
int set_config_opts(int argc, char *argv[], cfg_t *cfg);
static inline size_t min(size_t a, size_t b)
{
return a < b ? a : b;
}
enum pad_mode {
MODE_APPEND,
MODE_OVERWRITE,
};
struct extent {
unsigned long long start, end;
};
int open_file(struct image *image, const char *filename, int extra_flags);
int whole_file_exent(size_t size, struct extent **extents,
size_t *extent_count);
int map_file_extents(struct image *image, const char *filename, int fd,
size_t size, struct extent **extents, size_t *extent_count);
int is_block_device(const char *filename);
int block_device_size(struct image *image, const char *blkdev,
unsigned long long *size);
int prepare_image(struct image *image, unsigned long long size);
int insert_image(struct image *image, struct image *sub,
unsigned long long size, unsigned long long offset,
unsigned long long imageoffset,
unsigned char byte, cfg_bool_t sparse);
int insert_data(struct image *image, const void *data, const char *outfile,
size_t size, unsigned long long offset);
int extend_file(struct image *image, size_t size);
int reload_partitions(struct image *image);
int parse_holes(struct image *image, cfg_t *cfg);
unsigned long long cfg_getint_suffix(cfg_t *sec, const char *name);
unsigned long long cfg_getint_suffix_percent(cfg_t *sec, const char *name,
cfg_bool_t *percent);
static inline const char *imageoutfile(const struct image *image)
{
return image->outfile;
}
char *sanitize_path(const char *path);
int uuid_validate(const char *str);
void uuid_parse(const char *str, unsigned char *uuid);
char *uuid_random(void);
unsigned long long image_dir_size(struct image *image);
uint32_t crc32(const void *data, size_t len);
uint32_t crc32_next(const void *data, size_t len, uint32_t last_crc);
#define ct_assert(e) _Static_assert(e, #e)
#endif /* __PTX_IMAGE_H */
genimage-19/image-android-sparse.c 0000664 0000000 0000000 00000026655 15032005261 0017230 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2021 Michael Olbrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "genimage.h"
struct sparse {
uint32_t block_size;
cfg_bool_t fill_holes;
cfg_bool_t add_crc;
};
struct sparse_header {
uint32_t magic;
uint16_t major_version;
uint16_t minor_version;
uint16_t header_size;
uint16_t chunk_header_size;
uint32_t block_size;
uint32_t output_blocks;
uint32_t input_chunks;
uint32_t crc32;
} __attribute__((packed));
#define SPARSE_RAW htole16(0xCAC1)
#define SPARSE_FILL htole16(0xCAC2)
#define SPARSE_DONT_CARE htole16(0xCAC3)
#define SPARSE_CRC32 htole16(0xCAC4)
struct sparse_chunk_header {
uint16_t chunk_type;
uint16_t reserved;
uint32_t blocks;
uint32_t size;
} __attribute__((packed));
static int write_data(struct image *image, int fd, const void *data, size_t size)
{
int ret = 0;
ssize_t written = write(fd, data, size);
if (written < 0) {
ret = -errno;
image_error(image, "write %s: %s\n", imageoutfile(image), strerror(errno));
} else if ((size_t)written != size) {
image_error(image, "only %llu bytes written instead of %llu\n",
(unsigned long long)written, (unsigned long long)size);
ret = -EINVAL;
}
return ret;
}
static int flush_header(struct image *image, int fd, struct sparse_chunk_header *header,
ssize_t offset)
{
int ret;
if (header->chunk_type == 0)
return 0;
if (offset >= 0) {
if (lseek(fd, offset, SEEK_SET) < 0) {
ret = -errno;
image_error(image, "seek %s: %s\n", imageoutfile(image),
strerror(errno));
return ret;
}
}
ret = write_data(image, fd, header, sizeof(*header));
if (ret < 0)
return ret;
if (offset >= 0) {
if (lseek(fd, 0, SEEK_END) < 0) {
ret = -errno;
image_error(image, "seek %s: %s\n", imageoutfile(image),
strerror(errno));
return ret;
}
}
if (header->blocks > 0 || header->chunk_type == SPARSE_CRC32)
image_debug(image, "chunk(0x%04x): blocks =%7u size =%10u bytes\n",
header->chunk_type, header->blocks, header->size);
return 0;
}
static int android_sparse_generate(struct image *image)
{
struct sparse *sparse = image->handler_priv;
struct image *inimage;
const char *infile;
struct sparse_header header;
struct sparse_chunk_header chunk_header = {};
struct extent *extents = NULL;
size_t extent_count, extent, block_count, block;
int in_fd = -1, out_fd = -1, ret;
off_t offset;
unsigned int i;
uint32_t *buf, *zeros, crc32 = 0;
struct stat s;
memset(&header, 0, sizeof(header));
header.magic = htole32(0xed26ff3a);
header.major_version = htole16(0x1);
header.minor_version = htole16(0x0);
header.header_size = htole16(sizeof(struct sparse_header));
header.chunk_header_size = htole16(sizeof(struct sparse_chunk_header));
header.block_size = sparse->block_size;
inimage = image_get(list_first_entry(&image->partitions, struct partition, list)->image);
infile = imageoutfile(inimage);
in_fd = open(infile, O_RDONLY);
if (in_fd < 0) {
ret = -errno;
image_error(image, "open %s: %s\n", infile, strerror(errno));
return ret;
}
ret = fstat(in_fd, &s);
if (ret) {
ret = -errno;
image_error(image, "stat %s: %s\n", infile, strerror(errno));
goto out;
}
block_count = (s.st_size - 1 + sparse->block_size) / sparse->block_size;
header.output_blocks = block_count;
if (sparse->fill_holes)
whole_file_exent(s.st_size, &extents, &extent_count);
else {
ret = map_file_extents(inimage, infile, in_fd, s.st_size, &extents, &extent_count);
if (ret < 0)
goto out;
}
/* The extents may have a different granularity than the chosen block size.
So all start and end of all extents must be aligned accordingly. The
extents may overlap now, so merge them if necessary. */
for (extent = 0; extent < extent_count; ++extent) {
size_t size, max;
int j;
extents[extent].start = extents[extent].start / sparse->block_size *
sparse->block_size;
extents[extent].end = (extents[extent].end - 1 + sparse->block_size) /
sparse->block_size * sparse->block_size;
extents[extent].end = min(extents[extent].end, s.st_size);
for (j = extent - 1; j > 0; --j)
if (extents[j].end != 0)
break;
if (j >= 0 && extents[extent].start <= extents[j].end) {
extents[j].end = extents[extent].end;
extents[extent].start = 0;
extents[extent].end = 0;
}
/* TODO: split extents that are too big */
max = (~(uint32_t)0) - sizeof(struct sparse_chunk_header);
size = extents[extent].end - extents[extent].start;
if (size > max) {
image_error(image, "extents size %llu larger and supported maximum %llu.\n",
(unsigned long long)size, (unsigned long long)max);
ret = -EINVAL;
goto out;
}
}
out_fd = open_file(image, imageoutfile(image), O_TRUNC);
if (out_fd < 0) {
ret = out_fd;
goto out;
}
ret = write_data(image, out_fd, &header, sizeof(header));
if (ret < 0)
goto out;
block = 0;
buf = xzalloc(sparse->block_size);
zeros = xzalloc(sparse->block_size);
memset(zeros, 0, sparse->block_size);
for (extent = 0; extent < extent_count; ++extent) {
uint32_t start_block = extents[extent].start / sparse->block_size;
size_t size = extents[extent].end - extents[extent].start;
uint32_t fill_value = 0;
size_t pos;
/* skip removed extents */
if (size == 0)
continue;
if (block < start_block) {
header.input_chunks++;
chunk_header.chunk_type = SPARSE_DONT_CARE;
chunk_header.blocks = start_block - block;
chunk_header.size = sizeof(chunk_header);
ret = flush_header(image, out_fd, &chunk_header, -1);
if (ret < 0)
return ret;
block = start_block;
for (i = 0; i < chunk_header.blocks; ++i)
crc32 = crc32_next(zeros, sparse->block_size, crc32);
}
offset = lseek(in_fd, extents[extent].start, SEEK_SET);
if (offset < 0) {
ret = -errno;
image_error(image, "seek %s: %s\n", infile, strerror(errno));
goto out;
}
chunk_header.chunk_type = 0;
chunk_header.blocks = 0;
pos = lseek(out_fd, 0, SEEK_CUR);
while (size > 0) {
ssize_t now = min(size, sparse->block_size);
int fill = 1;
ssize_t r = read(in_fd, buf, now);
if (r < 0) {
ret = -errno;
image_error(image, "read %s: %s\n", infile, strerror(errno));
goto out;
} else if (r != now) {
ret = -EINVAL;
image_error(image, "short read %s %lld != %lld\n", infile,
(long long)r, (long long)now);
goto out;
}
/* The sparse format only allows image sizes that are a multiple of
the block size. Pad the last block as needed. */
if ((uint32_t)r < sparse->block_size) {
memset(((char *)buf) + r, 0, sparse->block_size - r);
now = sparse->block_size;
}
crc32 = crc32_next(buf, sparse->block_size, crc32);
for (i = 1; i < sparse->block_size / 4; ++i) {
if (buf[0] != buf[i]) {
fill = 0;
break;
}
}
if (fill) {
if (chunk_header.chunk_type != SPARSE_FILL ||
fill_value != buf[0]) {
header.input_chunks++;
ret = flush_header(image, out_fd, &chunk_header, pos);
if (ret < 0)
return ret;
pos = lseek(out_fd, 0, SEEK_CUR);
chunk_header.chunk_type = SPARSE_FILL;
chunk_header.size = sizeof(chunk_header) + sizeof(buf[0]);
chunk_header.blocks = 0;
fill_value = buf[0];
ret = flush_header(image, out_fd, &chunk_header, -1);
if (ret < 0)
return ret;
ret = write_data(image, out_fd, buf, sizeof(buf[0]));
if (ret < 0)
goto out;
}
chunk_header.blocks++;
} else {
if (chunk_header.chunk_type != SPARSE_RAW) {
header.input_chunks++;
ret = flush_header(image, out_fd, &chunk_header, pos);
if (ret < 0)
return ret;
pos = lseek(out_fd, 0, SEEK_CUR);
chunk_header.chunk_type = SPARSE_RAW;
chunk_header.size = sizeof(chunk_header);
chunk_header.blocks = 0;
ret = flush_header(image, out_fd, &chunk_header, -1);
if (ret < 0)
return ret;
}
chunk_header.blocks++;
chunk_header.size += now;
ret = write_data(image, out_fd, buf, now);
if (ret < 0)
goto out;
}
size -= r;
}
ret = flush_header(image, out_fd, &chunk_header, pos);
if (ret < 0)
return ret;
block = (extents[extent].end - 1 + sparse->block_size) / sparse->block_size;
}
if (block < block_count) {
header.input_chunks++;
chunk_header.chunk_type = SPARSE_DONT_CARE;
chunk_header.blocks = block_count - block;
chunk_header.size = sizeof(chunk_header);
ret = flush_header(image, out_fd, &chunk_header, -1);
if (ret < 0)
return ret;
for (i = 0; i < chunk_header.blocks; ++i)
crc32 = crc32_next(zeros, sparse->block_size, crc32);
}
if (sparse->add_crc) {
/*
* Albeit CRC is supported by the sparse format, the Android
* tools don't honor the support and now starting to fail if an
* CRC is found.
*/
header.input_chunks++;
chunk_header.chunk_type = SPARSE_CRC32;
chunk_header.blocks = 0;
chunk_header.size = sizeof(chunk_header) + sizeof(crc32);
ret = flush_header(image, out_fd, &chunk_header, -1);
if (ret < 0)
return ret;
ret = write_data(image, out_fd, &crc32, sizeof(crc32));
if (ret < 0)
goto out;
}
offset = lseek(out_fd, 0, SEEK_SET);
if (offset < 0) {
ret = -errno;
image_error(image, "seek %s: %s\n", infile, strerror(errno));
goto out;
}
ret = write_data(image, out_fd, &header, sizeof(header));
if (ret < 0)
goto out;
image_info(image, "sparse image with %u chunks and %u blocks\n",
header.input_chunks, header.output_blocks);
out:
close(in_fd);
if (out_fd >= 0)
close(out_fd);
if (extents)
free(extents);
return ret;
}
static int android_sparse_parse(struct image *image, cfg_t *cfg)
{
struct partition *part;
char *src;
src = cfg_getstr(image->imagesec, "image");
if (!src) {
image_error(image, "Mandatory 'image' option is missing!\n");
return -EINVAL;
}
image_info(image, "input image: %s\n", src);
part = xzalloc(sizeof *part);
part->image = src;
list_add_tail(&part->list, &image->partitions);
return 0;
}
static int android_sparse_setup(struct image *image, cfg_t *cfg)
{
struct sparse *sparse = xzalloc(sizeof(*sparse));
sparse->block_size = cfg_getint_suffix(cfg, "block-size");
if (sparse->block_size % 512) {
image_error(image, "block-size %u invalid. It must be a multiple of 512!\n",
sparse->block_size);
return -EINVAL;
}
sparse->fill_holes = cfg_getbool(cfg, "fill-holes");
sparse->add_crc = cfg_getbool(cfg, "add-crc");
image->handler_priv = sparse;
return 0;
}
static cfg_opt_t android_sparse_opts[] = {
CFG_STR("image", NULL, CFGF_NONE),
CFG_STR("block-size", "4k", CFGF_NONE),
CFG_BOOL("fill-holes", cfg_false, CFGF_NONE),
CFG_BOOL("add-crc", cfg_false, CFGF_NONE),
CFG_END()
};
struct image_handler android_sparse_handler = {
.type = "android-sparse",
.no_rootpath = cfg_true,
.generate = android_sparse_generate,
.parse = android_sparse_parse,
.setup = android_sparse_setup,
.opts = android_sparse_opts,
};
genimage-19/image-btrfs.c 0000664 0000000 0000000 00000004304 15032005261 0015420 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2022 Tomas Mudrunka
* Copyright (c) 2024 Fiona Klute
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include "genimage.h"
static int btrfs_generate(struct image *image)
{
struct stat s;
int ret;
const char *label = cfg_getstr(image->imagesec, "label");
const char *extraargs = cfg_getstr(image->imagesec, "extraargs");
ret = prepare_image(image, image->size);
if (ret)
return ret;
ret = systemp(image, "%s %s %s %s %s%s%s %s '%s'",
get_opt("mkfsbtrfs"),
label ? "-L" : "",
label ? label : "",
/* initial filesystem content, if any */
image->empty ? "" : "-r",
image->empty ? "" : "'",
image->empty ? "" : mountpath(image),
image->empty ? "" : "'",
extraargs,
imageoutfile(image)); /* destination file */
if (ret || image->empty)
return ret;
ret = stat(imageoutfile(image), &s);
if (ret) {
image_error(image, "stat(%s) failed: %s\n", imageoutfile(image), strerror(errno));
return ret;
}
if (image->size && image->size != (unsigned long long)s.st_size) {
image_error(image, "Created image is bigger than configured image size: %llu > %llu\n",
(unsigned long long)s.st_size, image->size);
return -E2BIG;
}
if (!image->size)
image->size = s.st_size;
return ret;
}
static cfg_opt_t btrfs_opts[] = {
CFG_STR("label", NULL, CFGF_NONE),
CFG_STR("extraargs", "", CFGF_NONE),
CFG_END()
};
struct image_handler btrfs_handler = {
.type = "btrfs",
.generate = btrfs_generate,
.opts = btrfs_opts,
};
genimage-19/image-cpio.c 0000664 0000000 0000000 00000002762 15032005261 0015240 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int cpio_generate(struct image *image)
{
int ret;
char *format = cfg_getstr(image->imagesec, "format");
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
char *comp = cfg_getstr(image->imagesec, "compress");
ret = systemp(image, "(cd '%s' && find . | %s -H '%s' %s -o %s %s) > '%s'",
mountpath(image),
get_opt("cpio"),
format, extraargs, comp[0] != '\0' ? "|" : "", comp,
imageoutfile(image));
return ret;
}
static cfg_opt_t cpio_opts[] = {
CFG_STR("format", "newc", CFGF_NONE),
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("compress", "", CFGF_NONE),
CFG_END()
};
struct image_handler cpio_handler = {
.type = "cpio",
.generate = cpio_generate,
.opts = cpio_opts,
};
genimage-19/image-cramfs.c 0000664 0000000 0000000 00000002554 15032005261 0015560 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2016 Julien Viard de Galbert
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int cram_generate(struct image *image)
{
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
return systemp(image, "%s%s%s %s '%s' '%s'",
get_opt("mkcramfs"),
image->name ? " -n " : "",
image->name ? image->name : "", /* name */
extraargs,
mountpath(image), /* source dir */
imageoutfile(image)); /* destination file */
}
static cfg_opt_t cram_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_END()
};
struct image_handler cramfs_handler = {
.type = "cramfs",
.generate = cram_generate,
.opts = cram_opts,
};
genimage-19/image-custom.c 0000664 0000000 0000000 00000004134 15032005261 0015613 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2025 Michael Olbrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include "genimage.h"
struct custom {
char *exec;
};
static int custom_generate(struct image *image)
{
struct custom *f = image->handler_priv;
const char *file = imageoutfile(image);
struct stat s;
int ret;
ret = prepare_image(image, image->size);
if (ret < 0)
return ret;
ret = systemp(image, "%s", f->exec);
if (ret)
return ret;
ret = stat(file, &s);
if (ret) {
ret = -errno;
if (ret == -ENOENT)
image_error(image, "command '%s' failed to create '%s'", f->exec, file);
else
image_error(image, "stat(%s) failed: %s\n", file, strerror(errno));
return ret;
}
if (!image->size)
image->size = s.st_size;
return ret;
}
static int custom_setup(struct image *image, cfg_t *cfg)
{
struct custom *c = xzalloc(sizeof(*c));
c->exec = cfg_getstr(cfg, "exec");
if (!c->exec) {
image_error(image, "mandatory option 'exec' is missing\n");
return -EINVAL;
}
image->handler_priv = c;
return 0;
}
static int custom_parse(struct image *image, cfg_t *cfg)
{
if (!image->mountpoint || image->mountpoint[0] == '\0')
image->empty = cfg_true;
return 0;
}
static cfg_opt_t custom_opts[] = {
CFG_STR("exec", NULL, CFGF_NONE),
CFG_END()
};
struct image_handler custom_handler = {
.type = "custom",
.generate = custom_generate,
.setup = custom_setup,
.parse = custom_parse,
.opts = custom_opts,
};
genimage-19/image-erofs.c 0000664 0000000 0000000 00000004230 15032005261 0015414 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2024 Sebastian Muxel , Entner Electronics
* (c) 2025 Michael Olbrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include "genimage.h"
struct erofs {
const char *label;
};
static int erofs_generate(struct image *image)
{
struct erofs *erofs = image->handler_priv;
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
const char *fs_timestamp = cfg_getstr(image->imagesec, "fs-timestamp");
int ret;
ret = systemp(image, "%s %s%s%s %s%s %s '%s' '%s'",
get_opt("mkfserofs"),
erofs->label ? "-L '" : "",
erofs->label ? erofs->label : "",
erofs->label ? "'" : "",
fs_timestamp ? "-T " : "",
fs_timestamp ? fs_timestamp : "",
extraargs,
imageoutfile(image),
mountpath(image));
return ret;
}
static int erofs_setup(struct image *image, cfg_t *cfg)
{
struct erofs *erofs = xzalloc(sizeof(*erofs));
const char *label = cfg_getstr(image->imagesec, "label");
if (label && label[0] == '\0')
label = NULL;
if (label && strlen(label) > 15) {
image_error(image, "Label '%s' is longer that allowes (15 bytes)\n", label);
return -EINVAL;
}
erofs->label = label;
image->handler_priv = erofs;
return 0;
}
static cfg_opt_t erofs_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("label", NULL, CFGF_NONE),
CFG_STR("fs-timestamp", NULL, CFGF_NONE),
CFG_END()
};
struct image_handler erofs_handler = {
.type = "erofs",
.generate = erofs_generate,
.setup = erofs_setup,
.opts = erofs_opts,
};
genimage-19/image-ext2.c 0000664 0000000 0000000 00000014675 15032005261 0015176 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include "genimage.h"
struct ext {
int use_mke2fs;
const char *features;
char *usage_type_args;
char *conf_env;
char *size_features;
};
static int ext2_generate_genext2fs(struct image *image)
{
int ret;
struct ext *ext = image->handler_priv;
const char *extraargs = cfg_getstr(image->imagesec, "extraargs");
const char *label = cfg_getstr(image->imagesec, "label");
ret = systemp(image, "%s %s%s%s --size-in-blocks=%lld -i 16384 '%s' %s",
get_opt("genext2fs"),
image->empty ? "" : "-d '",
image->empty ? "" : mountpath(image),
image->empty ? "" : "'",
image->size / 1024, imageoutfile(image), extraargs);
if (ret)
return ret;
if (ext->features && ext->features[0] != '\0') {
ret = systemp(image, "%s -O '%s' '%s'", get_opt("tune2fs"),
ext->features, imageoutfile(image));
if (ret)
return ret;
}
if (label && label[0] != '\0') {
ret = systemp(image, "%s -L '%s' '%s'", get_opt("tune2fs"),
label, imageoutfile(image));
if (ret)
return ret;
}
return 0;
}
static int ext2_generate_mke2fs(struct image *image)
{
struct ext *ext = image->handler_priv;
const char *extraargs = cfg_getstr(image->imagesec, "extraargs");
const char *label = cfg_getstr(image->imagesec, "label");
const char *root_owner = cfg_getstr(image->imagesec, "root-owner");
const char *options = "lazy_itable_init=0,lazy_journal_init=0";
const char *features = ext->features;
int ret;
if (features && features[0] == '\0')
features = NULL;
if (label && label[0] == '\0')
label = NULL;
ret = prepare_image(image, image->size);
if (ret < 0)
return ret;
return systemp(image, "%s%s -t %s%s -I 256 -E 'root_owner=%s,%s'%s %s%s%s %s %s%s%s %s%s%s '%s' %lldk",
ext->conf_env, get_opt("mke2fs"), image->handler->type,
ext->usage_type_args, root_owner, options, ext->size_features,
image->empty ? "" : "-d '",
image->empty ? "" : mountpath(image),
image->empty ? "" : "'",
extraargs,
label ? "-L '" : "",
label ? label : "",
label ? "'" : "",
features ? "-O '" : "",
features ? features : "",
features ? "'" : "",
imageoutfile(image), image->size / 1024);
}
static int ext2_generate(struct image *image)
{
struct ext *ext = image->handler_priv;
const char *fs_timestamp = cfg_getstr(image->imagesec, "fs-timestamp");
int ret;
if (ext->use_mke2fs)
ret = ext2_generate_mke2fs(image);
else
ret = ext2_generate_genext2fs(image);
if (ret)
return ret;
ret = systemp(image, "%s -pvfD '%s'", get_opt("e2fsck"),
imageoutfile(image));
/* e2fsck return 1 when the filesystem was successfully modified */
if (ret > 2)
return ret;
if (fs_timestamp) {
ret = systemp(image, "echo '"
"set_current_time %s\n"
"set_super_value mkfs_time %s\n"
"set_super_value lastcheck %s\n"
"set_super_value mtime 00000000' | %s -w '%s'",
fs_timestamp, fs_timestamp, fs_timestamp,
get_opt("debugfs"), imageoutfile(image));
if (ret)
return ret;
}
return 0;
}
static int ext2_setup(struct image *image, cfg_t *cfg)
{
struct ext *ext = xzalloc(sizeof(*ext));
const char *conf = cfg_getstr(image->imagesec, "mke2fs-conf");
const char *usage_type = cfg_getstr(image->imagesec, "usage-type");
if (!conf) {
conf = cfg_getstr(image->imagesec, "mke2fs_conf");
if (conf)
image_info(image, "option 'mke2fs_conf' is deprecated, use mke2fs-conf instead.\n");
}
if (!image->size) {
image_error(image, "no size given or must not be zero\n");
return -EINVAL;
}
ext->use_mke2fs = cfg_getbool(cfg, "use-mke2fs");
ext->features = cfg_getstr(image->imagesec, "features");
if (!ext->features) {
if (!ext->use_mke2fs) {
if (!strcmp(image->handler->type, "ext3"))
ext->features = "has_journal";
else if (!strcmp(image->handler->type, "ext4"))
ext->features = "extents,uninit_bg,dir_index,has_journal";
}
}
if (ext->use_mke2fs) {
int is_large = image->size >= 4ll * 1024 * 1024 * 1024;
int is_huge = image->size >= 2048ll * 1024 * 1024 * 1024;
struct stat s;
int ret;
if (conf) {
/* mke2fs ignores a missing config file, so make sure it exists. */
ret = stat(conf, &s);
if (ret) {
image_error(image, "mke2fs.conf(%s) does not exist: %s\n",
conf, strerror(errno));
return -errno;
}
xasprintf(&ext->conf_env, "MKE2FS_CONFIG=\"%s\" ", conf);
} else
ext->conf_env = "";
if (usage_type)
xasprintf(&ext->usage_type_args, " -T '%s'", usage_type);
else
ext->usage_type_args = "";
xasprintf(&ext->size_features, "%s%s",
is_large ? "" : " -O '^large_file'",
is_huge ? "" : " -O '^huge_file'");
} else {
if (conf) {
image_error(image, "'mke2fs.conf' is only used for 'mke2fs'\n");
return -EINVAL;
}
if (usage_type) {
image_error(image, "'usage_type' is only used for 'mke2fs'\n");
return -EINVAL;
}
}
image->handler_priv = ext;
return 0;
}
static cfg_opt_t ext_opts[] = {
CFG_STR("root-owner", "0:0", CFGF_NONE),
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("features", NULL, CFGF_NONE),
CFG_STR("label", NULL, CFGF_NONE),
CFG_STR("fs-timestamp", NULL, CFGF_NONE),
CFG_BOOL("use-mke2fs", cfg_true, CFGF_NONE),
CFG_STR("usage-type", NULL, CFGF_NONE),
CFG_STR("mke2fs-conf", NULL, CFGF_NONE),
CFG_STR("mke2fs_conf", NULL, CFGF_NONE),
CFG_END()
};
struct image_handler ext2_handler = {
.type = "ext2",
.generate = ext2_generate,
.setup = ext2_setup,
.opts = ext_opts,
};
struct image_handler ext3_handler = {
.type = "ext3",
.generate = ext2_generate,
.setup = ext2_setup,
.opts = ext_opts,
};
struct image_handler ext4_handler = {
.type = "ext4",
.generate = ext2_generate,
.setup = ext2_setup,
.opts = ext_opts,
};
genimage-19/image-f2fs.c 0000664 0000000 0000000 00000003263 15032005261 0015143 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2022 Tomas Mudrunka
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int f2fs_generate(struct image *image)
{
int ret;
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
char *label = cfg_getstr(image->imagesec, "label");
extraargs = cfg_getstr(image->imagesec, "extraargs");
ret = prepare_image(image, image->size);
if (ret)
return ret;
ret = systemp(image, "%s %s %s%s%s %s '%s'",
get_opt("mkfsf2fs"),
label ? "-l" : "",
label ? "'" : "",
label ? label : "",
label ? "'" : "",
extraargs,
imageoutfile(image));
if (ret || image->empty)
return ret;
ret = systemp(image, "%s -f '%s' '%s'",
get_opt("sloadf2fs"),
mountpath(image),
imageoutfile(image));
return ret;
}
static cfg_opt_t f2fs_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("label", NULL, CFGF_NONE),
CFG_END()
};
struct image_handler f2fs_handler = {
.type = "f2fs",
.generate = f2fs_generate,
.opts = f2fs_opts,
};
genimage-19/image-file.c 0000664 0000000 0000000 00000004736 15032005261 0015230 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include "genimage.h"
struct file {
char *name;
char *infile;
cfg_bool_t copy;
};
static int file_generate(struct image *image)
{
struct file *f = image->handler_priv;
int ret;
if (!f->copy)
return 0;
if (!strcmp(f->infile, imageoutfile(image)))
return 0;
ret = systemp(image, "cp '%s' '%s'", f->infile, imageoutfile(image));
return ret;
}
static int file_setup(struct image *image, cfg_t *cfg)
{
struct file *f = xzalloc(sizeof(*f));
struct stat s;
int ret;
if (cfg)
f->name = cfg_getstr(cfg, "name");
if (!f->name)
f->name = strdup(image->file);
if (f->name[0] == '/')
f->infile = strdup(f->name);
else
xasprintf(&f->infile, "%s/%s", inputpath(), f->name);
ret = stat(f->infile, &s);
if (ret) {
ret = -errno;
image_error(image, "stat(%s) failed: %s\n", f->infile,
strerror(errno));
return ret;
}
if (!image->size)
image->size = s.st_size;
if (cfg)
f->copy = cfg_getbool(cfg, "copy");
else
f->copy = cfg_false;
if (!f->copy) {
free(image->outfile);
image->outfile = strdup(f->infile);
}
ret = parse_holes(image, cfg);
if (ret)
return ret;
image->handler_priv = f;
return 0;
}
static int file_parse(struct image *image, cfg_t *cfg)
{
/* File type images are used for custom types so assume that the
* rootpath is need when a pre/post command is defined */
if (!image->exec_pre && !image->exec_post)
image->empty = cfg_true;
return 0;
}
static cfg_opt_t file_opts[] = {
CFG_STR("name", NULL, CFGF_NONE),
CFG_BOOL("copy", cfg_true, CFGF_NONE),
CFG_STR_LIST("holes", NULL, CFGF_NONE),
CFG_END()
};
struct image_handler file_handler = {
.type = "file",
.generate = file_generate,
.setup = file_setup,
.parse = file_parse,
.opts = file_opts,
};
genimage-19/image-fip.c 0000664 0000000 0000000 00000012000 15032005261 0015046 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2022 Ahmad Fatoum
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include "genimage.h"
static int fip_generate(struct image *image)
{
struct partition *part;
char *args = strdup("");
const char *extraargs = cfg_getstr(image->imagesec, "extraargs");
int ret;
list_for_each_entry(part, &image->partitions, list) {
struct image *child = image_get(part->image);
char *oldargs;
oldargs = args;
xasprintf(&args, "%s --%s '%s'", args, part->name, imageoutfile(child));
free(oldargs);
}
ret = systemp(image, "%s create %s %s '%s'", get_opt("fiptool"),
args, extraargs, imageoutfile(image));
free(args);
if (ret == 0) {
struct stat statbuf;
ret = stat(imageoutfile(image), &statbuf);
if (ret)
return ret;
image->size = statbuf.st_size;
}
return ret;
}
static void fip_add_part(struct image *image,
const char *name, const char *path)
{
struct partition *part;
part = xzalloc(sizeof *part);
part->image = path;
part->name = name;
list_add_tail(&part->list, &image->partitions);
}
/* clang-format off */
static cfg_opt_t fip_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR_LIST("tos-fw", NULL, CFGF_NONE), /* Secure Payload BL32 (Trusted OS, Extra1, Extra 2) */
/* CFGF_NODEFAULT marks options passed as-is */
CFG_STR("scp-fwu-cfg", NULL, CFGF_NODEFAULT), /* SCP Firmware Updater Configuration FWU SCP_BL2U */
CFG_STR("ap-fwu-cfg", NULL, CFGF_NODEFAULT), /* AP Firmware Updater Configuration BL2U */
CFG_STR("fwu", NULL, CFGF_NODEFAULT), /* Firmware Updater NS_BL2U */
CFG_STR("fwu-cert", NULL, CFGF_NODEFAULT), /* Non-Trusted Firmware Updater certificate */
CFG_STR("tb-fw", NULL, CFGF_NODEFAULT), /* Trusted Boot Firmware BL2 */
CFG_STR("scp-fw", NULL, CFGF_NODEFAULT), /* SCP Firmware SCP_BL2 */
CFG_STR("soc-fw", NULL, CFGF_NODEFAULT), /* EL3 Runtime Firmware BL31 */
CFG_STR("nt-fw", NULL, CFGF_NODEFAULT), /* Non-Trusted Firmware BL33 */
CFG_STR("fw-config", NULL, CFGF_NODEFAULT), /* FW_CONFIG */
CFG_STR("hw-config", NULL, CFGF_NODEFAULT), /* HW_CONFIG */
CFG_STR("tb-fw-config", NULL, CFGF_NODEFAULT), /* TB_FW_CONFIG */
CFG_STR("soc-fw-config", NULL, CFGF_NODEFAULT), /* SOC_FW_CONFIG */
CFG_STR("tos-fw-config", NULL, CFGF_NODEFAULT), /* TOS_FW_CONFIG */
CFG_STR("nt-fw-config", NULL, CFGF_NODEFAULT), /* NT_FW_CONFIG */
CFG_STR("rot-cert", NULL, CFGF_NODEFAULT), /* Root Of Trust key certificate */
CFG_STR("trusted-key-cert", NULL, CFGF_NODEFAULT), /* Trusted key certificate */
CFG_STR("scp-fw-key-cert", NULL, CFGF_NODEFAULT), /* SCP Firmware key certificate */
CFG_STR("soc-fw-key-cert", NULL, CFGF_NODEFAULT), /* SoC Firmware key certificate */
CFG_STR("tos-fw-key-cert", NULL, CFGF_NODEFAULT), /* Trusted OS Firmware key certificate */
CFG_STR("nt-fw-key-cert", NULL, CFGF_NODEFAULT), /* Non-Trusted Firmware key certificate */
CFG_STR("tb-fw-cert", NULL, CFGF_NODEFAULT), /* Trusted Boot Firmware BL2 certificate */
CFG_STR("scp-fw-cert", NULL, CFGF_NODEFAULT), /* SCP Firmware content certificate */
CFG_STR("soc-fw-cert", NULL, CFGF_NODEFAULT), /* SoC Firmware content certificate */
CFG_STR("tos-fw-cert", NULL, CFGF_NODEFAULT), /* Trusted OS Firmware content certificate */
CFG_STR("nt-fw-cert", NULL, CFGF_NODEFAULT), /* Non-Trusted Firmware content certificate */
CFG_STR("sip-sp-cert", NULL, CFGF_NODEFAULT), /* SiP owned Secure Partition content certificate */
CFG_STR("plat-sp-cert", NULL, CFGF_NODEFAULT), /* Platform owned Secure Partition content certificate */
CFG_END()
};
/* clang-format on */
static const char *tos_fw[] = { "tos-fw", "tos-fw-extra1", "tos-fw-extra2" };
static int fip_parse(struct image *image, cfg_t *cfg)
{
unsigned int i, num_tos_fw;
cfg_opt_t *opt;
num_tos_fw = cfg_size(cfg, "tos-fw");
if (num_tos_fw > ARRAY_SIZE(tos_fw)) {
image_error(image, "%u tos-fw binaries given, but maximum is %zu\n",
num_tos_fw, ARRAY_SIZE(tos_fw));
return -EINVAL;
}
for (i = 0; i < num_tos_fw; i++)
fip_add_part(image, tos_fw[i], cfg_getnstr(cfg, "tos-fw", i));
for (opt = fip_opts; opt->type; opt++) {
const char *file;
if (opt->flags != CFGF_NODEFAULT)
continue;
file = cfg_getstr(cfg, opt->name);
if (file)
fip_add_part(image, opt->name, file);
}
return 0;
}
struct image_handler fip_handler = {
.type = "fip",
.no_rootpath = cfg_true,
.generate = fip_generate,
.parse = fip_parse,
.opts = fip_opts,
};
genimage-19/image-fit.c 0000664 0000000 0000000 00000006016 15032005261 0015064 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2018 Sascha Hauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "genimage.h"
static struct partition *partition_by_name(struct image *image, const char *name)
{
struct partition *part;
list_for_each_entry(part, &image->partitions, list)
if (!strcmp(part->name, name))
return part;
return NULL;
}
static int fit_generate(struct image *image)
{
int ret;
struct partition *part, *its;
char *itspath;
int itsfd;
char *keydir = cfg_getstr(image->imagesec, "keydir");
char *keyopt = NULL;
its = partition_by_name(image, "its");
if (!its)
return -EINVAL;
struct image *itsimg = image_get(its->image);
xasprintf(&itspath, "%s/fit.its", tmppath());
/* Copy input its file to temporary path. Use 'cat' to ignore permissions */
ret = systemp(image, "cat '%s' > '%s'", imageoutfile(itsimg), itspath);
if (ret)
return ret;
itsfd = open(itspath, O_WRONLY | O_APPEND);
if (itsfd < 0) {
printf("Cannot open %s: %s\n", itspath, strerror(errno));
return -errno;
}
dprintf(itsfd, "\n");
/* Add /incbin/ to each /images// node */
list_for_each_entry(part, &image->partitions, list) {
struct image *child = image_get(part->image);
const char *file = imageoutfile(child);
const char *target = part->name;
if (part == its)
continue;
dprintf(itsfd, "/ { images { %s { data = /incbin/(\"%s\"); };};};\n", target, file);
}
close(itsfd);
if (keydir && *keydir) {
if (*keydir != '/') {
image_error(image, "'keydir' must be an absolute path\n");
return -EINVAL;
}
xasprintf(&keyopt, "-k '%s'", keydir);
}
ret = systemp(image, "%s -r %s -f '%s' '%s'",
get_opt("mkimage"), keyopt ? keyopt : "", itspath, imageoutfile(image));
if (ret)
image_error(image, "Failed to create FIT image\n");
return ret;
}
static int fit_parse(struct image *image, cfg_t *cfg)
{
struct partition *part;
char *its = cfg_getstr(image->imagesec, "its");
part = xzalloc(sizeof *part);
part->name = "its";
part->image = its;
list_add_tail(&part->list, &image->partitions);
return 0;
}
static cfg_opt_t fit_opts[] = {
CFG_STR("keydir", "", CFGF_NONE),
CFG_STR("its", "", CFGF_NONE),
CFG_END()
};
struct image_handler fit_handler = {
.type = "fit",
.no_rootpath = cfg_true,
.generate = fit_generate,
.parse = fit_parse,
.opts = fit_opts,
};
genimage-19/image-flash.c 0000664 0000000 0000000 00000010307 15032005261 0015375 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "list.h"
#include "genimage.h"
struct flash_image {
};
static int flash_generate(struct image *image)
{
struct partition *part;
unsigned long long end = 0;
int ret;
ret = prepare_image(image, image->size);
if (ret < 0)
return ret;
list_for_each_entry(part, &image->partitions, list) {
struct image *child = NULL;
image_info(image, "writing image partition '%s' (0x%llx@0x%llx)\n",
part->name, part->size, part->offset);
if (part->offset > end) {
ret = insert_image(image, NULL, part->offset - end, end, 0, 0xFF, cfg_false);
if (ret) {
image_error(image, "failed to pad image to size %lld\n",
part->offset);
return ret;
}
}
if (part->image)
child = image_get(part->image);
ret = insert_image(image, child, part->size, part->offset, 0, 0xFF, cfg_false);
if (ret) {
image_error(image, "failed to write image partition '%s'\n",
part->name);
return ret;
}
end = part->offset + part->size;
}
if (image->size > end) {
ret = insert_image(image, NULL, image->size - end, end, 0, 0xFF, cfg_false);
if (ret) {
image_error(image, "failed to pad image to size %lld\n",
image->size);
return ret;
}
}
return 0;
}
static int flash_setup(struct image *image, cfg_t *cfg)
{
struct flash_image *f = xzalloc(sizeof(*f));
struct partition *part;
int last = 0;
unsigned long long partsize = 0, flashsize;
image->handler_priv = f;
if (!image->flash_type) {
image_error(image, "no flash type given\n");
return -EINVAL;
}
flashsize = (unsigned long long)image->flash_type->pebsize * image->flash_type->numpebs;
list_for_each_entry(part, &image->partitions, list) {
if (last) {
image_error(image, "only last partition may have size 0\n");
return -EINVAL;
}
if (!part->size) {
last = 1;
if (partsize > flashsize)
goto err_exceed;
part->size = flashsize - partsize;
}
if (part->size % image->flash_type->pebsize) {
image_error(image, "part %s size (%lld) must be a "
"multiple of erase block size (%i bytes)\n",
part->name, part->size, image->flash_type->pebsize);
return -EINVAL;
}
if (part->offset % image->flash_type->pebsize) {
image_error(image, "part %s offset (%lld) must be a "
"multiple of erase block size (%i bytes)\n",
part->name, part->offset, image->flash_type->pebsize);
return -EINVAL;
}
if (part->offset) {
if (partsize > part->offset) {
image_error(image, "part %s overlaps with previous partition\n",
part->name);
return -EINVAL;
}
} else {
part->offset = partsize;
}
if (part->image) {
struct image *child = image_get(part->image);
if (!child) {
image_error(image, "could not find %s\n",
part->image);
return -EINVAL;
}
if (child->size > part->size) {
image_error(image, "part %s size (%lld) too small for %s (%lld)\n",
part->name, part->size, child->file, child->size);
return -EINVAL;
}
}
partsize = part->offset + part->size;
}
if (partsize > flashsize) {
err_exceed:
image_error(image, "size of partitions (%lld) exceeds flash size (%lld)\n",
partsize, flashsize);
return -EINVAL;
}
if (!image->size)
image->size = partsize;
return 0;
}
static cfg_opt_t flash_opts[] = {
CFG_END()
};
struct image_handler flash_handler = {
.type = "flash",
.no_rootpath = cfg_true,
.generate = flash_generate,
.setup = flash_setup,
.opts = flash_opts,
};
genimage-19/image-hd.c 0000664 0000000 0000000 00000122226 15032005261 0014677 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
* (c) 2011 Michael Olbrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "genimage.h"
#define TYPE_NONE 0
#define TYPE_MBR 1
#define TYPE_GPT 2
#define TYPE_HYBRID (TYPE_MBR | TYPE_GPT)
#define PARTITION_TYPE_EXTENDED 0x0F
struct hdimage {
unsigned int extended_partition_index;
struct partition *extended_partition;
unsigned long long align;
uint32_t disksig;
const char *disk_uuid;
int table_type;
unsigned long long gpt_location;
cfg_bool_t gpt_no_backup;
cfg_bool_t fill;
unsigned long long file_size;
};
struct mbr_partition_entry {
unsigned char boot;
unsigned char first_chs[3];
unsigned char partition_type;
unsigned char last_chs[3];
uint32_t relative_sectors;
uint32_t total_sectors;
} __attribute__((packed));
ct_assert(sizeof(struct mbr_partition_entry) == 16);
struct mbr_tail {
uint32_t disk_signature;
uint16_t copy_protect;
struct mbr_partition_entry part_entry[4];
uint16_t boot_signature;
} __attribute__((packed));
ct_assert(sizeof(struct mbr_tail) == 72);
struct gpt_header {
unsigned char signature[8];
uint32_t revision;
uint32_t header_size;
uint32_t header_crc;
uint32_t reserved;
uint64_t current_lba;
uint64_t backup_lba;
uint64_t first_usable_lba;
uint64_t last_usable_lba;
unsigned char disk_uuid[16];
uint64_t starting_lba;
uint32_t number_entries;
uint32_t entry_size;
uint32_t table_crc;
} __attribute__((packed));
ct_assert(sizeof(struct gpt_header) == 92);
struct gpt_partition_entry {
unsigned char type_uuid[16];
unsigned char uuid[16];
uint64_t first_lba;
uint64_t last_lba;
uint64_t flags;
uint16_t name[36];
} __attribute__((packed));
ct_assert(sizeof(struct gpt_partition_entry) == 128);
#define GPT_ENTRIES 128
#define GPT_SECTORS (1 + GPT_ENTRIES * sizeof(struct gpt_partition_entry) / 512)
#define GPT_REVISION_1_0 0x00010000
#define GPT_PE_FLAG_BOOTABLE (1ULL << 2)
#define GPT_PE_FLAG_READ_ONLY (1ULL << 60)
#define GPT_PE_FLAG_HIDDEN (1ULL << 62)
#define GPT_PE_FLAG_NO_AUTO (1ULL << 63)
static unsigned long long partition_end(const struct partition *part)
{
return part->offset + part->size;
}
static void lba_to_chs(unsigned int lba, unsigned char *chs)
{
const unsigned int hpc = 255;
const unsigned int spt = 63;
unsigned int s, c;
chs[0] = (lba / spt) % hpc;
c = (lba / (spt * hpc));
s = (lba > 0) ? (lba % spt + 1) : 0;
chs[1] = ((c & 0x300) >> 2) | (s & 0xff);
chs[2] = (c & 0xff);
}
static void hdimage_setup_chs(struct mbr_partition_entry *entry,
unsigned long long offset_sectors)
{
lba_to_chs(entry->relative_sectors + offset_sectors,
entry->first_chs);
lba_to_chs(entry->relative_sectors + entry->total_sectors - 1 + offset_sectors,
entry->last_chs);
}
static int hdimage_insert_mbr(struct image *image, struct list_head *partitions)
{
struct hdimage *hd = image->handler_priv;
struct mbr_tail mbr;
struct partition *part;
int ret, i = 0;
if (hd->table_type == TYPE_HYBRID) {
image_info(image, "writing hybrid MBR\n");
} else {
image_info(image, "writing MBR\n");
}
memset(&mbr, 0, sizeof(mbr));
memcpy(&mbr.disk_signature, &hd->disksig, sizeof(hd->disksig));
list_for_each_entry(part, partitions, list) {
struct mbr_partition_entry *entry;
if (!part->in_partition_table || part->logical)
continue;
if (hd->table_type == TYPE_HYBRID && !part->partition_type)
continue;
entry = &mbr.part_entry[i];
entry->boot = part->bootable ? 0x80 : 0x00;
entry->partition_type = part->partition_type;
entry->relative_sectors = part->offset / 512;
entry->total_sectors = part->size / 512;
hdimage_setup_chs(entry, 0);
image_debug(image, "[MBR entry %d]: type=%x start=%d size=%d\n",
i, entry->partition_type,
entry->relative_sectors, entry->total_sectors);
i++;
}
if (hd->table_type == TYPE_HYBRID) {
struct mbr_partition_entry *entry;
entry = &mbr.part_entry[i];
entry->boot = 0x00;
entry->partition_type = 0xee;
entry->relative_sectors = 1;
entry->total_sectors = hd->gpt_location / 512 + GPT_SECTORS - 2;
hdimage_setup_chs(entry, 0);
}
mbr.boot_signature = htole16(0xaa55);
ret = insert_data(image, &mbr, imageoutfile(image), sizeof(mbr), 440);
if (ret) {
if (hd->table_type == TYPE_HYBRID) {
image_error(image, "failed to write hybrid MBR\n");
} else {
image_error(image, "failed to write MBR\n");
}
return ret;
}
return 0;
}
static int hdimage_insert_ebr(struct image *image, struct partition *part)
{
struct hdimage *hd = image->handler_priv;
struct mbr_partition_entry *entry;
char ebr[4 * sizeof(struct mbr_partition_entry) + 2], *part_table;
int ret;
unsigned long long ebr_offset = part->offset - hd->align + 446;
image_debug(image, "writing EBR to sector %llu\n", ebr_offset / 512);
memset(ebr, 0, sizeof(ebr));
part_table = ebr;
entry = (struct mbr_partition_entry *)part_table;
entry->boot = 0x00;
entry->partition_type = part->partition_type;
entry->relative_sectors = hd->align / 512;
entry->total_sectors = part->size / 512;
// absolute CHS address of the logical partition
// equals to absolute partition offset
hdimage_setup_chs(entry, (part->offset - hd->align) / 512);
struct partition *p = part;
list_for_each_entry_continue(p, &image->partitions, list) {
if (!p->logical)
continue;
++entry;
entry->boot = 0x00;
entry->partition_type = PARTITION_TYPE_EXTENDED;
entry->relative_sectors = (p->offset - hd->align - hd->extended_partition->offset) / 512;
entry->total_sectors = (p->size + hd->align) / 512;
// absolute CHS address of the next EBR
// equals to relative address within extended partition + partition start
hdimage_setup_chs(entry, hd->extended_partition->offset / 512);
break;
}
part_table += 4 * sizeof(struct mbr_partition_entry);
part_table[0] = 0x55;
part_table[1] = 0xaa;
ret = insert_data(image, ebr, imageoutfile(image), sizeof(ebr),
ebr_offset);
if (ret) {
image_error(image, "failed to write EBR\n");
return ret;
}
return 0;
}
/* clang-format off */
static const struct gpt_partition_type_shortcut_t gpt_partition_type_shortcuts[] =
{
{ "L" , "0fc63daf-8483-4772-8e79-3d69d8477de4" },
{ "linux" , "0fc63daf-8483-4772-8e79-3d69d8477de4" },
{ "S" , "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" },
{ "swap" , "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f" },
{ "H" , "933ac7e1-2eb4-4f13-b844-0e14e2aef915" },
{ "home" , "933ac7e1-2eb4-4f13-b844-0e14e2aef915" },
{ "U" , "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" },
{ "uefi" , "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" },
{ "R" , "a19d880f-05fc-4d3b-a006-743f0f84911e" },
{ "raid" , "a19d880f-05fc-4d3b-a006-743f0f84911e" },
{ "V" , "e6d6d379-f507-44c2-a23c-238f2a3df928" },
{ "lvm" , "e6d6d379-f507-44c2-a23c-238f2a3df928" },
{ "F" , "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
{ "fat32" , "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" },
{ "barebox-state" , "4778ed65-bf42-45fa-9c5b-287a1dc4aab1" },
{ "barebox-env" , "6c3737f2-07f8-45d1-ad45-15d260aab24d" },
{ "u-boot-env" , "3de21764-95bd-54bd-a5c3-4abe786f38a8" },
/* Discoverable Partitions Specification GUID, see
* https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
*/
{ "root-alpha" , "6523f8ae-3eb1-4e2a-a05a-18b695ae656f" },
{ "root-arc" , "d27f46ed-2919-4cb8-bd25-9531f3c16534" },
{ "root-arm" , "69dad710-2ce4-4e3c-b16c-21a1d49abed3" },
{ "root-arm64" , "b921b045-1df0-41c3-af44-4c6f280d3fae" },
{ "root-ia64" , "993d8d3d-f80e-4225-855a-9daf8ed7ea97" },
{ "root-loongarch64" , "77055800-792c-4f94-b39a-98c91b762bb6" },
{ "root-mips" , "e9434544-6e2c-47cc-bae2-12d6deafb44c" },
{ "root-mips64" , "d113af76-80ef-41b4-bdb6-0cff4d3d4a25" },
{ "root-mips-le" , "37c58c8a-d913-4156-a25f-48b1b64e07f0" },
{ "root-mips64-le" , "700bda43-7a34-4507-b179-eeb93d7a7ca3" },
{ "root-parisc" , "1aacdb3b-5444-4138-bd9e-e5c2239b2346" },
{ "root-ppc" , "1de3f1ef-fa98-47b5-8dcd-4a860a654d78" },
{ "root-ppc64" , "912ade1d-a839-4913-8964-a10eee08fbd2" },
{ "root-ppc64-le" , "c31c45e6-3f39-412e-80fb-4809c4980599" },
{ "root-riscv32" , "60d5a7fe-8e7d-435c-b714-3dd8162144e1" },
{ "root-riscv64" , "72ec70a6-cf74-40e6-bd49-4bda08e8f224" },
{ "root-s390" , "08a7acea-624c-4a20-91e8-6e0fa67d23f9" },
{ "root-s390x" , "5eead9a9-fe09-4a1e-a1d7-520d00531306" },
{ "root-tilegx" , "c50cdd70-3862-4cc3-90e1-809a8c93ee2c" },
{ "root-x86" , "44479540-f297-41b2-9af7-d131d5f0458a" },
{ "root-x86-64" , "4f68bce3-e8cd-4db1-96e7-fbcaf984b709" },
{ "usr-alpha" , "e18cf08c-33ec-4c0d-8246-c6c6fb3da024" },
{ "usr-arc" , "7978a683-6316-4922-bbee-38bff5a2fecc" },
{ "usr-arm" , "7d0359a3-02b3-4f0a-865c-654403e70625" },
{ "usr-arm64" , "b0e01050-ee5f-4390-949a-9101b17104e9" },
{ "usr-ia64" , "4301d2a6-4e3b-4b2a-bb94-9e0b2c4225ea" },
{ "usr-loongarch64" , "e611c702-575c-4cbe-9a46-434fa0bf7e3f" },
{ "usr-mips" , "773b2abc-2a99-4398-8bf5-03baac40d02b" },
{ "usr-mips64" , "57e13958-7331-4365-8e6e-35eeee17c61b" },
{ "usr-mips-le" , "0f4868e9-9952-4706-979f-3ed3a473e947" },
{ "usr-mips64-le" , "c97c1f32-ba06-40b4-9f22-236061b08aa8" },
{ "usr-parisc" , "dc4a4480-6917-4262-a4ec-db9384949f25" },
{ "usr-ppc" , "7d14fec5-cc71-415d-9d6c-06bf0b3c3eaf" },
{ "usr-ppc64" , "2c9739e2-f068-46b3-9fd0-01c5a9afbcca" },
{ "usr-ppc64-le" , "15bb03af-77e7-4d4a-b12b-c0d084f7491c" },
{ "usr-riscv32" , "b933fb22-5c3f-4f91-af90-e2bb0fa50702" },
{ "usr-riscv64" , "beaec34b-8442-439b-a40b-984381ed097d" },
{ "usr-s390" , "cd0f869b-d0fb-4ca0-b141-9ea87cc78d66" },
{ "usr-s390x" , "8a4f5770-50aa-4ed3-874a-99b710db6fea" },
{ "usr-tilegx" , "55497029-c7c1-44cc-aa39-815ed1558630" },
{ "usr-x86" , "75250d76-8cc6-458e-bd66-bd47cc81a812" },
{ "usr-x86-64" , "8484680c-9521-48c6-9c11-b0720656f69e" },
{ "root-alpha-verity" , "fc56d9e9-e6e5-4c06-be32-e74407ce09a5" },
{ "root-arc-verity" , "24b2d975-0f97-4521-afa1-cd531e421b8d" },
{ "root-arm-verity" , "7386cdf2-203c-47a9-a498-f2ecce45a2d6" },
{ "root-arm64-verity" , "df3300ce-d69f-4c92-978c-9bfb0f38d820" },
{ "root-ia64-verity" , "86ed10d5-b607-45bb-8957-d350f23d0571" },
{ "root-loongarch64-verity" , "f3393b22-e9af-4613-a948-9d3bfbd0c535" },
{ "root-mips-verity" , "7a430799-f711-4c7e-8e5b-1d685bd48607" },
{ "root-mips64-verity" , "579536f8-6a33-4055-a95a-df2d5e2c42a8" },
{ "root-mips-le-verity" , "d7d150d2-2a04-4a33-8f12-16651205ff7b" },
{ "root-mips64-le-verity" , "16b417f8-3e06-4f57-8dd2-9b5232f41aa6" },
{ "root-parisc-verity" , "d212a430-fbc5-49f9-a983-a7feef2b8d0e" },
{ "root-ppc64-le-verity" , "906bd944-4589-4aae-a4e4-dd983917446a" },
{ "root-ppc64-verity" , "9225a9a3-3c19-4d89-b4f6-eeff88f17631" },
{ "root-ppc-verity" , "98cfe649-1588-46dc-b2f0-add147424925" },
{ "root-riscv32-verity" , "ae0253be-1167-4007-ac68-43926c14c5de" },
{ "root-riscv64-verity" , "b6ed5582-440b-4209-b8da-5ff7c419ea3d" },
{ "root-s390-verity" , "7ac63b47-b25c-463b-8df8-b4a94e6c90e1" },
{ "root-s390x-verity" , "b325bfbe-c7be-4ab8-8357-139e652d2f6b" },
{ "root-tilegx-verity" , "966061ec-28e4-4b2e-b4a5-1f0a825a1d84" },
{ "root-x86-64-verity" , "2c7357ed-ebd2-46d9-aec1-23d437ec2bf5" },
{ "root-x86-verity" , "d13c5d3b-b5d1-422a-b29f-9454fdc89d76" },
{ "usr-alpha-verity" , "8cce0d25-c0d0-4a44-bd87-46331bf1df67" },
{ "usr-arc-verity" , "fca0598c-d880-4591-8c16-4eda05c7347c" },
{ "usr-arm-verity" , "c215d751-7bcd-4649-be90-6627490a4c05" },
{ "usr-arm64-verity" , "6e11a4e7-fbca-4ded-b9e9-e1a512bb664e" },
{ "usr-ia64-verity" , "6a491e03-3be7-4545-8e38-83320e0ea880" },
{ "usr-loongarch64-verity" , "f46b2c26-59ae-48f0-9106-c50ed47f673d" },
{ "usr-mips-verity" , "6e5a1bc8-d223-49b7-bca8-37a5fcceb996" },
{ "usr-mips64-verity" , "81cf9d90-7458-4df4-8dcf-c8a3a404f09b" },
{ "usr-mips-le-verity" , "46b98d8d-b55c-4e8f-aab3-37fca7f80752" },
{ "usr-mips64-le-verity" , "3c3d61fe-b5f3-414d-bb71-8739a694a4ef" },
{ "usr-parisc-verity" , "5843d618-ec37-48d7-9f12-cea8e08768b2" },
{ "usr-ppc64-le-verity" , "ee2b9983-21e8-4153-86d9-b6901a54d1ce" },
{ "usr-ppc64-verity" , "bdb528a5-a259-475f-a87d-da53fa736a07" },
{ "usr-ppc-verity" , "df765d00-270e-49e5-bc75-f47bb2118b09" },
{ "usr-riscv32-verity" , "cb1ee4e3-8cd0-4136-a0a4-aa61a32e8730" },
{ "usr-riscv64-verity" , "8f1056be-9b05-47c4-81d6-be53128e5b54" },
{ "usr-s390-verity" , "b663c618-e7bc-4d6d-90aa-11b756bb1797" },
{ "usr-s390x-verity" , "31741cc4-1a2a-4111-a581-e00b447d2d06" },
{ "usr-tilegx-verity" , "2fb4bf56-07fa-42da-8132-6b139f2026ae" },
{ "usr-x86-64-verity" , "77ff5f63-e7b6-4633-acf4-1565b864c0e6" },
{ "usr-x86-verity" , "8f461b0d-14ee-4e81-9aa9-049b6fb97abd" },
{ "root-alpha-verity-sig" , "d46495b7-a053-414f-80f7-700c99921ef8" },
{ "root-arc-verity-sig" , "143a70ba-cbd3-4f06-919f-6c05683a78bc" },
{ "root-arm-verity-sig" , "42b0455f-eb11-491d-98d3-56145ba9d037" },
{ "root-arm64-verity-sig" , "6db69de6-29f4-4758-a7a5-962190f00ce3" },
{ "root-ia64-verity-sig" , "e98b36ee-32ba-4882-9b12-0ce14655f46a" },
{ "root-loongarch64-verity-sig" , "5afb67eb-ecc8-4f85-ae8e-ac1e7c50e7d0" },
{ "root-mips-verity-sig" , "bba210a2-9c5d-45ee-9e87-ff2ccbd002d0" },
{ "root-mips64-verity-sig" , "43ce94d4-0f3d-4999-8250-b9deafd98e6e" },
{ "root-mips-le-verity-sig" , "c919cc1f-4456-4eff-918c-f75e94525ca5" },
{ "root-mips64-le-verity-sig" , "904e58ef-5c65-4a31-9c57-6af5fc7c5de7" },
{ "root-parisc-verity-sig" , "15de6170-65d3-431c-916e-b0dcd8393f25" },
{ "root-ppc64-le-verity-sig" , "d4a236e7-e873-4c07-bf1d-bf6cf7f1c3c6" },
{ "root-ppc64-verity-sig" , "f5e2c20c-45b2-4ffa-bce9-2a60737e1aaf" },
{ "root-ppc-verity-sig" , "1b31b5aa-add9-463a-b2ed-bd467fc857e7" },
{ "root-riscv32-verity-sig" , "3a112a75-8729-4380-b4cf-764d79934448" },
{ "root-riscv64-verity-sig" , "efe0f087-ea8d-4469-821a-4c2a96a8386a" },
{ "root-s390-verity-sig" , "3482388e-4254-435a-a241-766a065f9960" },
{ "root-s390x-verity-sig" , "c80187a5-73a3-491a-901a-017c3fa953e9" },
{ "root-tilegx-verity-sig" , "b3671439-97b0-4a53-90f7-2d5a8f3ad47b" },
{ "root-x86-64-verity-sig" , "41092b05-9fc8-4523-994f-2def0408b176" },
{ "root-x86-verity-sig" , "5996fc05-109c-48de-808b-23fa0830b676" },
{ "usr-alpha-verity-sig" , "5c6e1c76-076a-457a-a0fe-f3b4cd21ce6e" },
{ "usr-arc-verity-sig" , "94f9a9a1-9971-427a-a400-50cb297f0f35" },
{ "usr-arm-verity-sig" , "d7ff812f-37d1-4902-a810-d76ba57b975a" },
{ "usr-arm64-verity-sig" , "c23ce4ff-44bd-4b00-b2d4-b41b3419e02a" },
{ "usr-ia64-verity-sig" , "8de58bc2-2a43-460d-b14e-a76e4a17b47f" },
{ "usr-loongarch64-verity-sig" , "b024f315-d330-444c-8461-44bbde524e99" },
{ "usr-mips-verity-sig" , "97ae158d-f216-497b-8057-f7f905770f54" },
{ "usr-mips64-verity-sig" , "05816ce2-dd40-4ac6-a61d-37d32dc1ba7d" },
{ "usr-mips-le-verity-sig" , "3e23ca0b-a4bc-4b4e-8087-5ab6a26aa8a9" },
{ "usr-mips64-le-verity-sig" , "f2c2c7ee-adcc-4351-b5c6-ee9816b66e16" },
{ "usr-parisc-verity-sig" , "450dd7d1-3224-45ec-9cf2-a43a346d71ee" },
{ "usr-ppc64-le-verity-sig" , "c8bfbd1e-268e-4521-8bba-bf314c399557" },
{ "usr-ppc64-verity-sig" , "0b888863-d7f8-4d9e-9766-239fce4d58af" },
{ "usr-ppc-verity-sig" , "7007891d-d371-4a80-86a4-5cb875b9302e" },
{ "usr-riscv32-verity-sig" , "c3836a13-3137-45ba-b583-b16c50fe5eb4" },
{ "usr-riscv64-verity-sig" , "d2f9000a-7a18-453f-b5cd-4d32f77a7b32" },
{ "usr-s390-verity-sig" , "17440e4f-a8d0-467f-a46e-3912ae6ef2c5" },
{ "usr-s390x-verity-sig" , "3f324816-667b-46ae-86ee-9b0c0c6c11b4" },
{ "usr-tilegx-verity-sig" , "4ede75e2-6ccc-4cc8-b9c7-70334b087510" },
{ "usr-x86-64-verity-sig" , "e7bb33fb-06cf-4e81-8273-e543b413e2e2" },
{ "usr-x86-verity-sig" , "974a71c0-de41-43c3-be5d-5c5ccd1ad2c0" },
{ "esp" , "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" },
{ "xbootldr" , "bc13c2ff-59e6-4262-a352-b275fd6f7172" },
{ "srv" , "3b8f8425-20e0-4f3b-907f-1a25a76f98e8" },
{ "var" , "4d21b016-b534-45c2-a9fb-5c16e091fd2d" },
{ "tmp" , "7ec6f557-3bc5-4aca-b293-16ef5df639d1" },
{ "user-home" , "773f91ef-66d4-49b5-bd83-d683bf40ad16" },
{ "linux-generic" , "0fc63daf-8483-4772-8e79-3d69d8477de4" },
{ 0, 0 } /* sentinel */
};
/* clang-format on */
static const char *
gpt_partition_type_lookup(const char *shortcut)
{
const struct gpt_partition_type_shortcut_t *s, *config_shortcuts;
config_shortcuts = get_gpt_shortcuts();
for (s = config_shortcuts; s && s->shortcut; s++) {
if (strcasecmp(s->shortcut, shortcut) == 0) {
return s->guid;
}
}
for (s = gpt_partition_type_shortcuts; s->shortcut; s++) {
if (strcasecmp(s->shortcut, shortcut) == 0) {
return s->guid;
}
}
return NULL;
}
static int hdimage_insert_protective_mbr(struct image *image)
{
struct partition mbr;
struct list_head mbr_list = LIST_HEAD_INIT(mbr_list);
int ret = 0;
image_info(image, "writing protective MBR\n");
memset(&mbr, 0, sizeof(struct partition));
mbr.offset = 512;
mbr.size = image->size - 512;
mbr.in_partition_table = 1;
mbr.partition_type = 0xee;
list_add_tail(&mbr.list, &mbr_list);
ret = hdimage_insert_mbr(image, &mbr_list);
if (ret) {
image_error(image, "failed to write protective MBR\n");
return ret;
}
return 0;
}
static int hdimage_insert_gpt(struct image *image, struct list_head *partitions)
{
struct hdimage *hd = image->handler_priv;
const char *outfile = imageoutfile(image);
struct gpt_header header;
struct gpt_partition_entry table[GPT_ENTRIES];
unsigned long long smallest_offset = ~0ULL, first_usable_offset = 0;
struct partition *part;
unsigned i, j;
int ret;
image_info(image, "writing GPT\n");
memset(&header, 0, sizeof(struct gpt_header));
memcpy(header.signature, "EFI PART", 8);
header.revision = htole32(GPT_REVISION_1_0);
header.header_size = htole32(sizeof(struct gpt_header));
header.current_lba = htole64(1);
header.backup_lba = htole64(hd->gpt_no_backup ? 1 : image->size / 512 - 1);
header.first_usable_lba = htole64(~0ULL);
header.last_usable_lba = htole64(image->size / 512 - 1 - GPT_SECTORS);
uuid_parse(hd->disk_uuid, header.disk_uuid);
header.starting_lba = htole64(hd->gpt_location / 512);
header.number_entries = htole32(GPT_ENTRIES);
header.entry_size = htole32(sizeof(struct gpt_partition_entry));
i = 0;
memset(&table, 0, sizeof(table));
list_for_each_entry(part, partitions, list) {
if (!part->in_partition_table)
continue;
if (part->offset < smallest_offset)
smallest_offset = part->offset;
uuid_parse(part->partition_type_uuid, table[i].type_uuid);
uuid_parse(part->partition_uuid, table[i].uuid);
table[i].first_lba = htole64(part->offset / 512);
table[i].last_lba = htole64((partition_end(part)) / 512 - 1);
table[i].flags =
(part->bootable ? GPT_PE_FLAG_BOOTABLE : 0) |
(part->read_only ? GPT_PE_FLAG_READ_ONLY : 0) |
(part->hidden ? GPT_PE_FLAG_HIDDEN : 0) |
(part->no_automount ? GPT_PE_FLAG_NO_AUTO : 0);
for (j = 0; j < strlen(part->name) && j < 36; j++)
table[i].name[j] = htole16(part->name[j]);
i++;
}
/*
* Find the last non-partition data before the first partition.
* This can be a bootloader or the GPT partition table.
*/
list_for_each_entry(part, partitions, list) {
unsigned long long end;
if (part->in_partition_table)
continue;
/* ignore the backup partition table at the end of the disk */
if (strstr(part->name, "GPT backup"))
continue;
end = partition_end(part);
if (end <= smallest_offset && end > first_usable_offset)
first_usable_offset = end;
}
header.first_usable_lba = htole64(roundup(first_usable_offset, 512) / 512);
header.table_crc = htole32(crc32(table, sizeof(table)));
header.header_crc = htole32(crc32(&header, sizeof(header)));
ret = insert_data(image, &header, outfile, sizeof(header), 512);
if (ret) {
image_error(image, "failed to write GPT\n");
return ret;
}
ret = insert_data(image, &table, outfile, sizeof(table), hd->gpt_location);
if (ret) {
image_error(image, "failed to write GPT table\n");
return ret;
}
if (!hd->gpt_no_backup) {
ret = extend_file(image, image->size);
if (ret) {
image_error(image, "failed to pad image to size %lld\n",
image->size);
return ret;
}
header.header_crc = 0;
header.current_lba = htole64(image->size / 512 - 1);
header.backup_lba = htole64(1);
header.starting_lba = htole64(image->size / 512 - GPT_SECTORS);
header.header_crc = htole32(crc32(&header, sizeof(header)));
ret = insert_data(image, &table, outfile, sizeof(table),
image->size - GPT_SECTORS * 512);
if (ret) {
image_error(image, "failed to write backup GPT table\n");
return ret;
}
ret = insert_data(image, &header, outfile, sizeof(header),
image->size - 512);
if (ret) {
image_error(image, "failed to write backup GPT\n");
return ret;
}
}
if (hd->table_type == TYPE_HYBRID) {
ret = hdimage_insert_mbr(image, partitions);
} else {
ret = hdimage_insert_protective_mbr(image);
}
if (ret) {
return ret;
}
return 0;
}
static int hdimage_generate(struct image *image)
{
struct partition *part;
struct hdimage *hd = image->handler_priv;
struct stat s;
int ret;
ret = prepare_image(image, hd->file_size);
if (ret < 0)
return ret;
list_for_each_entry(part, &image->partitions, list) {
struct image *child;
unsigned long long data_size;
image_info(image, "adding %s partition '%s'%s%s%s%s ...\n",
part->logical ? "logical" : "primary",
part->name,
part->in_partition_table ? " (in MBR)" : "",
part->image ? " from '" : "",
part->image ? part->image : "",
part->image ? "'" : "");
if (part->logical) {
ret = hdimage_insert_ebr(image, part);
if (ret) {
image_error(image, "failed to write EBR\n");
return ret;
}
}
if (!part->image)
continue;
child = image_get(part->image);
if (child->size == 0 && !part->fill)
continue;
if (part->imageoffset > child->size) {
image_error(image, "size %lld of %s is too small for imageoffset %lld\n",
child->size, child->name, part->imageoffset);
return -E2BIG;
}
data_size = child->size - part->imageoffset;
if (data_size > part->size) {
image_error(image, "part %s size (%lld) too small for %s (%lld)\n",
part->name, part->size, child->file, data_size);
return -E2BIG;
}
ret = insert_image(image, child, part->fill ? part->size : data_size,
part->offset, part->imageoffset, 0, part->sparse);
if (ret) {
image_error(image, "failed to write image partition '%s'\n",
part->name);
return ret;
}
}
if (hd->table_type != TYPE_NONE) {
if (hd->table_type & TYPE_GPT) {
ret = hdimage_insert_gpt(image, &image->partitions);
if (ret)
return ret;
} else {
ret = hdimage_insert_mbr(image, &image->partitions);
if (ret)
return ret;
}
}
if (hd->fill) {
ret = extend_file(image, image->size);
if (ret) {
image_error(image, "failed to fill the image.\n");
return ret;
}
}
if (!is_block_device(imageoutfile(image))) {
ret = stat(imageoutfile(image), &s);
if (ret) {
ret = -errno;
image_error(image, "stat(%s) failed: %s\n", imageoutfile(image),
strerror(errno));
return ret;
}
if (hd->file_size != (unsigned long long)s.st_size) {
image_error(image, "unexpected output file size: %llu != %llu\n",
hd->file_size, (unsigned long long)s.st_size);
return -EINVAL;
}
}
if (hd->table_type != TYPE_NONE)
return reload_partitions(image);
return 0;
}
static bool image_has_hole_covering(const char *image,
unsigned long long start, unsigned long long end)
{
struct image *child;
int i;
if (!image)
return false;
child = image_get(image);
for (i = 0; i < child->n_holes; ++i) {
const struct extent *e = &child->holes[i];
if (e->start <= start && end <= e->end)
return true;
}
return false;
}
static int check_overlap(struct image *image, struct partition *p)
{
unsigned long long start, end;
struct partition *q;
list_for_each_entry(q, &image->partitions, list) {
/* Stop iterating when we reach p. */
if (p == q)
return 0;
/* We must have that p starts beyond where q ends... */
if (p->offset >= partition_end(q))
continue;
/* ...or vice versa. */
if (q->offset >= partition_end(p))
continue;
/*
* Or maybe the image occupying the q partition has an
* area which it is ok to overwrite. We do not do the
* "vice versa" check, since images are written to the
* output file in the order the partitions are
* specified.
*/
start = max_ull(p->offset, q->offset);
end = min_ull(partition_end(p), q->offset + q->size);
if (image_has_hole_covering(q->image, start - q->offset, end - q->offset))
continue;
image_error(image,
"partition %s (offset 0x%llx, size 0x%llx) overlaps previous "
"partition %s (offset 0x%llx, size 0x%llx)\n",
p->name, p->offset, p->size,
q->name, q->offset, q->size);
if (!q->in_partition_table &&
(!strcmp(p->name, "[MBR]") || !strncmp(p->name, "[GPT", 4)))
image_error(image, "bootloaders, etc. that overlap with the "
"partition table must declare the overlapping "
"area as a hole.\n");
return -EINVAL;
}
/* This should not be reached. */
image_error(image, "linked list corruption???\n");
return -EIO;
}
static struct partition *
fake_partition(const char *name, unsigned long long offset, unsigned long long size)
{
struct partition *p = xzalloc(sizeof(*p));
p->name = name;
p->offset = offset;
p->size = size;
p->align = 1;
return p;
}
static void ensure_extended_partition_index(struct image *image)
{
struct hdimage *hd = image->handler_priv;
struct partition *part;
int count = 0;
if (hd->extended_partition_index)
return;
list_for_each_entry(part, &image->partitions, list) {
if (!part->in_partition_table)
continue;
if (++count > 4) {
hd->extended_partition_index = 4;
return;
}
}
}
static int setup_logical_partitions(struct image *image)
{
struct hdimage *hd = image->handler_priv;
struct partition *part;
bool in_extended = false, found_extended = false;
unsigned int count = 0, mbr_entries = 0;
if (hd->extended_partition_index > 4) {
image_error(image, "invalid extended partition index (%i). must be "
"less or equal to 4 (0 for automatic)\n",
hd->extended_partition_index);
return -EINVAL;
}
if (hd->table_type != TYPE_MBR)
return 0;
ensure_extended_partition_index(image);
if (!hd->extended_partition_index)
return 0;
list_for_each_entry(part, &image->partitions, list) {
if (!part->in_partition_table)
continue;
++count;
if (hd->extended_partition_index == count) {
size_t offset = part->offset ? part->offset - hd->align : 0;
struct partition *p = fake_partition("[Extended]", offset, 0);
p->in_partition_table = true;
p->partition_type = PARTITION_TYPE_EXTENDED;
p->align = hd->align;
hd->extended_partition = p;
/* insert before the first logical partition */
list_add_tail(&p->list, &part->list);
in_extended = found_extended = true;
++mbr_entries;
}
if (part->forced_primary)
in_extended = false;
if (in_extended && !part->forced_primary)
part->logical = true;
else
++mbr_entries;
if (part->forced_primary) {
if (!found_extended) {
image_error(image, "partition %s: forced-primary can only be used for "
"partitions following the extended partition\n",
part->name);
return -EINVAL;
}
} else if (!in_extended && found_extended) {
image_error(image,
"cannot create non-primary partition %s after forced-primary partition\n",
part->name);
return -EINVAL;
}
if (mbr_entries > 4) {
image_error(image, "too many primary partitions\n");
return -EINVAL;
}
}
return 0;
}
static int setup_uuid(struct image *image, cfg_t *cfg)
{
struct hdimage *hd = image->handler_priv;
const char *disk_signature = cfg_getstr(cfg, "disk-signature");
hd->disk_uuid = cfg_getstr(cfg, "disk-uuid");
if (hd->disk_uuid) {
if (!(hd->table_type & TYPE_GPT)) {
image_error(image, "'disk-uuid' is only valid for gpt and hybrid partition-table-type\n");
return -EINVAL;
}
if (uuid_validate(hd->disk_uuid) == -1) {
image_error(image, "invalid disk UUID: %s\n", hd->disk_uuid);
return -EINVAL;
}
} else {
hd->disk_uuid = uuid_random();
}
if (!disk_signature)
hd->disksig = 0;
else if (!strcmp(disk_signature, "random"))
hd->disksig = random();
else {
if (!(hd->table_type & TYPE_MBR)) {
image_error(image, "'disk-signature' is only valid for mbr and hybrid partition-table-type\n");
return -EINVAL;
}
hd->disksig = strtoul(disk_signature, NULL, 0);
}
return 0;
}
static int setup_part_autoresize(struct image *image, struct partition *part, bool *resized)
{
struct hdimage *hd = image->handler_priv;
long long partsize;
if (!part->autoresize)
return 0;
if (*resized) {
image_error(image, "'autoresize' is only supported "
"for one partition\n");
return -EINVAL;
}
if (image->size == 0) {
image_error(image, "the image size must be specified "
"when using an 'autoresize' partition\n");
return -EINVAL;
}
partsize = image->size - part->offset;
if (hd->table_type & TYPE_GPT)
partsize -= GPT_SECTORS * 512;
partsize = rounddown(partsize, part->align);
if (partsize <= 0) {
image_error(image, "partitions exceed device size\n");
return -EINVAL;
}
if (partsize < (long long)part->size) {
image_error(image, "auto-resize partition %s ends up with a size %lld"
" smaller than minimum %lld\n",
part->name, partsize, part->size);
return -EINVAL;
}
part->size = partsize;
*resized = true;
return 0;
}
static int setup_part_image(struct image *image, struct partition *part)
{
struct hdimage *hd = image->handler_priv;
struct image *child;
unsigned long long data_size = 0;
if (!part->image)
return 0;
child = image_get(part->image);
if (!child) {
image_error(image, "could not find %s\n",
part->image);
return -EINVAL;
}
if (child->size) {
if (part->imageoffset > child->size) {
image_error(image, "size %lld of %s is too small for imageoffset %lld\n",
child->size, child->name, part->imageoffset);
return -E2BIG;
}
data_size = child->size - part->imageoffset;
}
if (!part->size) {
if (part->in_partition_table)
part->size = roundup(data_size, part->align);
else
part->size = data_size;
}
if (data_size > part->size) {
image_error(image, "part %s size (%lld) too small for %s (%lld)\n",
part->name, part->size, child->file, data_size);
return -EINVAL;
}
if (part->offset + data_size > hd->file_size)
hd->file_size = part->offset + data_size;
return 0;
}
static int hdimage_setup(struct image *image, cfg_t *cfg)
{
struct partition *part;
unsigned int hybrid_entries = 0;
unsigned long long now = 0;
const char *table_type;
struct hdimage *hd = xzalloc(sizeof(*hd));
struct partition *gpt_backup = NULL;
bool partition_resized = false;
int ret;
image->handler_priv = hd;
hd->align = cfg_getint_suffix(cfg, "align");
hd->extended_partition_index = cfg_getint(cfg, "extended-partition");
table_type = cfg_getstr(cfg, "partition-table-type");
hd->gpt_location = cfg_getint_suffix(cfg, "gpt-location");
hd->gpt_no_backup = cfg_getbool(cfg, "gpt-no-backup");
hd->fill = cfg_getbool(cfg, "fill");
if (is_block_device(imageoutfile(image))) {
if (image->size) {
image_error(image, "image size must not be specified for a block device target\n");
return -EINVAL;
}
ret = block_device_size(image, imageoutfile(image), &image->size);
if (ret)
return ret;
image_info(image, "determined size of block device %s to be %llu\n",
imageoutfile(image), image->size);
}
if (!strcmp(table_type, "none"))
hd->table_type = TYPE_NONE;
else if (!strcmp(table_type, "mbr") || !strcmp(table_type, "dos"))
hd->table_type = TYPE_MBR;
else if (!strcmp(table_type, "gpt"))
hd->table_type = TYPE_GPT;
else if (!strcmp(table_type, "hybrid"))
hd->table_type = TYPE_HYBRID;
else {
image_error(image, "'%s' is not a valid partition-table-type\n",
table_type);
return -EINVAL;
}
if (cfg_size(cfg, "partition-table") > 0) {
hd->table_type = cfg_getbool(cfg, "partition-table") ? TYPE_MBR : TYPE_NONE;
image_info(image, "The option 'partition-table' is deprecated. Use 'partition-table-type' instead\n");
}
if (cfg_size(cfg, "gpt") > 0) {
hd->table_type = cfg_getbool(cfg, "gpt") ? TYPE_GPT : TYPE_MBR;
image_info(image, "The option 'gpt' is deprecated. Use 'partition-table-type' instead\n");
}
if (!hd->align)
hd->align = hd->table_type == TYPE_NONE ? 1 : 512;
if ((hd->table_type != TYPE_NONE) && ((hd->align % 512) || (hd->align == 0))) {
image_error(image, "partition alignment (%lld) must be a "
"multiple of 1 sector (512 bytes)\n",
hd->align);
return -EINVAL;
}
ret = setup_logical_partitions(image);
if (ret < 0)
return ret;
ret = setup_uuid(image, cfg);
if (ret < 0)
return ret;
if (hd->gpt_location == 0) {
hd->gpt_location = 2 * 512;
} else if (hd->gpt_location % 512) {
image_error(image, "GPT table location (%lld) must be a "
"multiple of 1 sector (512 bytes)\n",
hd->gpt_location);
}
if (hd->table_type != TYPE_NONE) {
struct partition *mbr = fake_partition("[MBR]", 512 - sizeof(struct mbr_tail),
sizeof(struct mbr_tail));
list_add_tail(&mbr->list, &image->partitions);
now = partition_end(mbr);
if (hd->table_type & TYPE_GPT) {
struct partition *gpt_header, *gpt_array;
unsigned long long backup_offset, backup_size;
gpt_header = fake_partition("[GPT header]", 512, 512);
gpt_array = fake_partition("[GPT array]", hd->gpt_location, (GPT_SECTORS - 1) * 512);
list_add_tail(&gpt_header->list, &image->partitions);
list_add_tail(&gpt_array->list, &image->partitions);
now = partition_end(gpt_array);
/* Includes both the backup header and array. */
backup_size = GPT_SECTORS * 512;
backup_offset = image->size ? image->size - backup_size : 0;
gpt_backup = fake_partition("[GPT backup]", backup_offset, backup_size);
list_add_tail(&gpt_backup->list, &image->partitions);
}
}
list_for_each_entry(part, &image->partitions, list) {
if (hd->table_type == TYPE_NONE)
part->in_partition_table = false;
if (!part->align)
part->align = (part->in_partition_table || hd->table_type == TYPE_NONE) ? hd->align : 1;
if (part->in_partition_table && part->align % hd->align) {
image_error(image, "partition alignment (%lld) of partition %s "
"must be multiple of image alignment (%lld)",
part->align, part->name, hd->align);
}
if (part->partition_type_uuid && !(hd->table_type & TYPE_GPT)) {
image_error(image, "part %s: 'partition-type-uuid' is only valid for gpt and hybrid partition-table-type\n",
part->name);
return -EINVAL;
}
if (part->partition_uuid && !(hd->table_type & TYPE_GPT)) {
image_error(image, "part %s: 'partition-uuid' is only valid for gpt and hybrid partition-table-type\n",
part->name);
return -EINVAL;
}
if (part->partition_type && !(hd->table_type & TYPE_MBR)) {
image_error(image, "part %s: 'partition-type' is only valid for mbr and hybrid partition-table-type\n",
part->name);
return -EINVAL;
}
if ((hd->table_type & TYPE_GPT) && part->in_partition_table) {
if (!part->partition_type_uuid)
part->partition_type_uuid = "L";
if (strlen(part->partition_type_uuid) > 0 &&
uuid_validate(part->partition_type_uuid) != 0) {
const char *uuid;
uuid = gpt_partition_type_lookup(part->partition_type_uuid);
if (!uuid) {
image_error(image,
"part %s has invalid type shortcut: %s\n",
part->name, part->partition_type_uuid);
return -EINVAL;
}
part->partition_type_uuid = uuid;
}
if (uuid_validate(part->partition_type_uuid) == -1) {
image_error(image,
"part %s has invalid partition type UUID: %s\n",
part->name, part->partition_type_uuid);
return -EINVAL;
}
if (part->partition_uuid) {
if (uuid_validate(part->partition_uuid) == -1) {
image_error(image,
"part %s has invalid partition UUID: %s\n",
part->name, part->partition_uuid);
return -EINVAL;
}
} else {
part->partition_uuid = uuid_random();
}
if (part->partition_type)
++hybrid_entries;
}
if (part->logical) {
/* reserve space for extended boot record */
now += hd->align;
now = roundup(now, part->align);
}
if (part == gpt_backup && !part->offset) {
/*
* Make sure the backup, and hence the whole
* image, ends at a 4K boundary.
*/
now += part->size;
part->offset = roundup(now, 4096) - part->size;
}
if (!part->offset && (part->in_partition_table || hd->table_type == TYPE_NONE)) {
part->offset = roundup(now, part->align);
}
if (part->offset % part->align) {
image_error(image, "part %s offset (%lld) must be a "
"multiple of %lld bytes\n",
part->name, part->offset, part->align);
return -EINVAL;
}
ret = setup_part_autoresize(image, part, &partition_resized);
if (ret < 0)
return ret;
ret = setup_part_image(image, part);
if (ret < 0)
return ret;
/* the size of the extended partition will be filled in later */
if (!part->size && part != hd->extended_partition) {
image_error(image, "part %s size must not be zero\n",
part->name);
return -EINVAL;
}
if (!part->logical) {
ret = check_overlap(image, part);
if (ret)
return ret;
} else if (now > part->offset) {
image_error(image, "part %s overlaps with previous partition\n",
part->name);
return -EINVAL;
}
if (part->in_partition_table && (part->size % 512)) {
image_error(image, "part %s size (%lld) must be a "
"multiple of 1 sector (512 bytes)\n",
part->name, part->size);
return -EINVAL;
}
if (partition_end(part) > now)
now = partition_end(part);
if (part->logical) {
size_t file_size = part->offset - hd->align + 512;
if (file_size > hd->file_size)
hd->file_size = file_size;
}
if (part->logical) {
hd->extended_partition->size = now - hd->extended_partition->offset;
}
}
if (hybrid_entries > 3) {
image_error(image, "hybrid MBR partitions (%i) exceeds maximum of 3\n",
hybrid_entries);
return -EINVAL;
}
if (hd->table_type == TYPE_HYBRID && hybrid_entries == 0) {
image_error(image, "no partition with partition-type but hybrid partition-table-type selected\n");
return -EINVAL;
}
if (image->size > 0 && now > image->size) {
image_error(image, "partitions exceed device size\n");
return -EINVAL;
}
if (image->size == 0) {
image->size = now;
}
if (hd->fill || ((hd->table_type & TYPE_GPT) && !hd->gpt_no_backup))
hd->file_size = image->size;
return 0;
}
static cfg_opt_t hdimage_opts[] = {
CFG_STR("align", NULL, CFGF_NONE),
CFG_STR("disk-signature", NULL, CFGF_NONE),
CFG_STR("disk-uuid", NULL, CFGF_NONE),
CFG_BOOL("partition-table", cfg_false, CFGF_NODEFAULT),
CFG_INT("extended-partition", 0, CFGF_NONE),
CFG_STR("partition-table-type", "mbr", CFGF_NONE),
CFG_BOOL("gpt", cfg_false, CFGF_NODEFAULT),
CFG_STR("gpt-location", NULL, CFGF_NONE),
CFG_BOOL("gpt-no-backup", cfg_false, CFGF_NONE),
CFG_BOOL("fill", cfg_false, CFGF_NONE),
CFG_END()
};
struct image_handler hdimage_handler = {
.type = "hdimage",
.no_rootpath = cfg_true,
.generate = hdimage_generate,
.setup = hdimage_setup,
.opts = hdimage_opts,
};
genimage-19/image-iso.c 0000664 0000000 0000000 00000003642 15032005261 0015076 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 Michael Olbrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int iso_generate(struct image *image)
{
int ret;
char *boot;
char *boot_image = cfg_getstr(image->imagesec, "boot-image");
char *bootargs = cfg_getstr(image->imagesec, "bootargs");
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
char *input_charset = cfg_getstr(image->imagesec, "input-charset");
char *volume_id = cfg_getstr(image->imagesec, "volume-id");
if (boot_image)
xasprintf(&boot, "-b '%s' %s", boot_image, bootargs);
else
boot = "";
ret = systemp(image, "%s -input-charset %s -R -hide-rr-moved %s -V '%s' %s -o '%s' '%s'",
get_opt("genisoimage"),
input_charset,
boot,
volume_id,
extraargs,
imageoutfile(image),
mountpath(image));
return ret;
}
static cfg_opt_t iso_opts[] = {
CFG_STR("boot-image", NULL, CFGF_NONE),
CFG_STR("bootargs", "-no-emul-boot -boot-load-size 4 -boot-info-table -c boot.cat -hide boot.cat", CFGF_NONE),
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("input-charset", "default", CFGF_NONE),
CFG_STR("volume-id", "", CFGF_NONE),
CFG_END()
};
struct image_handler iso_handler = {
.type = "iso",
.generate = iso_generate,
.opts = iso_opts,
};
genimage-19/image-jffs2.c 0000664 0000000 0000000 00000003113 15032005261 0015307 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int jffs2_generate(struct image *image)
{
int ret;
char *extraargs;
extraargs = cfg_getstr(image->imagesec, "extraargs");
ret = systemp(image, "%s --eraseblock=%d %s%s%s -o '%s' %s",
get_opt("mkfsjffs2"),
image->flash_type->pebsize,
image->empty ? "" : "-d '",
image->empty ? "" : mountpath(image),
image->empty ? "" : "'",
imageoutfile(image), extraargs);
return ret;
}
static int jffs2_setup(struct image *image, cfg_t *cfg)
{
if (!image->flash_type) {
image_error(image, "no flash type given\n");
return -EINVAL;
}
return 0;
}
static cfg_opt_t jffs2_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_END()
};
struct image_handler jffs2_handler = {
.type = "jffs2",
.generate = jffs2_generate,
.setup = jffs2_setup,
.opts = jffs2_opts,
};
genimage-19/image-mdraid.c 0000664 0000000 0000000 00000040705 15032005261 0015545 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2025 Tomas Mudrunka
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
/*
* MDRAID Superblock generator
* This should create valid mdraid superblock for raid1 with 1 device (more devices can be added once mounted).
* Unlike mdadm this works completely in userspace and does not need kernel to create the ondisk structures.
* It is still very basic, but following seems to be working:
*
* mdadm --examine test.img
* losetup /dev/loop1 test.img
* mdadm --assemble md /dev/loop1
*
* Some docs:
* https://raid.wiki.kernel.org/index.php/RAID_superblock_formats#Sub-versions_of_the_version-1_superblock
* https://docs.huihoo.com/doxygen/linux/kernel/3.7/md__p_8h_source.html
*/
#include
#include
#include
#include
#include
#include
#include "genimage.h"
#define DATA_OFFSET_SECTORS (2048)
#define DATA_OFFSET_BYTES (DATA_OFFSET_SECTORS * 512)
#define BITMAP_SECTORS_MAX 256
/* (should be divisible by 8 sectors to keep 4kB alignment) */
#define MDRAID_ALIGN_BYTES 8 * 512
/*
* Array creation timestamp has to be identical across all the raid members,
* so we share it between invocations
*/
static time_t mdraid_time = 0;
/*
* bitmap structures:
* Taken from Linux kernel drivers/md/md-bitmap.h
* (Currently it's missing from linux-libc-dev debian package, so cannot be simply included)
*/
/* clang-format off */
#ifndef BITMAP_MAGIC
#define BITMAP_MAGIC 0x6d746962 // This is actualy just char string saying "bitm" :-)
/* use these for bitmap->flags and bitmap->sb->state bit-fields */
enum bitmap_state {
BITMAP_STALE = 1, /* the bitmap file is out of date or had -EIO */
BITMAP_WRITE_ERROR = 2, /* A write error has occurred */
BITMAP_HOSTENDIAN =15,
};
/* the superblock at the front of the bitmap file -- little endian */
typedef struct bitmap_super_s {
__le32 magic; /* 0 BITMAP_MAGIC */
__le32 version; /* 4 the bitmap major for now, could change... */
__u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */
__le64 events; /* 24 event counter for the bitmap (1)*/
__le64 events_cleared;/*32 event counter when last bit cleared (2) */
__le64 sync_size; /* 40 the size of the md device's sync range(3) */
__le32 state; /* 48 bitmap state information */
__le32 chunksize; /* 52 the bitmap chunk size in bytes */
__le32 daemon_sleep; /* 56 seconds between disk flushes */
__le32 write_behind; /* 60 number of outstanding write-behind writes */
__le32 sectors_reserved; /* 64 number of 512-byte sectors that are
* reserved for the bitmap. */
__le32 nodes; /* 68 the maximum number of nodes in cluster. */
__u8 cluster_name[64]; /* 72 cluster name to which this md belongs */
__u8 pad[256 - 136]; /* set to zero */
} bitmap_super_t;
/* clang-format on */
/*
* notes:
* (1) This event counter is updated before the eventcounter in the md superblock
* When a bitmap is loaded, it is only accepted if this event counter is equal
* to, or one greater than, the event counter in the superblock.
* (2) This event counter is updated when the other one is *if*and*only*if* the
* array is not degraded. As bits are not cleared when the array is degraded,
* this represents the last time that any bits were cleared.
* If a device is being added that has an event count with this value or
* higher, it is accepted as conforming to the bitmap.
* (3)This is the number of sectors represented by the bitmap, and is the range that
* resync happens across. For raid1 and raid5/6 it is the size of individual
* devices. For raid10 it is the size of the array.
*/
#endif //BITMAP_MAGIC
/* Superblock struct sanity check */
ct_assert(offsetof(struct mdp_superblock_1, data_offset) == 128);
ct_assert(offsetof(struct mdp_superblock_1, utime) == 192);
ct_assert(sizeof(struct mdp_superblock_1) == 256);
/* This structure is used to store mdraid state data in handler_priv */
typedef struct mdraid_img_s {
/* Partition of data to be imported to raid */
struct partition img_data_part;
/* Partition of parent raid image (we can inherit config from it) */
struct partition img_parent_part;
/* Images for aforementioned partitions */
struct image *img_data;
/* Dtto */
struct image *img_parent;
/* Actual mdraid superblock that is gonna be stored on disk */
struct mdp_superblock_1 *sb;
/* Actual bitmap superblock that is gonna be stored on disk */
bitmap_super_t bsb;
/* This is counter used by slave devices to take roles */
__le16 last_role;
} mdraid_img_t;
static unsigned int calc_sb_1_csum(struct mdp_superblock_1 *sb)
{
unsigned int disk_csum, csum;
unsigned long long newcsum;
int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev) * 2;
unsigned int *isuper = (unsigned int *)sb;
/* Temporarily set checksum in struct to 0 while remembering original value */
disk_csum = sb->sb_csum;
sb->sb_csum = 0;
newcsum = 0;
for (; size >= 4; size -= 4) {
newcsum += __le32_to_cpu(*isuper);
isuper++;
}
if (size == 2)
newcsum += __le16_to_cpu(*(unsigned short *)isuper);
csum = (newcsum & 0xffffffff) + (newcsum >> 32);
/* Set checksum in struct back to original value */
sb->sb_csum = disk_csum;
return __cpu_to_le32(csum);
}
static int mdraid_generate(struct image *image)
{
mdraid_img_t *md = image->handler_priv;
/* Inheriting from this parent if not NULL */
mdraid_img_t *mdp = NULL;
__le16 max_devices;
/* Determine max_devices while considering possibility of inheritance from other image */
if (md->img_parent) {
mdp = md->img_parent->handler_priv;
max_devices = mdp->sb->raid_disks;
} else {
max_devices = cfg_getint(image->imagesec, "devices");
}
/* Determine role of this device in array */
__le16 role = cfg_getint(image->imagesec, "role");
if (cfg_getint(image->imagesec, "role") == -1) {
/* If role is -1 it should be autoassigned to parenting devices */
if (mdp) {
/* Take role from master and increment its counter */
role = ++mdp->last_role;
} else {
/* Master has role of 0 */
role = 0;
}
image_info(image, "MDRAID automaticaly assigned role %d.\n", role);
}
if (role > MD_DISK_ROLE_MAX) {
image_error(image, "MDRAID role has to be >= 0 and <= %d.\n", MD_DISK_ROLE_MAX);
return 6;
}
if (role >= max_devices) {
image_error(image, "MDRAID role of this image has to be lower than total number of %d devices (roles are counted from 0).\n",
max_devices);
return 5;
}
/* MD Superblock and Bitmap Superblock */
size_t superblock_size = sizeof(struct mdp_superblock_1) + max_devices * 2;
struct mdp_superblock_1 *sb = md->sb = xzalloc(superblock_size);
bitmap_super_t *bsb = &md->bsb;
if (mdp) {
/* We are inheriting the superblock in this case */
memcpy(md->sb, mdp->sb, superblock_size);
//memcpy(&md->bsb, &mdp->bsb, sizeof(bitmap_super_t));
} else {
/* We are not inheriting superblock, therefore we need to fully initialize the array */
char *name = cfg_getstr(image->imagesec, "label");
/* constant array information - 128 bytes */
/* MD_SB_MAGIC: 0xa92b4efc - little endian. */
sb->magic = MD_SB_MAGIC;
/* Always 1 for 1.xx metadata version :-) */
sb->major_version = 1;
/* bit 0 set if 'bitmap_offset' is meaningful */
sb->feature_map = MD_FEATURE_BITMAP_OFFSET;
/* always set to 0 when writing */
sb->pad0 = 0;
char *raid_uuid = cfg_getstr(image->imagesec, "raid-uuid");
if (!raid_uuid)
raid_uuid = uuid_random();
/* user-space generated. U8[16] */
uuid_parse(raid_uuid, sb->set_uuid);
strncpy(sb->set_name, name, 32);
/* set and interpreted by user-space. CHAR[32] */
sb->set_name[31] = 0;
long int timestamp = cfg_getint(image->imagesec, "timestamp");
if (timestamp >= 0) {
sb->ctime = timestamp & 0xffffffffff;
} else {
/* lo 40 bits are seconds, top 24 are microseconds or 0 */
sb->ctime = mdraid_time & 0xffffffffff;
}
/* -4 (multipath), -1 (linear), 0,1,4,5 */
sb->level = 1;
/* only for raid5 and raid10 currently */
// sb->layout;
/* used size of component devices, in 512byte sectors */
sb->size = (image->size - DATA_OFFSET_BYTES) / 512;
/* in 512byte sectors - not used in raid 1 */
sb->chunksize = 0;
sb->raid_disks = max_devices;
}
/*
* sectors after start of superblock that bitmap starts
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
sb->bitmap_offset = 8;
/* constant this-device information - 64 bytes */
/* sector start of data, often 0 */
sb->data_offset = DATA_OFFSET_SECTORS;
/* sectors in this device that can be used for data */
sb->data_size = sb->size;
/* sector start of this superblock */
sb->super_offset = 8;
/* permanent identifier of this device - not role in raid (They can be equal tho). */
sb->dev_number = role;
/* number of read errors that were corrected by re-writing */
sb->cnt_corrected_read = 0;
char *disk_uuid = cfg_getstr(image->imagesec, "disk-uuid");
if (!disk_uuid)
disk_uuid = uuid_random();
/* user-space setable, ignored by kernel U8[16] */
uuid_parse(disk_uuid, sb->device_uuid);
/* per-device flags. Only two defined... */
sb->devflags = 0;
/* mask for writemostly flag in above */
//#define WriteMostly1 1
/* Should avoid retries and fixups and just fail */
//#define FailFast1 2
/*
* Bad block log. If there are any bad blocks the feature flag is set.
* If offset and size are non-zero, that space is reserved and available
*/
/* shift from sectors to badblock size, typicaly 9-12 (shift by 9 is equal to 512 sectors per badblock) */
sb->bblog_shift = 9;
/* number of sectors reserved for list */
sb->bblog_size = 8;
/* sector offset from superblock to bblog, signed - not unsigned */
sb->bblog_offset = sb->bitmap_offset + BITMAP_SECTORS_MAX + 8;
/* array state information - 64 bytes */
/* 40 bits second, 24 bits microseconds */
sb->utime = sb->ctime;
/* incremented when superblock updated */
sb->events = 0;
/* data before this offset (from data_offset) known to be in sync */
sb->resync_offset = 0;
/* size of devs[] array to consider */
sb->max_dev = max_devices;
/* set to 0 when writing */
// pad3[64-32];
/*
* device state information. Indexed by dev_number.
* 2 bytes per device
* Note there are no per-device state flags. State information is rolled
* into the 'roles' value. If a device is spare or faulty, then it doesn't
* have a meaningful role.
*/
/* role in array, or 0xffff for a spare, or 0xfffe for faulty */
__le16 *dev_roles = (__le16 *)((char *)sb + sizeof(struct mdp_superblock_1));
/* All devices in array are set as inactive initialy */
//memset(dev_roles, 0xFF, max_devices*2);
/* All devices are assigned roles equal to their dev_number initialy */
for (int i = 0; i < max_devices; i++) {
/* Assign active role to all devices */
dev_roles[i] = i;
}
/* Calculate superblock checksum */
sb->sb_csum = calc_sb_1_csum(sb);
/* Prepare bitmap superblock (bitmaps don't have checksums for performance reasons) */
/* 0 BITMAP_MAGIC - This is actualy just char string saying "bitm" :-) */
bsb->magic = BITMAP_MAGIC;
/* 4 the bitmap major for now, could change... */
bsb->version = 4; /* v4 is compatible with mdraid v1.2 */
/* 8 128 bit uuid - must match md device uuid */
memcpy(bsb->uuid, sb->set_uuid, sizeof(bsb->uuid));
/* 24 event counter for the bitmap (1) */
bsb->events = 0;
/* 32 event counter when last bit cleared (2) */
bsb->events_cleared = 0;
/* 40 the size of the md device's sync range(3) */
bsb->sync_size = sb->data_size;
/* 48 bitmap state information */
bsb->state = 0;
/* 52 the bitmap chunk size in bytes, 64MB is default on linux */
bsb->chunksize = 64 * 1024 * 1024;
/* 5 is considered safe default. 56 seconds between disk flushes */
bsb->daemon_sleep = 5;
/* 60 number of outstanding write-behind writes */
bsb->write_behind = 0;
/* 64 number of 512-byte sectors that are reserved for the bitmap. */
bsb->sectors_reserved = roundup(bsb->sync_size / bsb->chunksize, 8);
/* 68 the maximum number of nodes in cluster. */
bsb->nodes = 0;
/* 72 cluster name to which this md belongs */
//bsb->cluster_name[64];
/* set to zero */
// pad[256 - 136];
/* Increase bitmap chunk size till we fit in sectors max */
while (bsb->sectors_reserved > BITMAP_SECTORS_MAX) {
bsb->chunksize *= 2;
bsb->sectors_reserved = roundup(bsb->sync_size / bsb->chunksize, 8);
}
/* Construct image file */
int ret;
ret = prepare_image(image, image->size);
if (ret)
return ret;
/* Write superblock */
ret = insert_data(image, sb, imageoutfile(image), superblock_size, sb->super_offset * 512);
if (ret)
return ret;
/* Write bitmap */
if (sb->feature_map & MD_FEATURE_BITMAP_OFFSET) {
ret = insert_data(image, bsb, imageoutfile(image), sizeof(*bsb),
(sb->super_offset + sb->bitmap_offset) * 512);
if (ret)
return ret;
}
/* Write data */
if (md->img_data) {
ret = insert_image(image, md->img_data, md->img_data->size, DATA_OFFSET_BYTES, 0, 0, cfg_true);
if (ret)
return ret;
}
return 0;
}
static int mdraid_parse(struct image *image, cfg_t *cfg)
{
mdraid_img_t *md = xzalloc(sizeof(mdraid_img_t));
image->handler_priv = md;
/* Common MDRAID subsystem init */
if (!mdraid_time)
mdraid_time = time(NULL);
/* Sanity checks */
int raid_level = cfg_getint(image->imagesec, "level");
if (raid_level != 1) {
image_error(image, "MDRAID Currently only supporting raid level 1 (mirror)!\n");
return 1;
}
/* Inherit config from parent */
md->img_parent_part.image = cfg_getstr(image->imagesec, "parent");
if (md->img_parent_part.image) {
/* Add parent partition as dependency (so it's built first) */
list_add_tail(&md->img_parent_part.list, &image->partitions);
/* Find parent image */
md->img_parent = image_get(md->img_parent_part.image);
if (!md->img_parent) {
image_error(image, "MDRAID cannot find parent image to inherit metadata config from: %s\n",
md->img_parent_part.image);
return 9;
}
/* Inherit image size from parent */
image_info(image, "MDRAID will inherit array metadata config from parent: %s\n",
md->img_parent->file);
image->size = md->img_parent->size;
}
/* Find data partition to be put inside the array */
if (md->img_parent) {
md->img_data_part.image = cfg_getstr(md->img_parent->imagesec, "image");
} else {
md->img_data_part.image = cfg_getstr(image->imagesec, "image");
}
/* Add data partition as dependency (so it's built first) */
if (md->img_data_part.image) {
list_add_tail(&md->img_data_part.list, &image->partitions);
}
return 0;
}
static int mdraid_setup(struct image *image, cfg_t *cfg)
{
mdraid_img_t *md = image->handler_priv;
/* Find data image and its metadata if data partition exists */
if (md->img_data_part.image) {
image_info(image, "MDRAID using data from: %s\n", md->img_data_part.image);
md->img_data = image_get(md->img_data_part.image);
if (!md->img_data) {
image_error(image, "MDRAID cannot get image definition: %s\n", md->img_data_part.image);
return 8;
}
if (image->size == 0)
image->size = roundup(md->img_data->size + DATA_OFFSET_BYTES, MDRAID_ALIGN_BYTES);
if (image->size < (md->img_data->size + DATA_OFFSET_BYTES)) {
image_error(image, "MDRAID image too small to fit %s\n", md->img_data->file);
return 3;
}
} else {
image_info(image, "MDRAID is created without data.\n");
}
/* Make sure size is aligned */
if (image->size != roundup(image->size, MDRAID_ALIGN_BYTES)) {
image_error(image, "MDRAID image size has to be aligned to %d bytes!\n", MDRAID_ALIGN_BYTES);
return 4;
}
return 0;
}
static cfg_opt_t mdraid_opts[] = {
CFG_STR("label", "any:42", CFGF_NONE),
CFG_INT("level", 1, CFGF_NONE),
CFG_INT("devices", 1, CFGF_NONE),
CFG_INT("role", -1, CFGF_NONE),
CFG_INT("timestamp", -1, CFGF_NONE),
CFG_STR("raid-uuid", NULL, CFGF_NONE),
CFG_STR("disk-uuid", NULL, CFGF_NONE),
CFG_STR("image", NULL, CFGF_NONE),
CFG_STR("parent", NULL, CFGF_NONE),
CFG_END()
};
struct image_handler mdraid_handler = {
.type = "mdraid",
.no_rootpath = cfg_true,
.parse = mdraid_parse,
.setup = mdraid_setup,
.generate = mdraid_generate,
.opts = mdraid_opts,
};
genimage-19/image-qemu.c 0000664 0000000 0000000 00000004627 15032005261 0015257 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2018 Alexandre Fournier , Kiplink
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
struct qemu {
const char *format;
const char *extraargs;
};
static int qemu_generate(struct image *image)
{
struct partition *part;
struct qemu *qemu = image->handler_priv;
char *partitions = NULL;
int ret;
list_for_each_entry(part, &image->partitions, list) {
struct image *child;
const char *infile;
if (!part->image) {
image_debug(image, "skipping partition %s\n",
part->name);
continue;
}
image_info(image, "adding partition %s from %s ...\n",
part->name, part->image);
child = image_get(part->image);
infile = imageoutfile(child);
if (!partitions)
xasprintf(&partitions, "'%s'", infile);
else
xasprintf(&partitions, "%s '%s'", partitions, infile);
}
ret = systemp(image, "qemu-img convert %s -O %s %s '%s'",
qemu->extraargs,
qemu->format,
partitions,
imageoutfile(image));
return ret;
}
static int qemu_setup(struct image *image, cfg_t *cfg)
{
struct qemu *qemu = xzalloc(sizeof(*qemu));
struct partition *part;
int partitions_count = 0;
list_for_each_entry(part, &image->partitions, list) {
if (part->image)
partitions_count++;
}
if (partitions_count == 0) {
image_error(image, "no partition given\n");
return -EINVAL;
}
qemu->format = cfg_getstr(cfg, "format");
qemu->extraargs = cfg_getstr(cfg, "extraargs");
image->handler_priv = qemu;
return 0;
}
static cfg_opt_t qemu_opts[] = {
CFG_STR("format", "qcow2", CFGF_NONE),
CFG_STR("extraargs", "", CFGF_NONE),
CFG_END()
};
struct image_handler qemu_handler = {
.type = "qemu",
.no_rootpath = cfg_true,
.generate = qemu_generate,
.setup = qemu_setup,
.opts = qemu_opts,
};
genimage-19/image-rauc.c 0000664 0000000 0000000 00000016731 15032005261 0015241 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2016 Michael Olbrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include "genimage.h"
#define RAUC_CONTENT 0
#define RAUC_KEY 1
#define RAUC_CERT 2
#define RAUC_KEYRING 3
#define RAUC_INTERMEDIATE 4
static const char *pkcs11_prefix = "pkcs11:";
static int rauc_generate(struct image *image)
{
int ret;
struct partition *part;
const char *extraargs = cfg_getstr(image->imagesec, "extraargs");
const char *manifest = cfg_getstr(image->imagesec, "manifest");
const char *cert = cfg_getstr(image->imagesec, "cert");
const char *key = cfg_getstr(image->imagesec, "key");
const char *keyring = cfg_getstr(image->imagesec, "keyring");
char *keyringarg = NULL;
char *manifest_file = NULL;
char *tmpdir = NULL;
char *intermediatearg = NULL;
unsigned int i;
image_debug(image, "manifest = '%s'\n", manifest);
xasprintf(&tmpdir, "%s/rauc-%s", tmppath(), sanitize_path(image->file));
ret = systemp(image, "mkdir -p '%s'", tmpdir);
if (ret)
goto out;
xasprintf(&manifest_file, "%s/manifest.raucm", tmpdir);
ret = insert_data(image, manifest, manifest_file, strlen(manifest), 0);
if (ret)
goto out;
for (i = 0; i < cfg_size(image->imagesec, "intermediate"); i++) {
const char *uri;
uri = cfg_getnstr(image->imagesec, "intermediate", i);
if (!strncmp(pkcs11_prefix, uri, strlen(pkcs11_prefix)))
xstrcatf(&intermediatearg, " --intermediate='%s'", uri);
}
list_for_each_entry(part, &image->partitions, list) {
struct image *child = image_get(part->image);
const char *file = imageoutfile(child);
const char *target = part->name;
char *tmptarget;
char *path, *tmp;
if (part->partition_type == RAUC_CERT)
cert = file;
if (part->partition_type == RAUC_KEY)
key = file;
if (part->partition_type == RAUC_KEYRING)
keyring = file;
if (part->partition_type == RAUC_INTERMEDIATE)
xstrcatf(&intermediatearg, " --intermediate='%s'", file);
if (part->partition_type != RAUC_CONTENT)
continue;
if (!target) {
/* use basename from source as target name */
tmp = strrchr(child->file, '/');
if (tmp)
target = tmp + 1;
else
target = child->file;
}
/* create parent directories if target needs it */
path = strdupa(target);
tmp = strrchr(path, '/');
if (tmp) {
*tmp = '\0';
ret = systemp(image, "mkdir -p '%s/%s'",
tmpdir, path);
if (ret)
goto out;
}
xasprintf(&tmptarget, "%s/%s", tmpdir, target);
image_info(image, "adding file '%s' as '%s' (offset=%lld)...\n",
child->file, target, part->imageoffset);
if (part->imageoffset) {
unlink(tmptarget);
/*
* Starting with coreutils 9.1 you can use a 'B' suffix for
* skip=N instead of iflag=skip_bytes to have N count bytes, not
* (input) blocks.
*
* Note that dd doesn't behave as optimal as cp in the
* else branch below because it doesn't preserve holes.
* To improve here insert_image() should be extended to
* support part->imageoffset != 0 and then it can
* replace both commands.
*/
ret = systemp(image, "dd if='%s' of='%s' iflag=skip_bytes skip=%lld",
file, tmptarget, part->imageoffset);
} else {
ret = systemp(image, "cp --remove-destination '%s' '%s'",
file, tmptarget);
}
free(tmptarget);
if (ret)
goto out;
}
if (keyring)
xasprintf(&keyringarg, "--keyring='%s'", keyring);
systemp(image, "rm -f '%s'", imageoutfile(image));
ret = systemp(image, "%s bundle '%s' --cert='%s' --key='%s' %s %s %s '%s'",
get_opt("rauc"), tmpdir, cert, key,
(keyringarg ? keyringarg : ""),
(intermediatearg ? intermediatearg : ""),
extraargs, imageoutfile(image));
out:
free(keyringarg);
free(tmpdir);
free(manifest_file);
free(intermediatearg);
return ret;
}
static int rauc_parse(struct image *image, cfg_t *cfg)
{
unsigned int i;
unsigned int num_files;
struct partition *part;
char *part_image_key;
char *part_image_cert;
char *part_image_keyring;
part_image_key = cfg_getstr(image->imagesec, "key");
if (!part_image_key) {
image_error(image, "Mandatory 'key' option is missing!\n");
return -EINVAL;
}
if (strncmp(pkcs11_prefix, part_image_key, strlen(pkcs11_prefix))) {
part = xzalloc(sizeof *part);
part->image = part_image_key;
part->partition_type = RAUC_KEY;
list_add_tail(&part->list, &image->partitions);
}
part_image_cert = cfg_getstr(image->imagesec, "cert");
if (!part_image_cert) {
image_error(image, "Mandatory 'cert' option is missing!\n");
return -EINVAL;
}
if (strncmp(pkcs11_prefix, part_image_cert, strlen(pkcs11_prefix))) {
part = xzalloc(sizeof *part);
part->image = part_image_cert;
part->partition_type = RAUC_CERT;
list_add_tail(&part->list, &image->partitions);
}
part_image_keyring = cfg_getstr(image->imagesec, "keyring");
if (part_image_keyring) {
part = xzalloc(sizeof *part);
part->image = part_image_keyring;
part->partition_type = RAUC_KEYRING;
list_add_tail(&part->list, &image->partitions);
}
for (i = 0; i < cfg_size(cfg, "intermediate"); i++) {
char *part_image_intermediate;
part_image_intermediate = cfg_getnstr(cfg, "intermediate", i);
if (strncmp(pkcs11_prefix, part_image_intermediate,
strlen(pkcs11_prefix))) {
part = xzalloc(sizeof *part);
part->image = part_image_intermediate;
part->partition_type = RAUC_INTERMEDIATE;
list_add_tail(&part->list, &image->partitions);
}
}
num_files = cfg_size(cfg, "file");
for (i = 0; i < num_files; i++) {
cfg_t *filesec = cfg_getnsec(cfg, "file", i);
part = xzalloc(sizeof *part);
part->name = cfg_title(filesec);
part->image = cfg_getstr(filesec, "image");
part->imageoffset = cfg_getint_suffix(filesec, "offset");
part->partition_type = RAUC_CONTENT;
list_add_tail(&part->list, &image->partitions);
}
for (i = 0; i < cfg_size(cfg, "files"); i++) {
part = xzalloc(sizeof *part);
part->image = cfg_getnstr(cfg, "files", i);
part->partition_type = RAUC_CONTENT;
list_add_tail(&part->list, &image->partitions);
}
return 0;
}
static int rauc_setup(struct image *image, cfg_t *cfg)
{
char *manifest = cfg_getstr(image->imagesec, "manifest");
if (!manifest) {
image_error(image, "Mandatory 'manifest' option is missing!\n");
return -EINVAL;
}
return 0;
}
static cfg_opt_t file_opts[] = {
CFG_STR("image", NULL, CFGF_NONE),
CFG_STR("offset", "0", CFGF_NONE),
CFG_END()
};
static cfg_opt_t rauc_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR_LIST("files", NULL, CFGF_NONE),
CFG_SEC("file", file_opts, CFGF_MULTI | CFGF_TITLE),
CFG_STR("key", NULL, CFGF_NONE),
CFG_STR("cert", NULL, CFGF_NONE),
CFG_STR("keyring", NULL, CFGF_NONE),
CFG_STR_LIST("intermediate", 0, CFGF_NONE),
CFG_STR("manifest", NULL, CFGF_NONE),
CFG_END()
};
struct image_handler rauc_handler = {
.type = "rauc",
.no_rootpath = cfg_true,
.generate = rauc_generate,
.parse = rauc_parse,
.setup = rauc_setup,
.opts = rauc_opts,
};
genimage-19/image-squashfs.c 0000664 0000000 0000000 00000005645 15032005261 0016146 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2014 Juergen Beisert
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "genimage.h"
static int squash_generate(struct image *image)
{
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
char compression[128];
char *comp_setup = cfg_getstr(image->imagesec, "compression");
unsigned block_size = cfg_getint_suffix(image->imagesec, "block-size");
unsigned long long file_size;
struct stat sb;
int ret;
/*
* 'mksquashfs' currently defaults to 'gzip' compression. Provide a shortcut
* to be able to disable all kind of compression and force the current
* default behaviour for the future. Disabling compression is very useful
* to handle binary diffs.
*/
if (!strcasecmp(comp_setup, "none"))
strncpy(compression, "-comp gzip -noInodeCompression -noDataCompression -noFragmentCompression -noXattrCompression", sizeof(compression));
else
snprintf(compression, sizeof(compression), "-comp %s", comp_setup);
ret = systemp(image, "%s '%s' '%s' -b %u -noappend %s %s",
get_opt("mksquashfs"),
mountpath(image), /* source dir */
imageoutfile(image), /* destination file */
block_size, compression, extraargs);
if (ret)
return ret;
ret = stat(imageoutfile(image), &sb);
if (ret) {
ret = -errno;
image_error(image, "stat(%s) failed: %s\n", imageoutfile(image), strerror(errno));
return ret;
}
file_size = sb.st_size;
if (image->size && file_size > image->size) {
image_error(image, "generated image %s is larger than given image size (%llu v %llu)\n",
imageoutfile(image), file_size, image->size);
return -E2BIG;
}
image_debug(image, "setting image size to %llu bytes\n", file_size);
image->size = file_size;
return 0;
}
/**
* 'compression' can be 'gzip' (the current default), 'lzo', 'xz' or 'none'
* @note 'none' is a special keyword to add the parameters '-noInodeCompression -noDataCompression -noFragmentCompression -noXattrCompression'
*/
static cfg_opt_t squash_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("compression", "gzip", CFGF_NONE),
CFG_STR("block-size", "4096", CFGF_NONE),
CFG_END()
};
struct image_handler squashfs_handler = {
.type = "squashfs",
.generate = squash_generate,
.opts = squash_opts,
};
genimage-19/image-tar.c 0000664 0000000 0000000 00000002425 15032005261 0015070 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int tar_generate(struct image *image)
{
int ret;
char *comp = "a";
if (strstr(image->file, ".tar.gz") || strstr(image->file, "tgz"))
comp = "z";
if (strstr(image->file, ".tar.bz2"))
comp = "j";
ret = systemp(image, "%s c%s -f '%s' -C '%s' .",
get_opt("tar"),
comp,
imageoutfile(image), mountpath(image));
return ret;
}
static cfg_opt_t tar_opts[] = {
CFG_END()
};
struct image_handler tar_handler = {
.type = "tar",
.generate = tar_generate,
.opts = tar_opts,
};
genimage-19/image-ubi.c 0000664 0000000 0000000 00000006133 15032005261 0015061 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
struct ubi {
};
static int ubi_generate(struct image *image)
{
int ret;
FILE *fini;
char *tempfile;
int i = 0;
struct partition *part;
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
xasprintf(&tempfile, "%s/ubi.ini", tmppath());
if (!tempfile)
return -ENOMEM;
fini = fopen(tempfile, "w");
if (!fini) {
ret = -errno;
image_error(image, "creating temp file failed: %s\n", strerror(errno));
goto err_free;
}
list_for_each_entry(part, &image->partitions, list) {
struct image *child = NULL;
unsigned long long size = part->size;
if (part->image)
child = image_get(part->image);
if (!size) {
if (!child) {
image_error(image, "could not find %s\n", part->image);
fclose(fini);
ret = -EINVAL;
goto err_free;
}
size = child->size;
}
fprintf(fini, "[%s]\n", part->name);
fprintf(fini, "mode=ubi\n");
if (child)
fprintf(fini, "image=%s\n", imageoutfile(child));
fprintf(fini, "vol_id=%d\n", i);
fprintf(fini, "vol_size=%lld\n", size);
fprintf(fini, "vol_type=%s\n", part->read_only ? "static" : "dynamic");
fprintf(fini, "vol_name=%s\n", part->name);
if (part->autoresize)
fprintf(fini, "vol_flags=autoresize\n");
fprintf(fini, "vol_alignment=1\n");
i++;
}
fclose(fini);
ret = systemp(image, "%s -s %d -O %d -p %d -m %d -o '%s' '%s' %s",
get_opt("ubinize"),
image->flash_type->sub_page_size,
image->flash_type->vid_header_offset,
image->flash_type->pebsize,
image->flash_type->minimum_io_unit_size,
imageoutfile(image),
tempfile,
extraargs);
err_free:
free(tempfile);
return ret;
}
static int ubi_setup(struct image *image, cfg_t *cfg)
{
struct ubi *ubi = xzalloc(sizeof(*ubi));
int autoresize = 0;
struct partition *part;
if (!image->flash_type) {
image_error(image, "no flash type given\n");
return -EINVAL;
}
image->handler_priv = ubi;
list_for_each_entry(part, &image->partitions, list)
autoresize += part->autoresize;
if (autoresize > 1) {
image_error(image, "more than one volume has the autoresize flag set\n");
return -EINVAL;
}
return 0;
}
static cfg_opt_t ubi_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_END()
};
struct image_handler ubi_handler = {
.type = "ubi",
.no_rootpath = cfg_true,
.generate = ubi_generate,
.setup = ubi_setup,
.opts = ubi_opts,
};
genimage-19/image-ubifs.c 0000664 0000000 0000000 00000004337 15032005261 0015416 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2011 Sascha Hauer , Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int ubifs_generate(struct image *image)
{
int max_leb_cnt;
int ret;
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
unsigned long long max_size = cfg_getint_suffix(image->imagesec, "max-size");
cfg_bool_t space_fixup = cfg_getbool(image->imagesec, "space-fixup");
if (max_size)
max_leb_cnt = max_size / image->flash_type->lebsize;
else
max_leb_cnt = image->size / image->flash_type->lebsize;
ret = systemp(image, "%s %s%s%s %s -e %d -m %d -c %d -o '%s' %s",
get_opt("mkfsubifs"),
image->empty ? "" : "-d '",
image->empty ? "" : mountpath(image),
image->empty ? "" : "'",
space_fixup ? "-F" : "",
image->flash_type->lebsize,
image->flash_type->minimum_io_unit_size,
max_leb_cnt,
imageoutfile(image),
extraargs);
return ret;
}
static int ubifs_setup(struct image *image, cfg_t *cfg)
{
if (!image->flash_type) {
image_error(image, "no flash type given\n");
return -EINVAL;
}
if (image->flash_type->lebsize <= 0) {
image_error(image, "invalid lebsize (%d) in %s\n",
image->flash_type->lebsize, image->flash_type->name);
return -EINVAL;
}
return 0;
}
static cfg_opt_t ubifs_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("max-size", NULL, CFGF_NONE),
CFG_BOOL("space-fixup", 0, CFGF_NONE),
CFG_END()
};
struct image_handler ubifs_handler = {
.type = "ubifs",
.generate = ubifs_generate,
.setup = ubifs_setup,
.opts = ubifs_opts,
};
genimage-19/image-vfat.c 0000664 0000000 0000000 00000007201 15032005261 0015237 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 Michael Olbrich
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* 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, see .
*/
#include
#include
#include
#include
#include
#include "genimage.h"
static int vfat_generate(struct image *image)
{
int ret;
struct partition *part;
char *extraargs = cfg_getstr(image->imagesec, "extraargs");
char *label = cfg_getstr(image->imagesec, "label");
if (label && label[0] != '\0')
xasprintf(&label, "-n '%s'", label);
else
label = "";
ret = prepare_image(image, image->size);
if (ret)
return ret;
ret = systemp(image, "%s %s %s '%s'", get_opt("mkdosfs"),
extraargs, label, imageoutfile(image));
if (ret)
return ret;
list_for_each_entry(part, &image->partitions, list) {
struct image *child = image_get(part->image);
const char *file = imageoutfile(child);
const char *target = part->name;
char *path = strdupa(target);
char *next = path;
while ((next = strchr(next, '/')) != NULL) {
*next = '\0';
/* ignore the error: mdd fails if the target exists. */
systemp(image, "MTOOLS_SKIP_CHECK=1 %s -DsS -i %s '::%s'",
get_opt("mmd"), imageoutfile(image), path);
*next = '/';
++next;
}
image_info(image, "adding file '%s' as '%s' ...\n",
child->file, *target ? target : child->file);
ret = systemp(image, "MTOOLS_SKIP_CHECK=1 %s -sp -i '%s' '%s' '::%s'",
get_opt("mcopy"), imageoutfile(image),
file, target);
if (ret)
return ret;
}
if (!list_empty(&image->partitions))
return 0;
if (!image->empty)
ret = systemp(image, "MTOOLS_SKIP_CHECK=1 %s -sp -i '%s' '%s'/* ::",
get_opt("mcopy"), imageoutfile(image), mountpath(image));
return ret;
}
static int vfat_setup(struct image *image, cfg_t *cfg)
{
char *label = cfg_getstr(image->imagesec, "label");
if (!image->size) {
image_error(image, "no size given or must not be zero\n");
return -EINVAL;
}
if (label && strlen(label) > 11) {
image_error(image, "vfat volume name cannot be longer than 11 characters\n");
return -EINVAL;
}
return 0;
}
static int vfat_parse(struct image *image, cfg_t *cfg)
{
unsigned int i;
unsigned int num_files;
struct partition *part;
num_files = cfg_size(cfg, "file");
for (i = 0; i < num_files; i++) {
cfg_t *filesec = cfg_getnsec(cfg, "file", i);
part = xzalloc(sizeof *part);
part->name = cfg_title(filesec);
part->image = cfg_getstr(filesec, "image");
list_add_tail(&part->list, &image->partitions);
}
for (i = 0; i < cfg_size(cfg, "files"); i++) {
part = xzalloc(sizeof *part);
part->image = cfg_getnstr(cfg, "files", i);
part->name = "";
list_add_tail(&part->list, &image->partitions);
}
return 0;
}
static cfg_opt_t file_opts[] = {
CFG_STR("image", NULL, CFGF_NONE),
CFG_END()
};
static cfg_opt_t vfat_opts[] = {
CFG_STR("extraargs", "", CFGF_NONE),
CFG_STR("label", "", CFGF_NONE),
CFG_STR_LIST("files", NULL, CFGF_NONE),
CFG_SEC("file", file_opts, CFGF_MULTI | CFGF_TITLE),
CFG_END()
};
struct image_handler vfat_handler = {
.type = "vfat",
.generate = vfat_generate,
.setup = vfat_setup,
.parse = vfat_parse,
.opts = vfat_opts,
};
genimage-19/list.h 0000664 0000000 0000000 00000041030 15032005261 0014175 0 ustar 00root root 0000000 0000000 #ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
#define LIST_POISON1 ((void *) 0x00100100)
#define LIST_POISON2 ((void *) 0x00200200)
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next);
#endif
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
#else
extern void list_add(struct list_head *new, struct list_head *head);
#endif
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
static inline void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/**
* list_add_sort - add a new entry to a sorted list
* @new: new entry to be added
* @head: list head to add it in
* @compare: Compare function to compare two list entries
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_sort(struct list_head *new, struct list_head *head,
int (*compare)(struct list_head *a, struct list_head *b))
{
struct list_head *pos, *insert = head;
list_for_each(pos, head) {
if (compare(pos, new) < 0)
continue;
insert = pos;
break;
}
list_add_tail(new, insert);
}
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos; \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#endif
genimage-19/m4/ 0000775 0000000 0000000 00000000000 15032005261 0013373 5 ustar 00root root 0000000 0000000 genimage-19/m4/.gitignore 0000664 0000000 0000000 00000000100 15032005261 0015352 0 ustar 00root root 0000000 0000000 libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
genimage-19/m4/attributes.m4 0000664 0000000 0000000 00000024274 15032005261 0016034 0 ustar 00root root 0000000 0000000 dnl Macros to check the presence of generic (non-typed) symbols.
dnl Copyright (c) 2006-2008 Diego Pettenò
dnl Copyright (c) 2006-2008 xine project
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 2, or (at your option)
dnl any later version.
dnl
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
dnl 02110-1301, USA.
dnl
dnl As a special exception, the copyright owners of the
dnl macro gives unlimited permission to copy, distribute and modify the
dnl configure scripts that are the output of Autoconf when processing the
dnl Macro. You need not follow the terms of the GNU General Public
dnl License when using or distributing such scripts, even though portions
dnl of the text of the Macro appear in them. The GNU General Public
dnl License (GPL) does govern all other use of the material that
dnl constitutes the Autoconf Macro.
dnl
dnl This special exception to the GPL applies to versions of the
dnl Autoconf Macro released by this project. When you make and
dnl distribute a modified version of the Autoconf Macro, you may extend
dnl this special exception to the GPL to apply to your modified version as
dnl well.
dnl Check if the flag is supported by compiler
dnl CC_CHECK_CFLAGS_SILENT([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [
AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]),
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])],
[eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_cflags_$1])='no'"])
CFLAGS="$ac_save_CFLAGS"
])
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
[$2], [$3])
])
dnl Check if the flag is supported by compiler (cacheable)
dnl CC_CHECK_CFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
AC_DEFUN([CC_CHECK_CFLAGS], [
AC_CACHE_CHECK([if $CC supports $1 flag],
AS_TR_SH([cc_cv_cflags_$1]),
CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
)
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
[$2], [$3])
])
dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found])
dnl Check for CFLAG and appends them to CFLAGS if supported
AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
AC_CACHE_CHECK([if $CC supports $1 flag],
AS_TR_SH([cc_cv_cflags_$1]),
CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
)
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
[CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
])
dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not])
AC_DEFUN([CC_CHECK_CFLAGS_APPEND], [
for flag in $1; do
CC_CHECK_CFLAG_APPEND($flag, [$2], [$3])
done
])
dnl Check if the flag is supported by linker (cacheable)
dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
AC_DEFUN([CC_CHECK_LDFLAGS], [
AC_CACHE_CHECK([if $CC supports $1 flag],
AS_TR_SH([cc_cv_ldflags_$1]),
[ac_save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $1"
AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])],
[eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_ldflags_$1])="])
LDFLAGS="$ac_save_LDFLAGS"
])
AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
[$2], [$3])
])
dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
dnl the current linker to avoid undefined references in a shared object.
AC_DEFUN([CC_NOUNDEFINED], [
dnl We check $host for which systems to enable this for.
AC_REQUIRE([AC_CANONICAL_HOST])
case $host in
dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
dnl are requested, as different implementations are present; to avoid problems
dnl use -Wl,-z,defs only for those platform not behaving this way.
*-freebsd* | *-openbsd*) ;;
*)
dnl First of all check for the --no-undefined variant of GNU ld. This allows
dnl for a much more readable commandline, so that people can understand what
dnl it does without going to look for what the heck -z defs does.
for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
break
done
;;
esac
AC_SUBST([LDFLAGS_NOUNDEFINED])
])
dnl Check for a -Werror flag or equivalent. -Werror is the GCC
dnl and ICC flag that tells the compiler to treat all the warnings
dnl as fatal. We usually need this option to make sure that some
dnl constructs (like attributes) are not simply ignored.
dnl
dnl Other compilers don't support -Werror per se, but they support
dnl an equivalent flag:
dnl - Sun Studio compiler supports -errwarn=%all
AC_DEFUN([CC_CHECK_WERROR], [
AC_CACHE_CHECK(
[for $CC way to treat warnings as errors],
[cc_cv_werror],
[CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
[CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
])
])
AC_DEFUN([CC_CHECK_ATTRIBUTE], [
AC_REQUIRE([CC_CHECK_WERROR])
AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
AS_TR_SH([cc_cv_attribute_$1]),
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
[eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
[eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
CFLAGS="$ac_save_CFLAGS"
])
AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
[AC_DEFINE(
AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
[Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
)
$4],
[$5])
])
AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
CC_CHECK_ATTRIBUTE(
[constructor],,
[void __attribute__((constructor)) ctor() { int a; }],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
CC_CHECK_ATTRIBUTE(
[format], [format(printf, n, n)],
[void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
CC_CHECK_ATTRIBUTE(
[format_arg], [format_arg(printf)],
[char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
CC_CHECK_ATTRIBUTE(
[visibility_$1], [visibility("$1")],
[void __attribute__((visibility("$1"))) $1_function() { }],
[$2], [$3])
])
AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
CC_CHECK_ATTRIBUTE(
[nonnull], [nonnull()],
[void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
CC_CHECK_ATTRIBUTE(
[unused], ,
[void some_function(void *foo, __attribute__((unused)) void *bar);],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
CC_CHECK_ATTRIBUTE(
[sentinel], ,
[void some_function(void *foo, ...) __attribute__((sentinel));],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
CC_CHECK_ATTRIBUTE(
[deprecated], ,
[void some_function(void *foo, ...) __attribute__((deprecated));],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
CC_CHECK_ATTRIBUTE(
[alias], [weak, alias],
[void other_function(void *foo) { }
void some_function(void *foo) __attribute__((weak, alias("other_function")));],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
CC_CHECK_ATTRIBUTE(
[malloc], ,
[void * __attribute__((malloc)) my_alloc(int n);],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_PACKED], [
CC_CHECK_ATTRIBUTE(
[packed], ,
[struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
[$1], [$2])
])
AC_DEFUN([CC_ATTRIBUTE_CONST], [
CC_CHECK_ATTRIBUTE(
[const], ,
[int __attribute__((const)) twopow(int n) { return 1 << n; } ],
[$1], [$2])
])
AC_DEFUN([CC_FLAG_VISIBILITY], [
AC_REQUIRE([CC_CHECK_WERROR])
AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
[cc_cv_flag_visibility],
[cc_flag_visibility_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
cc_cv_flag_visibility='yes',
cc_cv_flag_visibility='no')
CFLAGS="$cc_flag_visibility_save_CFLAGS"])
AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
[AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
[Define this if the compiler supports the -fvisibility flag])
$1],
[$2])
])
AC_DEFUN([CC_FUNC_EXPECT], [
AC_REQUIRE([CC_CHECK_WERROR])
AC_CACHE_CHECK([if compiler has __builtin_expect function],
[cc_cv_func_expect],
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[int some_function() {
int a = 3;
return (int)__builtin_expect(a, 3);
}])],
[cc_cv_func_expect=yes],
[cc_cv_func_expect=no])
CFLAGS="$ac_save_CFLAGS"
])
AS_IF([test "x$cc_cv_func_expect" = "xyes"],
[AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
[Define this if the compiler supports __builtin_expect() function])
$1],
[$2])
])
AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
AC_REQUIRE([CC_CHECK_WERROR])
AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
[cc_cv_attribute_aligned],
[ac_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $cc_cv_werror"
for cc_attribute_align_try in 64 32 16 8 4 2; do
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
int main() {
static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
return c;
}])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
done
CFLAGS="$ac_save_CFLAGS"
])
if test "x$cc_cv_attribute_aligned" != "x"; then
AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
[Define the highest alignment supported])
fi
])
genimage-19/test.config 0000664 0000000 0000000 00000004431 15032005261 0015223 0 ustar 00root root 0000000 0000000
include("flash.conf")
#-----------------------------------
image data.tgz {
tar {}
mountpoint = "/data"
}
image nand-pcm038.img {
flash {
}
flashtype = "nand-64M-512"
partition barebox {
image = "barebox-pcm038.bin"
size = 512K
}
partition bareboxenv {
image = "bareboxenv-pcm038.bin"
size = 512K
}
partition kernel {
image = "kernel-imx.bin"
size = 4M
}
partition root {
image = "root-nand.ubi"
size = 20M
}
partition data {
image = "data-nand.ubi"
size = 0
}
}
image root-nor-32M-64k.jffs2 {
name = "root"
flashtype = "nor-64M-128k"
jffs2 {}
size = 24M
mountpoint = "/"
}
image data-nor-32M-64k.jffs2 {
name = "data"
flashtype = "nor-64M-128k"
size = 0
jffs2 {
extraargs = "-l"
}
mountpoint = "/data"
}
image nand-pcm037.img {
flash {
}
flashtype = "nand-64M-512"
partition barebox {
image = "barebox-pcm037.bin"
size = 512K
}
partition bareboxenv {
image = "bareboxenv-pcm037.bin"
size = 512K
}
partition kernel {
image = "kernel-imx.bin"
size = 4M
}
partition root {
image = "root-nand.ubi"
size = 20M
}
partition data {
image = "data-nand.ubi"
size = 0
}
}
image data-nand.ubi {
ubi {}
partition data {
autoresize = true
image = "data-nand.ubifs"
}
partition root {
image = "data-nand.ubifs"
}
}
image data-nand.ubifs {
ubifs {}
name = "data"
size = 128M
mountpoint = "/data"
}
image barebox-pcm038.bin {
name = "barebox"
file {}
}
image bareboxenv-pcm038.bin {
name = "bareboxenv"
file {}
}
image barebox-pcm037.bin {
name = "barebox"
file {}
}
image bareboxenv-pcm037.bin {
name = "bareboxenv"
file {}
}
image kernel-imx.bin {
name = "kernel"
file {
name = "zImage-linux-2.6.39-imx"
}
}
image root-nand.ubi {
name = "root"
ubi {}
partition root {
image = "root-nand.ubifs"
}
}
image root-nand.ubifs {
name = "root"
size = 128M
ubifs {}
mountpoint = "/"
}
image hdimg.img {
hdimage {}
partition root {
offset = 2M
size = 128M
partition-type = 0x78
image = "root.ext2"
}
partition data {
size = 20M
partition-type = 0x1a
image = "data.ext2"
}
size = 2G
}
image root.ext2 {
ext2 {}
size = 128M
mountpoint = "/"
}
image data.ext2 {
ext2 {}
size = 20M
mountpoint = "/data"
}
config {
outputpath = images
inputpath = input
rootpath = root
tmppath = tmp
}
genimage-19/test/ 0000775 0000000 0000000 00000000000 15032005261 0014032 5 ustar 00root root 0000000 0000000 genimage-19/test/btrfs.config 0000664 0000000 0000000 00000000250 15032005261 0016336 0 ustar 00root root 0000000 0000000 image test.btrfs {
btrfs {
label = "btrfstest"
# set UUID to test if extraargs works
extraargs = "--uuid 47e790af-a2e1-42ff-92c7-83f45f7b2228"
}
size = 128M
}
genimage-19/test/cpio.config 0000664 0000000 0000000 00000000105 15032005261 0016147 0 ustar 00root root 0000000 0000000 image test.cpio {
cpio {
format = "newc"
compress = "gzip"
}
}
genimage-19/test/cramfs.config 0000664 0000000 0000000 00000000073 15032005261 0016474 0 ustar 00root root 0000000 0000000 image test.cramfs {
cramfs {
extraargs = "-b 4096"
}
}
genimage-19/test/custom.config 0000664 0000000 0000000 00000000131 15032005261 0016526 0 ustar 00root root 0000000 0000000 image test.custom {
custom {
exec = 'echo "Hello genimage!" > "${IMAGEOUTFILE}"'
}
}
genimage-19/test/erofs.dump.new 0000664 0000000 0000000 00000013564 15032005261 0016640 0 ustar 00root root 0000000 0000000 Filesystem magic number: 0xE0F5E1E2
Filesystem blocksize: 4096
Filesystem blocks: 2
Filesystem inode metadata start block: 0
Filesystem shared xattr metadata start block: 0
Filesystem root nid: 36
Filesystem lz4_max_distance: 0
Filesystem sb_size: 128
Filesystem inode count: 41
Filesystem created: Sat Jan 1 00:00:00 2000
Filesystem features: sb_csum mtime
Filesystem UUID: 83d9e40a-fb96-469e-abb9-24fb3c3bd0ff
Filesystem total file count: 41
Filesystem unknown type count: 0
Filesystem regular file count: 24
Filesystem directory count: 17
Filesystem char dev count: 0
Filesystem block dev count: 0
Filesystem FIFO file count: 0
Filesystem SOCK file count: 0
Filesystem symlink file count: 0
Filesystem compressed files: 0
Filesystem uncompressed files: 41
Filesystem total original file size: 0 Bytes
Filesystem total file size: 0 Bytes
Filesystem compress rate: nan%
Original file size distribution:
>=(KB) .. <(KB) count ratio |distribution |
0 .. 1 24 100.00% |##################################################|
1 .. 2 0 0.00% | |
2 .. 4 0 0.00% | |
4 .. 8 0 0.00% | |
8 .. 16 0 0.00% | |
16 .. 32 0 0.00% | |
32 .. 64 0 0.00% | |
64 .. 128 0 0.00% | |
128 .. 256 0 0.00% | |
256 .. 512 0 0.00% | |
512 .. 1024 0 0.00% | |
1024 .. 2048 0 0.00% | |
2048 .. 4096 0 0.00% | |
4096 .. 8192 0 0.00% | |
8192 .. 16384 0 0.00% | |
16384 .. 32768 0 0.00% | |
32768 .. 0 0.00% | |
On-disk file size distribution:
>=(KB) .. <(KB) count ratio |distribution |
0 .. 1 24 100.00% |##################################################|
1 .. 2 0 0.00% | |
2 .. 4 0 0.00% | |
4 .. 8 0 0.00% | |
8 .. 16 0 0.00% | |
16 .. 32 0 0.00% | |
32 .. 64 0 0.00% | |
64 .. 128 0 0.00% | |
128 .. 256 0 0.00% | |
256 .. 512 0 0.00% | |
512 .. 1024 0 0.00% | |
1024 .. 2048 0 0.00% | |
2048 .. 4096 0 0.00% | |
4096 .. 8192 0 0.00% | |
8192 .. 16384 0 0.00% | |
16384 .. 32768 0 0.00% | |
32768 .. 0 0.00% | |
File type distribution:
type count ratio |distribution |
.txt 0 0.00% | |
.so 0 0.00% | |
.xml 0 0.00% | |
.apk 0 0.00% | |
.odex 0 0.00% | |
.vdex 0 0.00% | |
.oat 0 0.00% | |
.rc 0 0.00% | |
.otf 0 0.00% | |
others 24 100.00% |##################################################|
Path : /
Size: 95 On-disk size: 95 directory
NID: 36 Links: 6 Layout: 2 Compression ratio: 100.00%
Inode size: 64 Xattr size: 0
Uid: 0 Gid: 0 Access: 0755/rwxr-xr-x
Timestamp: 2000-01-01 00:00:00.000000000
NID TYPE FILENAME
36 2 .
36 2 ..
41 2 bar
46 2 baz
51 2 foo
56 2 with spaces
genimage-19/test/erofs.dump.old 0000664 0000000 0000000 00000013515 15032005261 0016621 0 ustar 00root root 0000000 0000000 Filesystem magic number: 0xE0F5E1E2
Filesystem blocks: 2
Filesystem inode metadata start block: 0
Filesystem shared xattr metadata start block: 0
Filesystem root nid: 36
Filesystem inode count: 41
Filesystem created: Sat Jan 1 00:00:00 2000
Filesystem features: sb_csum mtime
Filesystem UUID: 83d9e40a-fb96-469e-abb9-24fb3c3bd0ff
Filesystem total file count: 41
Filesystem unknown type count: 0
Filesystem regular file count: 24
Filesystem directory count: 17
Filesystem char dev count: 0
Filesystem block dev count: 0
Filesystem FIFO file count: 0
Filesystem SOCK file count: 0
Filesystem symlink file count: 0
Filesystem compressed files: 0
Filesystem uncompressed files: 41
Filesystem total original file size: 0 Bytes
Filesystem total file size: 0 Bytes
Filesystem compress rate: nan%
Original file size distribution:
>=(KB) .. <(KB) count ratio |distribution |
0 .. 1 24 100.00% |##################################################|
1 .. 2 0 0.00% | |
2 .. 4 0 0.00% | |
4 .. 8 0 0.00% | |
8 .. 16 0 0.00% | |
16 .. 32 0 0.00% | |
32 .. 64 0 0.00% | |
64 .. 128 0 0.00% | |
128 .. 256 0 0.00% | |
256 .. 512 0 0.00% | |
512 .. 1024 0 0.00% | |
1024 .. 2048 0 0.00% | |
2048 .. 4096 0 0.00% | |
4096 .. 8192 0 0.00% | |
8192 .. 16384 0 0.00% | |
16384 .. 32768 0 0.00% | |
32768 .. 0 0.00% | |
On-disk file size distribution:
>=(KB) .. <(KB) count ratio |distribution |
0 .. 1 24 100.00% |##################################################|
1 .. 2 0 0.00% | |
2 .. 4 0 0.00% | |
4 .. 8 0 0.00% | |
8 .. 16 0 0.00% | |
16 .. 32 0 0.00% | |
32 .. 64 0 0.00% | |
64 .. 128 0 0.00% | |
128 .. 256 0 0.00% | |
256 .. 512 0 0.00% | |
512 .. 1024 0 0.00% | |
1024 .. 2048 0 0.00% | |
2048 .. 4096 0 0.00% | |
4096 .. 8192 0 0.00% | |
8192 .. 16384 0 0.00% | |
16384 .. 32768 0 0.00% | |
32768 .. 0 0.00% | |
File type distribution:
type count ratio |distribution |
.txt 0 0.00% | |
.so 0 0.00% | |
.xml 0 0.00% | |
.apk 0 0.00% | |
.odex 0 0.00% | |
.vdex 0 0.00% | |
.oat 0 0.00% | |
.rc 0 0.00% | |
.otf 0 0.00% | |
.txt 0 0.00% | |
others 24 100.00% |##################################################|
File : /
Size: 95 On-disk size: 95 directory
NID: 36 Links: 6 Layout: 2 Compression ratio: 100.00%
Inode size: 64 Extent size: 0 Xattr size: 0
Uid: 0 Gid: 0 Access: 0755/rwxr-xr-x
Timestamp: 2000-01-01 00:00:00.000000000
NID TYPE FILENAME
36 2 .
36 2 ..
41 2 bar
70 2 baz
99 2 foo
130 2 with spaces
genimage-19/test/erofs.new.config 0000664 0000000 0000000 00000000216 15032005261 0017126 0 ustar 00root root 0000000 0000000 image test.erofs {
erofs {
fs-timestamp = "20000101000000"
extraargs = "-U 83d9e40a-fb96-469e-abb9-24fb3c3bd0ff -b 4096"
}
size = 4M
}
genimage-19/test/erofs.old.config 0000664 0000000 0000000 00000000206 15032005261 0017112 0 ustar 00root root 0000000 0000000 image test.erofs {
erofs {
fs-timestamp = "20000101000000"
extraargs = "-U 83d9e40a-fb96-469e-abb9-24fb3c3bd0ff"
}
size = 4M
}
genimage-19/test/exec-check.sh 0000775 0000000 0000000 00000001161 15032005261 0016367 0 ustar 00root root 0000000 0000000 #!/bin/bash
exec >&2
name="${1}"
empty="${2}"
set -ex
: OUTPUTPATH
test "${OUTPUTPATH}" = "${PWD}/images"
: INPUTPATH
test "${INPUTPATH}" = "${PWD}/input"
: ROOTPATH
test "${ROOTPATH}" = "${PWD}/root.orig"
: TMPPATH
test "${TMPPATH}" = "${PWD}/tmp"
: IMAGE
test "${IMAGE}" = "${name}"
: IMAGEOUTFILE
test "${IMAGEOUTFILE}" = "${PWD}/images/${name}"
: IMAGENAME
test "${IMAGENAME}" = "exec-test"
: IMAGESIZE
test "${IMAGESIZE}" = "3584"
: IMAGEMOUNTPOINT
test "${IMAGEMOUNTPOINT}" = ""
: IMAGEMOUNTPATH
if [ "${empty}" = "empty" ]; then
test "${IMAGEMOUNTPATH}" = ""
else
test "${IMAGEMOUNTPATH}" = "${PWD}/tmp/root"
fi
genimage-19/test/exec-fail.config 0000664 0000000 0000000 00000000061 15032005261 0017053 0 ustar 00root root 0000000 0000000 image file1.img {
file {}
exec-pre = "false"
}
genimage-19/test/exec.config 0000664 0000000 0000000 00000000665 15032005261 0016154 0 ustar 00root root 0000000 0000000 image file1.img {
file {}
name = "exec-test"
exec-pre = "./exec-check.sh file1.img"
}
image file2.img {
file {}
name = "exec-test"
mountpoint = "/"
exec-post = "./exec-check.sh file2.img"
}
image file3.img {
file {}
name = "exec-test"
empty = true
exec-pre = "./exec-check.sh file3.img empty"
}
image file4.img {
file {}
name = "exec-test"
empty = true
mountpoint = "/"
exec-post = "./exec-check.sh file4.img empty"
}
genimage-19/test/ext.test 0000775 0000000 0000000 00000005743 15032005261 0015547 0 ustar 00root root 0000000 0000000 #!/bin/bash
test_description="extX Image Tests"
. "$(dirname "${0}")/test-setup.sh"
check_root() {
diff -ru "${root_orig}" "${root_test}"
}
func_check() {
local ret="$?"
set +x
if [ "${ret}" != 0 ]; then
echo "Failed to execute '${FUNCNAME[1]}'!" >&2
return "${ret}"
fi
}
compare_label() {
if [ "${1}" != "${2}" ]; then
echo "Filesystem Label does not match: exprected: '${2}' found '${1}'"
return 1
fi
}
version_leq() {
first="$(printf "${1}\n${2}" | sort -V | head -n1)"
test "${first}" == "${1}"
}
check_ext() {
[ "$verbose" = "t" ] && set -x
# UUID is randomly generated
uuid="Filesystem UUID"
# Hash Seed is randomly generated
seed="Directory Hash Seed:"
# checksum depends on random data
csum1="Checksum: \|Group 0: (Blocks 1-4095) csum"
# format change
csum2="Group 0: (Blocks 1-4095) \\[ITABLE_ZEROED\\]\| Checksum .*, unused inodes 205"
dumpe2fs "${1}" | grep -v "^\($uuid\|$seed\|$csum1\|$csum2\)" > "dump" &&
# some architectures (including arm64) use unsigned char
sed -i 's/un\(signed_directory_hash\)/\1/' "dump" &&
if [ "${4}" = "genext2fs" ]; then
if [ "$(genext2fs --version)" = "genext2fs 1.4.1" ]; then
version=0
else
dumpe2fs_version="$(dumpe2fs -V |& sed -n 's/^dumpe2fs \([^ ]*\) .*/\1/p')"
if version_leq "${dumpe2fs_version}" "1.46.2"; then
# Debian Bullseye
version=1
else
version=2
fi
fi
else
mke2fs_version="$(mke2fs -V |& sed -n 's/^mke2fs \([^ ]*\) .*/\1/p')"
if version_leq "${mke2fs_version}" "1.45.5"; then
# Ubuntu 20.04
version=0
elif version_leq "${mke2fs_version}" "1.46.5"; then
# Ubuntu 22.04
version=1
elif version_leq "${mke2fs_version}" "1.47.0"; then
# Ubuntu 24.04
version=2
else
# at least 1.47.0
version=3
fi
fi
export TEST_CMP="diff --ignore-space-change -u" &&
test_cmp "${testdir}/${2}.${version}.dump" "dump" &&
e2fsck -nf "${1}" &&
# old versions of debugfs cannot dump '/'
debugfs -R "ls -p" "${1}" | (
IFS=/
while read a b c d e x f; do
case "${x}" in
.|..|lost+found|"") continue ;;
esac
debugfs -R "rdump \"${x}\" \"${root_test}\"" "${1}" || break
done
) &&
check_size "${1}" "${3}" &&
check_root
func_check
}
exec_test_set_prereq genext2fs
exec_test_set_prereq e2fsck
test_expect_success genext2fs,e2fsck "ext2" "
run_genimage_root ext2.config test.ext2 &&
check_ext images/test.ext2 ext2test 4194304 genext2fs
"
test_expect_success genext2fs,e2fsck "ext2percent" "
run_genimage_root ext2percent.config test.ext2 &&
check_ext images/test.ext2 ext2test-percent 69632 genext2fs
"
test_expect_success genext2fs,e2fsck "ext3" "
run_genimage_root ext3.config test.ext3 &&
check_ext images/test.ext3 ext3test 4194304 genext2fs
"
test_expect_success genext2fs,e2fsck "ext4" "
run_genimage ext4.config test.ext4 &&
check_ext images/test.ext4 ext4test 4194304 genext2fs
"
test_expect_success mke2fs,e2fsck "mke2fs" "
run_genimage_root mke2fs.config mke2fs.ext4 &&
check_ext images/mke2fs.ext4 mke2fs 33554432 mke2fs
"
test_done
# vim: syntax=sh
genimage-19/test/ext2.config 0000664 0000000 0000000 00000000166 15032005261 0016106 0 ustar 00root root 0000000 0000000 image test.ext2 {
ext2 {
label = "ext2test"
use-mke2fs = false
fs-timestamp = "20000101000000"
}
size = 4M
}
genimage-19/test/ext2percent.config 0000664 0000000 0000000 00000000170 15032005261 0017462 0 ustar 00root root 0000000 0000000 image test.ext2 {
ext2 {
label = "ext2test"
use-mke2fs = false
fs-timestamp = "20000101000000"
}
size = 100%
}
genimage-19/test/ext2test-percent.0.dump 0000664 0000000 0000000 00000002372 15032005261 0020303 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext2test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 0 (original)
Filesystem features: (none)
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 56
Block count: 68
Reserved block count: 3
Free blocks: 36
Free inodes: 5
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 72
Fragments per group: 72
Inodes per group: 56
Inode blocks per group: 7
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
Group 0: (Blocks 1-67)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-11 (+4)
36 free blocks, 5 free inodes, 18 directories
Free blocks: 32-67
Free inodes: 52-56
genimage-19/test/ext2test-percent.1.dump 0000664 0000000 0000000 00000002460 15032005261 0020302 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext2test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: (none)
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 56
Block count: 68
Reserved block count: 3
Free blocks: 22
Free inodes: 5
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 72
Fragments per group: 72
Inodes per group: 56
Inode blocks per group: 7
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Group 0: (Blocks 1-67)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-11 (+4)
22 free blocks, 5 free inodes, 18 directories
Free blocks: 46-67
Free inodes: 52-56
genimage-19/test/ext2test-percent.2.dump 0000664 0000000 0000000 00000002464 15032005261 0020307 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext2test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: (none)
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 56
Block count: 68
Reserved block count: 3
Free blocks: 22
Free inodes: 5
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 72
Fragments per group: 72
Inodes per group: 56
Inode blocks per group: 7
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Group 0: (Blocks 1-67)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-11 (+4)
22 free blocks, 5 free inodes, 18 directories
Free blocks: 46-67
Free inodes: 52-56
genimage-19/test/ext2test.0.dump 0000664 0000000 0000000 00000002423 15032005261 0016642 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext2test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 0 (original)
Filesystem features: (none)
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Free blocks: 3837
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
Group 0: (Blocks 1-4095)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
3837 free blocks, 205 free inodes, 18 directories
Free blocks: 259-4095
Free inodes: 52-256
genimage-19/test/ext2test.1.dump 0000664 0000000 0000000 00000002510 15032005261 0016640 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext2test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: (none)
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Free blocks: 4025
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Group 0: (Blocks 1-4095)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
4025 free blocks, 205 free inodes, 18 directories
Free blocks: 71-4095
Free inodes: 52-256
genimage-19/test/ext2test.2.dump 0000664 0000000 0000000 00000002514 15032005261 0016645 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext2test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: (none)
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Free blocks: 4025
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Group 0: (Blocks 1-4095)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
4025 free blocks, 205 free inodes, 18 directories
Free blocks: 71-4095
Free inodes: 52-256
genimage-19/test/ext3.config 0000664 0000000 0000000 00000000166 15032005261 0016107 0 ustar 00root root 0000000 0000000 image test.ext3 {
ext3 {
label = "ext3test"
use-mke2fs = false
fs-timestamp = "20000101000000"
}
size = 4M
}
genimage-19/test/ext3test.0.dump 0000664 0000000 0000000 00000003063 15032005261 0016644 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext3test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Free blocks: 2808
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
Journal backup: inode blocks
Journal features: (none)
Journal size: 1024k
Journal length: 1024
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 1-4095)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
2808 free blocks, 205 free inodes, 18 directories
Free blocks: 1288-4095
Free inodes: 52-256
genimage-19/test/ext3test.1.dump 0000664 0000000 0000000 00000003156 15032005261 0016650 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext3test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Free blocks: 2996
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
Journal backup: inode blocks
Journal features: (none)
Total journal size: 1024k
Total journal blocks: 1024
Max transaction length: 1024
Fast commit length: 0
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 1-4095)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
2996 free blocks, 205 free inodes, 18 directories
Free blocks: 1100-4095
Free inodes: 52-256
genimage-19/test/ext3test.2.dump 0000664 0000000 0000000 00000003221 15032005261 0016642 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext3test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Overhead clusters: 1024
Free blocks: 2996
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
Journal backup: inode blocks
Journal features: (none)
Total journal size: 1024k
Total journal blocks: 1024
Max transaction length: 1024
Fast commit length: 0
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 1-4095)
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
2996 free blocks, 205 free inodes, 18 directories
Free blocks: 1100-4095
Free inodes: 52-256
genimage-19/test/ext4.config 0000664 0000000 0000000 00000000215 15032005261 0016103 0 ustar 00root root 0000000 0000000 image test.ext4 {
ext4 {
label = "ext4test"
fs-timestamp = "20000101000000"
use-mke2fs = false
}
srcpath = "root.orig"
size = 4M
}
genimage-19/test/ext4test.0.dump 0000664 0000000 0000000 00000003234 15032005261 0016645 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext4test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal dir_index extent uninit_bg
Filesystem flags: signed_directory_hash
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Free blocks: 2813
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
Default directory hash: half_md4
Journal backup: inode blocks
Journal features: (none)
Journal size: 1024k
Journal length: 1024
Journal sequence: 0x00000001
Journal start: 0
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
2813 free blocks, 205 free inodes, 18 directories, 205 unused inodes
Free blocks: 1283-4095
Free inodes: 52-256
genimage-19/test/ext4test.1.dump 0000664 0000000 0000000 00000003327 15032005261 0016651 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext4test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal dir_index extent uninit_bg
Filesystem flags: signed_directory_hash
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Free blocks: 3001
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
Default directory hash: half_md4
Journal backup: inode blocks
Journal features: (none)
Total journal size: 1024k
Total journal blocks: 1024
Max transaction length: 1024
Fast commit length: 0
Journal sequence: 0x00000001
Journal start: 0
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
3001 free blocks, 205 free inodes, 18 directories, 205 unused inodes
Free blocks: 1095-4095
Free inodes: 52-256
genimage-19/test/ext4test.2.dump 0000664 0000000 0000000 00000003372 15032005261 0016652 0 ustar 00root root 0000000 0000000 Filesystem volume name: ext4test
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal dir_index extent uninit_bg
Filesystem flags: signed_directory_hash
Default mount options: (none)
Filesystem state: clean
Errors behavior: Unknown (continue)
Filesystem OS type: Linux
Inode count: 256
Block count: 4096
Reserved block count: 204
Overhead clusters: 1024
Free blocks: 3001
Free inodes: 205
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 4096
Fragments per group: 4096
Inodes per group: 256
Inode blocks per group: 32
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: 20
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
Default directory hash: half_md4
Journal backup: inode blocks
Journal features: (none)
Total journal size: 1024k
Total journal blocks: 1024
Max transaction length: 1024
Fast commit length: 0
Journal sequence: 0x00000001
Journal start: 0
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2)
Inode bitmap at 4 (+3)
Inode table at 5-36 (+4)
3001 free blocks, 205 free inodes, 18 directories, 205 unused inodes
Free blocks: 1095-4095
Free inodes: 52-256
genimage-19/test/f2fs.config 0000664 0000000 0000000 00000000100 15032005261 0016050 0 ustar 00root root 0000000 0000000 image test.f2fs {
f2fs {
label = "f2fstest"
}
size = 64M
}
genimage-19/test/filesystem.test 0000775 0000000 0000000 00000006003 15032005261 0017121 0 ustar 00root root 0000000 0000000 #!/bin/bash
test_description="Filesystem Image Tests"
. "$(dirname "${0}")/test-setup.sh"
check_filelist() {
test_cmp "${filelist_orig}" "${filelist_test}"
}
exec_test_set_prereq cpio
test_expect_success cpio "cpio" "
run_genimage_root cpio.config test.cpio &&
zcat images/test.cpio | cpio --extract -t | grep -v '^\.$' | sort > '${filelist_test}' &&
check_size_range images/test.cpio 400 550 &&
check_filelist
"
exec_test_set_prereq mkfs.cramfs
test_expect_success mkfs_cramfs "cramfs" "
run_genimage_root cramfs.config test.cramfs &&
check_size images/test.cramfs 4096
"
exec_test_set_prereq genisoimage
test_expect_success genisoimage "iso" "
run_genimage_root iso.config test.iso &&
check_size_range images/test.iso 300000 400000
"
exec_test_set_prereq mkfs.f2fs
exec_test_set_prereq sload.f2fs
exec_test_set_prereq fsck.f2fs
test_expect_success mkfs_f2fs,sload_f2fs,fsck_f2fs "f2fs" "
run_genimage_root f2fs.config test.f2fs &&
fsck.f2fs images/test.f2fs
"
exec_test_set_prereq btrfs
exec_test_set_prereq mkfs.btrfs
test_expect_success mkfs_btrfs,btrfs "btrfs" "
run_genimage_root btrfs.config test.btrfs &&
btrfs check images/test.btrfs &&
test \"\$(btrfs filesystem label images/test.btrfs)\" = btrfstest &&
btrfs filesystem show images/test.btrfs | grep -q \"uuid: 47e790af-a2e1-42ff-92c7-83f45f7b2228\"
"
exec_test_set_prereq mksquashfs
test_expect_success mksquashfs "squashfs" "
run_genimage_root squashfs.config test.squashfs &&
check_size_range images/test.squashfs 4000 4100 &&
unsquashfs -ls images/test.squashfs | sed -n '/squashfs-root/s;squashfs-root/;;p' | sort > '${filelist_test}' &&
check_filelist
"
exec_test_set_prereq tar
test_expect_success tar "tar" "
run_genimage_root tar.config test.tar.gz &&
check_size_range images/test.tar.gz 500 600 &&
zcat images/test.tar.gz | tar -t | sed -n -e 's;/$;;' -e 's;^\./\(..*\)$;\1;p' | sort > '${filelist_test}' &&
check_filelist
"
exec_test_set_prereq dd
exec_test_set_prereq mkdosfs
exec_test_set_prereq mcopy
test_expect_success dd,mkdosfs,mcopy "vfat" "
run_genimage_root vfat.config test.vfat &&
fsck.fat -p images/test.vfat | tee fsck.log &&
test_must_fail grep -q 'Filesystem was changed' fsck.log &&
check_size images/test.vfat 4193280 &&
MTOOLS_SKIP_CHECK=1 mdir -/ -f -b -i images/test.vfat / | sed -e 's;^::/;;' -e 's;/$;;' | sort > '${filelist_test}' &&
check_filelist
"
exec_test_set_prereq mkfs.erofs
exec_test_set_prereq fsck.erofs
test_expect_success mkfs_erofs,fsck_erofs "erofs" "
if mkfs.erofs --help |& grep -q -- --mkfs-time; then
dump=\"${testdir}/erofs.dump.new\"
config=erofs.new.config
else
dump=\"${testdir}/erofs.dump.old\"
config=erofs.old.config
fi
SOURCE_DATE_EPOCH=946684800 run_genimage_root \"\${config}\" test.erofs &&
fsck.erofs -p images/test.erofs | tee erofs.log &&
test_must_fail grep -q 'Filesystem was changed' erofs.log &&
check_size images/test.erofs 8192 &&
dump.erofs -s -S --ls --path=/ images/test.erofs | sed 's/-nan/nan/' > erofs.dump &&
test_cmp \"\${dump}\" erofs.dump
"
test_done
# vim: syntax=sh
genimage-19/test/fip-size.config 0000664 0000000 0000000 00000000425 15032005261 0016750 0 ustar 00root root 0000000 0000000 image test.fip {
fip {
extraargs = "--align 64"
fw-config = "part1.img"
tos-fw = { "part2.img", "part1.img" }
/* will be about 12k in size */
}
}
image test.hdimage {
hdimage {}
partition part1 {
image = test.fip
size = 512 /* too small for fip image */
}
}
genimage-19/test/fip.config 0000664 0000000 0000000 00000000172 15032005261 0015777 0 ustar 00root root 0000000 0000000 image test.fip {
fip {
extraargs = "--align 64"
fw-config = "part1.img"
tos-fw = { "part2.img", "part1.img" }
}
}
genimage-19/test/fit.config 0000664 0000000 0000000 00000000214 15032005261 0016000 0 ustar 00root root 0000000 0000000 image test.fit {
fit {
its = "fit.its"
}
partition kernel {
image = "part1.img"
}
partition ramdisk {
image = "part2.img"
}
}
genimage-19/test/fit.its 0000664 0000000 0000000 00000000736 15032005261 0015343 0 ustar 00root root 0000000 0000000 /dts-v1/;
/ {
description = "Test FIT image";
#address-cells = <1>;
images {
kernel {
description = "kernel";
type = "kernel";
arch = "arm";
os = "linux";
compression = "none";
};
ramdisk {
description = "ramdisk";
type = "ramdisk";
arch = "arm";
os = "linux";
compression = "none";
};
};
configurations {
default = "conf";
conf {
description = "test dummy config";
kernel = "kernel";
ramdisk = "ramdisk";
};
};
};
genimage-19/test/flash-fill.config 0000664 0000000 0000000 00000000327 15032005261 0017244 0 ustar 00root root 0000000 0000000 include("flash-types.config")
image test.flash {
flash {
}
flashtype = "nand-64M-512"
partition part1 {
image = "part1.img"
size = 1M
}
partition part2 {
image = "part2.img"
size = 1M
}
size = 3M
}
genimage-19/test/flash-fill.md5 0000664 0000000 0000000 00000000064 15032005261 0016462 0 ustar 00root root 0000000 0000000 00fa74768f013beb47f76edc71e5fc51 images/test.flash
genimage-19/test/flash-types.config 0000664 0000000 0000000 00000000445 15032005261 0017463 0 ustar 00root root 0000000 0000000 flash nand-64M-512 {
pebsize = 16384
lebsize = 15360
numpebs = 4096
minimum-io-unit-size = 512
vid-header-offset = 512
sub-page-size = 512
}
flash nor-64M-128k {
pebsize = 131072
lebsize = 130944
numpebs = 256
minimum-io-unit-size = 1
vid-header-offset = 64
sub-page-size = 1
}
genimage-19/test/flash.config 0000664 0000000 0000000 00000000314 15032005261 0016314 0 ustar 00root root 0000000 0000000 include("flash-types.config")
image test.flash {
flash {
}
flashtype = "nand-64M-512"
partition part1 {
image = "part1.img"
size = 1M
}
partition part2 {
image = "part2.img"
size = 1M
}
}
genimage-19/test/flash.md5 0000664 0000000 0000000 00000000064 15032005261 0015536 0 ustar 00root root 0000000 0000000 3ac27658859853c3c49b1c8f4524e9cc images/test.flash
genimage-19/test/flash.test 0000775 0000000 0000000 00000002107 15032005261 0016033 0 ustar 00root root 0000000 0000000 #!/bin/bash
test_description="Flash Image Tests"
. "$(dirname "${0}")/test-setup.sh"
exec_test_set_prereq dd
test_expect_success dd "flash" "
setup_test_images &&
run_genimage flash.config test.flash &&
check_size 'images/test.flash' 2097152 &&
md5sum -c '${testdir}/flash.md5'
"
test_expect_success dd "flash-fill" "
setup_test_images &&
run_genimage flash-fill.config test.flash &&
check_size 'images/test.flash' 3145728 &&
md5sum -c '${testdir}/flash-fill.md5'
"
exec_test_set_prereq mkfs.jffs2
test_expect_success mkfs_jffs2 "jffs2" "
run_genimage_root jffs2.config test.jffs2 &&
md5sum -c '${testdir}/jffs2.md5'
"
exec_test_set_prereq mkfs.ubifs
test_expect_success mkfs_ubifs "ubifs" "
run_genimage_root ubifs.config test.ubifs &&
check_size_range images/test.ubifs 200000 300000
"
setup_ubi_images() {
rm -rf input &&
mkdir input &&
cp images/test.ubifs input/
}
exec_test_set_prereq ubinize
test_expect_success ubinize "ubi" "
setup_ubi_images &&
run_genimage ubi.config test.ubi &&
check_size_range images/test.ubi 550000 600000
"
test_done
# vim: syntax=sh
genimage-19/test/genimage.test 0000775 0000000 0000000 00000003546 15032005261 0016522 0 ustar 00root root 0000000 0000000 #!/bin/bash
test_description="Genimage Basic Functionality Tests"
. "$(dirname "${0}")/test-setup.sh"
setup_exec_files() {
rm -rf input &&
mkdir input &&
dd if=/dev/zero of=input/file1.img bs=512 count=7 &&
dd if=/dev/zero of=input/file2.img bs=512 count=7 &&
dd if=/dev/zero of=input/file3.img bs=512 count=7 &&
dd if=/dev/zero of=input/file4.img bs=512 count=7
}
test_expect_success "exec" "
setup_exec_files &&
run_genimage_root exec.config"
test_expect_success "exec-fail" "
setup_exec_files &&
test_must_fail run_genimage_root exec-fail.config"
"$genimage" --help | grep -q 'GENIMAGE_INCLUDEPATH' && test_set_prereq "includepath"
test_expect_success fdisk-gpt,sfdisk-gpt "includepath1" "
run_genimage include.config &&
sanitized_fdisk_sfdisk images/include.hdimage > include.fdisk &&
test_cmp '${testdir}/include-ccc.fdisk' include.fdisk
"
test_expect_success fdisk-gpt,sfdisk-gpt,includepath "includepath2" "
extra_opts='--includepath=${testdir}/include/aaa' run_genimage include.config &&
sanitized_fdisk_sfdisk images/include.hdimage > include.fdisk &&
test_cmp '${testdir}/include-aaa.fdisk' include.fdisk
"
test_expect_success fdisk-gpt,sfdisk-gpt,includepath "includepath3" "
extra_opts='--includepath=${testdir}/include/bbb:${testdir}/include/aaa' run_genimage include.config &&
sanitized_fdisk_sfdisk images/include.hdimage > include.fdisk &&
test_cmp '${testdir}/include-bbb.fdisk' include.fdisk
"
test_expect_success fdisk-gpt,sfdisk-gpt,includepath "includepath4" "
extra_opts='--includepath=.:${testdir}/include/bbb' run_genimage include.config &&
sanitized_fdisk_sfdisk images/include.hdimage > include.fdisk &&
test_cmp '${testdir}/include-ccc.fdisk' include.fdisk
"
test_expect_success !includepath "includepath5" "
extra_opts='--includepath=${testdir}/include/aaa' test_must_fail run_genimage include.config
"
test_done
# vim: syntax=sh
genimage-19/test/gpt-invalid-partition-type1.config 0000664 0000000 0000000 00000000241 15032005261 0022503 0 ustar 00root root 0000000 0000000 image gpt-partition-types-fail.img {
hdimage {
partition-table-type = "gpt"
}
partition part1 {
partition-type-uuid = "unknown-shortcut"
size = 1M
}
}
genimage-19/test/gpt-invalid-partition-type2.config 0000664 0000000 0000000 00000000265 15032005261 0022512 0 ustar 00root root 0000000 0000000 image gpt-partition-types-fail.img {
hdimage {
partition-table-type = "gpt"
}
partition part1 {
partition-type-uuid = "30f239f3-275c-4e0d-9b61-Ka385b7b80f9"
size = 1M
}
}
genimage-19/test/gpt-overlap1.config 0000664 0000000 0000000 00000000504 15032005261 0017541 0 ustar 00root root 0000000 0000000 image test.gpt-overlap1 {
hdimage {
partition-table-type = "gpt"
}
partition SPL {
# This should fail due to placing something on top of the GPT array.
offset = 1K
size = 24K
in-partition-table = false
image = "3K.img"
}
partition aaa {
in-partition-table = true
offset = 1M
image = "70K.img"
}
}
genimage-19/test/gpt-overlap2.config 0000664 0000000 0000000 00000000422 15032005261 0017541 0 ustar 00root root 0000000 0000000 image test.gpt-overlap2 {
hdimage {
partition-table-type = "gpt"
gpt-location = 32K
}
partition SPL {
offset = 1K
size = 24K
in-partition-table = false
image = "3K.img"
}
partition aaa {
in-partition-table = true
offset = 1M
image = "70K.img"
}
}
genimage-19/test/gpt-overlap3.config 0000664 0000000 0000000 00000000544 15032005261 0017547 0 ustar 00root root 0000000 0000000 image test.gpt-overlap3 {
hdimage {
partition-table-type = "gpt"
gpt-location = 30K
}
partition SPL {
offset = 1K
size = 24K
in-partition-table = false
image = "3K.img"
}
partition aaa {
# The GPT partition table array occupies 16K, so this should fail.
in-partition-table = true
offset = 32K
image = "70K.img"
size = 1M
}
}
genimage-19/test/gpt-partition-types.config 0000664 0000000 0000000 00000001530 15032005261 0021163 0 ustar 00root root 0000000 0000000 image gpt-partition-types.img {
/* note: set non-random disk-uuid and partition-uuid */
hdimage {
partition-table-type = "gpt"
disk-uuid = "b0326371-955b-42e3-ad81-ad0151d813ec"
}
partition part1 {
partition-type-uuid = "linux"
partition-uuid = "3c1e674d-4bfd-4347-a1ab-4bb5d258b361"
size = 1M
}
partition part2 {
partition-type-uuid = "U"
partition-uuid = "6a879323-b5f9-4275-9bb0-1c881048cba2"
size = 1M
}
partition part3 {
partition-type-uuid = "swap"
partition-uuid = "9ea7f2d5-ea3f-431a-a9a5-16cabbca7f1b"
size = 1M
}
partition part4 {
partition-type-uuid = "3df8f8b0-4464-4fe6-8df4-2a5e2f6c4949"
partition-uuid = "7dd9bebe-1c35-4886-a26c-2b784f172d89"
size = 1M
}
partition part5 {
partition-type-uuid = "usr-loongarch64-verity-sig"
partition-uuid = "ae7784a0-a0b7-4ef4-94c4-c3ef78b00176"
size = 1M
}
}
genimage-19/test/gpt-partition-types.fdisk 0000664 0000000 0000000 00000001442 15032005261 0021020 0 ustar 00root root 0000000 0000000 Disk identifier: B0326371-955B-42E3-AD81-AD0151D813EC
images/gpt-partition-types.img1:start=34,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=3C1E674D-4BFD-4347-A1AB-4BB5D258B361,name="part1"
images/gpt-partition-types.img2:start=2082,size=2048,type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B,uuid=6A879323-B5F9-4275-9BB0-1C881048CBA2,name="part2"
images/gpt-partition-types.img3:start=4130,size=2048,type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F,uuid=9EA7F2D5-EA3F-431A-A9A5-16CABBCA7F1B,name="part3"
images/gpt-partition-types.img4:start=6178,size=2048,type=3DF8F8B0-4464-4FE6-8DF4-2A5E2F6C4949,uuid=7DD9BEBE-1C35-4886-A26C-2B784F172D89,name="part4"
images/gpt-partition-types.img5:start=8226,size=2048,type=B024F315-D330-444C-8461-44BBDE524E99,uuid=AE7784A0-A0B7-4EF4-94C4-C3EF78B00176,name="part5"
genimage-19/test/hdimage-fail1.config 0000664 0000000 0000000 00000000244 15032005261 0017611 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = "mbr"
}
partition part1 {
/* partition-type-uuid not valid for mbr */
partition-type-uuid = "L"
}
}
genimage-19/test/hdimage-fail10.config 0000664 0000000 0000000 00000001120 15032005261 0017663 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
extended-partition = 3
}
partition primary1 {
image = "part1.img"
partition-type = 0x83
}
partition primary2 {
image = "part1.img"
partition-type = 0x83
}
partition extended1 {
image = "part1.img"
partition-type = 0x83
}
partition extended2 {
image = "part1.img"
partition-type = 0x83
}
partition primary3 {
image = "part1.img"
partition-type = 0x83
forced-primary = "yes"
}
partition primary4 {
image = "part1.img"
partition-type = 0x83
/* would be 5th primary partition */
forced-primary = "yes"
}
}
genimage-19/test/hdimage-fail11.config 0000664 0000000 0000000 00000001123 15032005261 0017667 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
extended-partition = 1
}
partition extended1 {
image = "part1.img"
partition-type = 0x83
}
partition extended2 {
image = "part1.img"
partition-type = 0x83
}
partition extended3 {
image = "part1.img"
partition-type = 0x83
}
partition extended4 {
image = "part1.img"
partition-type = 0x83
}
partition primary2 {
image = "part1.img"
partition-type = 0x83
forced-primary = "yes"
}
partition extended5 {
image = "part1.img"
partition-type = 0x83
/* extended partition would overlap the forced-primary one */
}
}
genimage-19/test/hdimage-fail2.config 0000664 0000000 0000000 00000000233 15032005261 0017610 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = "gpt"
}
partition part1 {
/* partition-type not valid for gpt */
partition-type = 0x83
}
}
genimage-19/test/hdimage-fail3.config 0000664 0000000 0000000 00000000230 15032005261 0017606 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = "hybrid"
}
partition part1 {
/* missing partition-type */
partition-type-uuid = "L"
}
}
genimage-19/test/hdimage-fail4.config 0000664 0000000 0000000 00000000241 15032005261 0017611 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = "mbr"
/* disk-uuid is only valid for gpt */
disk-uuid = "afcfea87-e41a-40e0-85ae-295c60773c7a"
}
}
genimage-19/test/hdimage-fail5.config 0000664 0000000 0000000 00000000217 15032005261 0017615 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = "gpt"
/* disk-signature is only valid for mbr */
disk-signature = 0x12345678
}
}
genimage-19/test/hdimage-fail6.config 0000664 0000000 0000000 00000000722 15032005261 0017617 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
disk-signature = 0x12345678
}
partition part1 {
offset = 1M
size = 1M
partition-type = 0x83
}
partition part2 {
offset = 2M
size = 1M
partition-type = 0x83
}
partition part3 {
offset = 3M
size = 1M
partition-type = 0x83
}
partition part4 {
/* this will overlap with the EBR */
offset = 4M
size = 1M
partition-type = 0x83
}
partition part5 {
offset = 5M
size = 1M
partition-type = 0x83
}
}
genimage-19/test/hdimage-fail7.config 0000664 0000000 0000000 00000000705 15032005261 0017621 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = "hybrid"
disk-signature = 0x12345678
}
partition part1 {
size = 1M
partition-type-uuid = L
}
partition part2 {
size = 1M
partition-type = 0x83
}
partition part3 {
size = 1M
partition-type = 0x83
}
partition part4 {
size = 1M
partition-type = 0x83
}
partition part5 {
size = 1M
/* at most 3 MBR partitions are allowed in hybrid mode */
partition-type = 0x83
}
}
genimage-19/test/hdimage-fail8.config 0000664 0000000 0000000 00000001024 15032005261 0017615 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
extended-partition = 1
}
partition part1 {
image = "part1.img"
partition-type = 0x83
forced-primary = "yes"
/* forced-primary can be only used for partitions defined after the extended partition */
}
partition part2 {
image = "part1.img"
partition-type = 0x83
}
partition part3 {
image = "part1.img"
partition-type = 0x83
}
partition part4 {
image = "part1.img"
partition-type = 0x83
}
partition part5 {
image = "part1.img"
partition-type = 0x83
}
}
genimage-19/test/hdimage-fail9.config 0000664 0000000 0000000 00000000757 15032005261 0017632 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
}
partition primary1 {
image = "part1.img"
partition-type = 0x83
}
partition primary2 {
image = "part1.img"
partition-type = 0x83
}
partition primary3 {
image = "part1.img"
partition-type = 0x83
}
partition primary4 {
image = "part1.img"
partition-type = 0x83
}
partition primary5 {
image = "part1.img"
partition-type = 0x83
/* part4 is implicitly extended -> too many primary entries */
forced-primary = "yes"
}
}
genimage-19/test/hdimage-forced-primary.config 0000664 0000000 0000000 00000001655 15032005261 0021547 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
disk-signature = 0x12345678
extended-partition = 2
}
partition part1 {
image = "part1.img"
partition-type = 0xc
bootable = "yes"
}
/*
* partition 2 will be the extended partition entry
* partitions 3-4 will be primary partitions at the end
* partition 5 is first logical partition of the extended partition
*/
partition part5-logical {
image = "part1.img"
partition-type = 0x83
}
partition part6-logical {
image = "part2.img"
partition-type = 0x83
}
partition part7-logical {
image = "part1.img"
partition-type = 0x83
}
partition part8-logical {
image = "part2.img"
partition-type = 0x83
}
partition part9-logical {
image = "part1.img"
partition-type = 0x83
}
partition part3 {
image = "part1.img"
partition-type = 0x83
forced-primary = "yes"
}
partition part4 {
image = "part2.img"
partition-type = 0x82
forced-primary = "yes"
}
}
genimage-19/test/hdimage-forced-primary.fdisk 0000664 0000000 0000000 00000000754 15032005261 0021401 0 ustar 00root root 0000000 0000000 Disk identifier: 0x12345678
images/test.hdimage1:start=2048,size=2048,type=c,bootable
images/test.hdimage2:start=4096,size=20480,type=f
images/test.hdimage3:start=24576,size=2048,type=83
images/test.hdimage4:start=26624,size=2048,type=82
images/test.hdimage5:start=6144,size=2048,type=83
images/test.hdimage6:start=10240,size=2048,type=83
images/test.hdimage7:start=14336,size=2048,type=83
images/test.hdimage8:start=18432,size=2048,type=83
images/test.hdimage9:start=22528,size=2048,type=83
genimage-19/test/hdimage-hybrid.config 0000664 0000000 0000000 00000002747 15032005261 0020110 0 ustar 00root root 0000000 0000000 image hybrid.hdimage {
hdimage {
partition-table-type = "hybrid"
fill = "true"
disk-uuid = "afcfea87-e41a-40e0-85ae-295c60773c7a"
}
partition part1 {
align = 1M
image = "part1.img"
size = 1M
partition-uuid = "92762261-e854-45c1-b4c9-fc5e752034ab"
partition-type = 0x83
}
partition part2 {
image = "part2.img"
size = 1M
partition-type-uuid = "L"
partition-uuid = "41061242-1d5a-4657-892d-fcc1fdb11a6c"
partition-type = 0x83
}
partition part3 {
image = "part1.img"
size = 1M
partition-type-uuid = "S"
partition-uuid = "954532ea-bd86-4992-a1ed-2cdb2c18581a"
partition-type = 0x83
}
partition part4 {
image = "part2.img"
size = 1M
partition-type-uuid = "F"
partition-uuid = "6d04bf47-3ddf-4a75-919b-c7bf46f2ef92"
}
partition part5 {
image = "part1.img"
size = 1M
partition-uuid = "92762261-e854-45c1-b4c9-fc5e752034ab"
}
partition part6 {
image = "part2.img"
size = 1M
partition-uuid = "c9460c06-fbc0-48ae-b4f3-3e897d3ebe71"
}
}
image mbr.hdimage {
hdimage {
partition-table-type = "mbr"
fill = "true"
}
partition part1 {
align = 1M
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part2 {
image = "part2.img"
size = 1M
partition-type = 0x83
}
partition part3 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition fake-gpt {
/* position of the GPT */
offset = 1s
/* size of the GPT header + table */
size = 33s
/* type of the protective enty */
partition-type = 0xEE
}
}
genimage-19/test/hdimage-hybrid.fdisk 0000664 0000000 0000000 00000001606 15032005261 0017734 0 ustar 00root root 0000000 0000000 Disk identifier: AFCFEA87-E41A-40E0-85AE-295C60773C7A
images/hybrid.hdimage1:start=2048,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=92762261-E854-45C1-B4C9-FC5E752034AB,name="part1"
images/hybrid.hdimage2:start=4096,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=41061242-1D5A-4657-892D-FCC1FDB11A6C,name="part2"
images/hybrid.hdimage3:start=6144,size=2048,type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F,uuid=954532EA-BD86-4992-A1ED-2CDB2C18581A,name="part3"
images/hybrid.hdimage4:start=8192,size=2048,type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7,uuid=6D04BF47-3DDF-4A75-919B-C7BF46F2EF92,name="part4"
images/hybrid.hdimage5:start=10240,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=92762261-E854-45C1-B4C9-FC5E752034AB,name="part5"
images/hybrid.hdimage6:start=12288,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=C9460C06-FBC0-48AE-B4F3-3E897D3EBE71,name="part6"
genimage-19/test/hdimage-imageoffset.config 0000664 0000000 0000000 00000000216 15032005261 0021105 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = none
align = 1
}
partition test {
image = "offset.img"
imageoffset = 4k
}
}
genimage-19/test/hdimage-nopart.config 0000664 0000000 0000000 00000000376 15032005261 0020126 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = none
align = 128
fill = true
}
size = 512
partition part1 {
image = "block1.img"
}
partition part2 {
image = "block2.img"
align = 8
}
partition part3 {
image = "block3.img"
}
}
genimage-19/test/hdimage-nopart.hexdump 0000664 0000000 0000000 00000001213 15032005261 0020322 0 ustar 00root root 0000000 0000000 00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000060 ff ff ff ff 00 00 00 00 aa aa aa aa aa aa aa aa |................|
00000070 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................|
*
00000090 aa aa aa aa aa aa aa aa aa aa 00 00 00 00 00 00 |................|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000100 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 |wwwwwwwwwwwwwwww|
*
00000140 77 77 77 77 77 77 77 77 77 77 77 00 00 00 00 00 |wwwwwwwwwww.....|
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000200
genimage-19/test/hdimage-sparse.config 0000664 0000000 0000000 00000001575 15032005261 0020122 0 ustar 00root root 0000000 0000000 image test.ext4 {
ext4 {
label = "mke2fs"
fs-timestamp = "20000101000000"
use-mke2fs = true
mke2fs-conf = "mke2fs.conf"
extraargs = "-U 12345678-1234-1234-1234-1234567890ab -E quotatype="
features = "^resize_inode,quota"
}
size = 32M
}
image test.hdimage {
hdimage {
align = 1M
fill = true
disk-signature = 0x12345678
}
partition part1 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part2 {
image = "test.ext4"
partition-type = 0x83
sparse = false
}
partition part3 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part4 {
image = "part2.img"
size = 1M
partition-type = 0x83
fill = true
sparse = false
}
partition part5 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part6 {
image = "part2.img"
size = 1M
partition-type = 0x83
fill = true
sparse = false
}
}
genimage-19/test/hdimage.config 0000664 0000000 0000000 00000002236 15032005261 0016622 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
fill = true
disk-signature = 0x12345678
}
partition part1 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part2 {
image = "part3.img"
size = 1M
partition-type = 0x83
}
partition part3 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part4 {
image = "part2.img"
size = 1M
partition-type = 0x83
}
partition part5 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part6 {
image = "part2.img"
size = 1M
partition-type = 0x83
}
}
image test.hdimage-2 {
hdimage {
align = 1M
disk-signature = 0x12345678
extended-partition = 2
}
partition part1 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part2 {
image = "part2.img"
size = 1M
partition-type = 0x83
}
partition part3 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part4 {
image = "part2.img"
size = 1M
partition-type = 0x83
}
partition part5 {
image = "part1.img"
size = 1M
partition-type = 0x83
}
partition part6 {
image = "part2.img"
autoresize = true
partition-type = 0x83
}
size = 12M
}
genimage-19/test/hdimage.fdisk 0000664 0000000 0000000 00000000575 15032005261 0016461 0 ustar 00root root 0000000 0000000 Disk identifier: 0x12345678
images/test.hdimage1:start=2048,size=2048,type=83
images/test.hdimage2:start=4096,size=2048,type=83
images/test.hdimage3:start=6144,size=2048,type=83
images/test.hdimage4:start=8192,size=12288,type=f
images/test.hdimage5:start=10240,size=2048,type=83
images/test.hdimage6:start=14336,size=2048,type=83
images/test.hdimage7:start=18432,size=2048,type=83
genimage-19/test/hdimage.fdisk-2 0000664 0000000 0000000 00000000623 15032005261 0016612 0 ustar 00root root 0000000 0000000 Disk identifier: 0x12345678
images/test.hdimage-2p1:start=2048,size=2048,type=83
images/test.hdimage-2p2:start=4096,size=20480,type=f
images/test.hdimage-2p5:start=6144,size=2048,type=83
images/test.hdimage-2p6:start=10240,size=2048,type=83
images/test.hdimage-2p7:start=14336,size=2048,type=83
images/test.hdimage-2p8:start=18432,size=2048,type=83
images/test.hdimage-2p9:start=22528,size=2048,type=83
genimage-19/test/hdimage.test 0000775 0000000 0000000 00000015320 15032005261 0016335 0 ustar 00root root 0000000 0000000 #!/bin/bash
test_description="hdimage Image Tests"
. "$(dirname "${0}")/test-setup.sh"
get_disk_usage() {
local file="${1}"
if [ ! -f "${file}" ]; then
echo "Failed to check file disk usage: '${file}' does not exist!"
return 1
fi
set -- $(du -B 1 "${file}")
usage="${1}"
}
check_disk_usage_range() {
local usage
get_disk_usage "${1}" || return
if [ "${usage}" -lt "${2}" -o "${usage}" -gt "${3}" ]; then
echo "Incorrect file disk usage for '${1}': expected min: ${2} max: ${3} found: ${usage}"
return 1
fi
}
exec_test_set_prereq fdisk
exec_test_set_prereq sfdisk
test_expect_success fdisk,sfdisk "hdimage" "
setup_test_images &&
run_genimage hdimage.config test.hdimage &&
check_size images/test.hdimage 10485760 &&
sfdisk_validate images/test.hdimage &&
check_disk_usage_range images/test.hdimage 40960 57344 &&
sanitized_fdisk_sfdisk images/test.hdimage > hdimage.fdisk &&
test_cmp '${testdir}/hdimage.fdisk' hdimage.fdisk &&
check_size images/test.hdimage-2 11539968 &&
sfdisk_validate images/test.hdimage-2 &&
check_disk_usage_range images/test.hdimage-2 61290 65536 &&
sanitized_fdisk_sfdisk images/test.hdimage-2 > hdimage.fdisk-2 &&
test_cmp '${testdir}/hdimage.fdisk-2' hdimage.fdisk-2
"
test_expect_success "hdimage2" "
setup_test_images &&
test_must_fail run_genimage hdimage2.config test.hdimage
"
test_expect_success fdisk-gpt,sfdisk-gpt "hdimage4" "
setup_test_images &&
run_genimage hdimage4.config test.hdimage &&
check_size images/test.hdimage 7360512 &&
sfdisk_validate images/test.hdimage &&
sanitized_fdisk_sfdisk images/test.hdimage > hdimage4.fdisk &&
test_cmp '${testdir}/hdimage4.fdisk' hdimage4.fdisk
"
test_expect_success fdisk-gpt,sfdisk-gpt "hdimage5" "
setup_test_images &&
run_genimage hdimage5.config test.hdimage &&
check_size images/test.hdimage 7360512 &&
sanitized_fdisk_sfdisk images/test.hdimage > hdimage5.fdisk &&
test_cmp '${testdir}/hdimage5.fdisk' hdimage5.fdisk
"
test_expect_success fdisk,sfdisk "hdimage6" "
setup_test_images &&
run_genimage hdimage6.config test.hdimage &&
check_size images/test.hdimage 28082176 &&
sanitized_fdisk_sfdisk images/test.hdimage > hdimage6.fdisk &&
test_cmp '${testdir}/hdimage6.fdisk' hdimage6.fdisk
"
test_expect_success fdisk-gpt,sfdisk-gpt "hdimage7" "
setup_test_images &&
run_genimage hdimage7.config &&
sfdisk_validate images/test.hdimage &&
sanitized_fdisk_sfdisk images/test.hdimage > hdimage7.fdisk &&
test_cmp '${testdir}/hdimage7.fdisk' hdimage7.fdisk
"
exec_test_set_prereq hexdump
test_expect_success fdisk-gpt,sfdisk-gpt,hexdump "hdimage-hybrid" "
setup_test_images &&
run_genimage hdimage-hybrid.config &&
sfdisk_validate images/hybrid.hdimage &&
sanitized_fdisk_sfdisk images/hybrid.hdimage > hdimage-hybrid.fdisk &&
test_cmp '${testdir}/hdimage-hybrid.fdisk' hdimage-hybrid.fdisk &&
dd if=images/hybrid.hdimage count=1 | hexdump -C > hybrid.sector0 &&
dd if=images/mbr.hdimage count=1 | hexdump -C > mbr.sector0 &&
test_cmp hybrid.sector0 mbr.sector0
"
test_expect_success "hdimage syntax" "
setup_test_images &&
test_must_fail run_genimage hdimage-fail1.config &&
test_must_fail run_genimage hdimage-fail2.config &&
test_must_fail run_genimage hdimage-fail3.config &&
test_must_fail run_genimage hdimage-fail4.config &&
test_must_fail run_genimage hdimage-fail5.config &&
test_must_fail run_genimage hdimage-fail6.config &&
test_must_fail run_genimage hdimage-fail7.config &&
test_must_fail run_genimage hdimage-fail8.config &&
test_must_fail run_genimage hdimage-fail9.config &&
test_must_fail run_genimage hdimage-fail10.config &&
test_must_fail run_genimage hdimage-fail11.config
"
setup_gpt_files() {
rm -rf input &&
mkdir input &&
truncate -s 3k input/3K.img &&
truncate -s 70k input/70K.img
}
test_expect_success "gpt-overlap1" "
setup_gpt_files &&
test_must_fail run_genimage gpt-overlap1.config"
test_expect_success "gpt-overlap2" "
setup_gpt_files &&
run_genimage gpt-overlap2.config"
test_expect_success "gpt-overlap3" "
setup_gpt_files &&
test_must_fail run_genimage gpt-overlap3.config"
test_expect_success fdisk,sfdisk "gpt-partition-types" "
run_genimage gpt-partition-types.config &&
sfdisk_validate images/gpt-partition-types.img &&
sanitized_fdisk_sfdisk images/gpt-partition-types.img > gpt-partition-types.fdisk &&
test_cmp '${testdir}/gpt-partition-types.fdisk' gpt-partition-types.fdisk"
test_expect_success "gpt-invalid-partition-types" "
test_must_fail run_genimage gpt-invalid-partition-type1.config &&
test_must_fail run_genimage gpt-invalid-partition-type2.config"
# A bootloader image with a don't-care region extending over MBR
# table, GPT header and (usual) placement of GPT array.
test_expect_success "bootloader-hole1" "
setup_gpt_files &&
run_genimage hole.config"
# Oops, if we move the GPT array we're no longer covered by the hole.
test_expect_success "bootloader-hole2" "
setup_gpt_files &&
GPT_LOCATION=64K test_must_fail run_genimage hole.config"
# But it's ok if the array is moved beyond the bootloader.
test_expect_success "bootloader-hole3" "
setup_gpt_files &&
GPT_LOCATION=70K run_genimage hole.config"
# If the 70K bootloader starts at 64K, it will overlap a partition at 129K.
test_expect_success "bootloader-hole4" "
setup_gpt_files &&
OFFSET=64K test_must_fail run_genimage hole.config"
# But if it starts at 128K, its hole will cover the small 3K partition.
test_expect_success "bootloader-hole5" "
setup_gpt_files &&
OFFSET=128K run_genimage hole.config"
test_expect_success hexdump "hdimage no-partition" "
dd if=/dev/zero bs=1 count=100 | tr '\000' '\377' > input/block1.img &&
dd if=/dev/zero bs=1 count=50 | tr '\000' '\252' > input/block2.img &&
dd if=/dev/zero bs=1 count=75 | tr '\000' '\167' > input/block3.img &&
run_genimage hdimage-nopart.config &&
hexdump -C images/test.hdimage > 'hdimage-nopart.hexdump' &&
test_cmp 'hdimage-nopart.hexdump' '${testdir}/hdimage-nopart.hexdump'
"
test_expect_success sfdisk "hdimage forced-primary" "
setup_test_images &&
run_genimage hdimage-forced-primary.config &&
sfdisk_validate images/test.hdimage &&
sanitized_fdisk_sfdisk images/test.hdimage > hdimage.fdisk &&
test_cmp '${testdir}/hdimage-forced-primary.fdisk' hdimage.fdisk
"
test_expect_success fdisk,sfdisk,mke2fs "hdimage sparse" "
setup_test_images &&
run_genimage_root hdimage-sparse.config test.hdimage &&
check_size images/test.hdimage 42991616 &&
sfdisk_validate images/test.hdimage &&
check_disk_usage_range images/test.hdimage 34000000 37000000
"
test_expect_success "hdimage imageoffset" "
echo '0123456789abcdef' | dd of=input/offset.img seek=4 bs=1k &&
run_genimage hdimage-imageoffset.config test.hdimage &&
echo '0123456789abcdef' > images/test.hdimage.expect &&
test_cmp images/test.hdimage.expect images/test.hdimage
"
test_done
# vim: syntax=sh
genimage-19/test/hdimage2.config 0000664 0000000 0000000 00000000240 15032005261 0016675 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
disk-signature = 0x12345678
}
partition part1 {
image = "part2.img"
size = 5k
partition-type = 0x83
}
}
genimage-19/test/hdimage4.config 0000664 0000000 0000000 00000002017 15032005261 0016703 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
partition-table-type = "gpt"
fill = "true"
disk-uuid = "afcfea87-e41a-40e0-85ae-295c60773c7a"
}
partition part1 {
image = "part1.img"
size = 1M
partition-uuid = "92762261-e854-45c1-b4c9-fc5e752034ab"
}
partition part2 {
image = "part2.img"
size = 1M
partition-type-uuid = "L"
partition-uuid = "41061242-1d5a-4657-892d-fcc1fdb11a6c"
}
partition part3 {
image = "part1.img"
size = 1M
partition-type-uuid = "S"
partition-uuid = "954532ea-bd86-4992-a1ed-2cdb2c18581a"
}
partition part4 {
image = "part2.img"
size = 1M
partition-type-uuid = "F"
partition-uuid = "6d04bf47-3ddf-4a75-919b-c7bf46f2ef92"
}
partition part5 {
image = "part1.img"
size = 1M
partition-type-uuid = "forty-two"
partition-uuid = "92762261-e854-45c1-b4c9-fc5e752034ab"
}
partition part6 {
image = "part2.img"
size = 1M
partition-uuid = "c9460c06-fbc0-48ae-b4f3-3e897d3ebe71"
}
}
config {
gpt-shortcuts {
forty-two = "2a422a42-2a42-2a42-2a42-2a422a422a42"
}
}
genimage-19/test/hdimage4.fdisk 0000664 0000000 0000000 00000001572 15032005261 0016543 0 ustar 00root root 0000000 0000000 Disk identifier: AFCFEA87-E41A-40E0-85AE-295C60773C7A
images/test.hdimage1:start=2048,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=92762261-E854-45C1-B4C9-FC5E752034AB,name="part1"
images/test.hdimage2:start=4096,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=41061242-1D5A-4657-892D-FCC1FDB11A6C,name="part2"
images/test.hdimage3:start=6144,size=2048,type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F,uuid=954532EA-BD86-4992-A1ED-2CDB2C18581A,name="part3"
images/test.hdimage4:start=8192,size=2048,type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7,uuid=6D04BF47-3DDF-4A75-919B-C7BF46F2EF92,name="part4"
images/test.hdimage5:start=10240,size=2048,type=2A422A42-2A42-2A42-2A42-2A422A422A42,uuid=92762261-E854-45C1-B4C9-FC5E752034AB,name="part5"
images/test.hdimage6:start=12288,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=C9460C06-FBC0-48AE-B4F3-3E897D3EBE71,name="part6"
genimage-19/test/hdimage5.config 0000664 0000000 0000000 00000001657 15032005261 0016715 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
align = 1M
partition-table-type = "gpt"
gpt-no-backup = "true"
fill = "true"
disk-uuid = "afcfea87-e41a-40e0-85ae-295c60773c7a"
}
partition part1 {
image = "part1.img"
size = 1M
partition-uuid = "92762261-e854-45c1-b4c9-fc5e752034ab"
}
partition part2 {
image = "part2.img"
size = 1M
partition-type-uuid = "L"
partition-uuid = "41061242-1d5a-4657-892d-fcc1fdb11a6c"
}
partition part3 {
image = "part1.img"
size = 1M
partition-type-uuid = "S"
partition-uuid = "954532ea-bd86-4992-a1ed-2cdb2c18581a"
}
partition part4 {
image = "part2.img"
size = 1M
partition-type-uuid = "F"
partition-uuid = "6d04bf47-3ddf-4a75-919b-c7bf46f2ef92"
}
partition part5 {
image = "part1.img"
size = 1M
partition-uuid = "92762261-e854-45c1-b4c9-fc5e752034ab"
}
partition part6 {
image = "part2.img"
size = 1M
partition-uuid = "c9460c06-fbc0-48ae-b4f3-3e897d3ebe71"
}
}
genimage-19/test/hdimage5.fdisk 0000664 0000000 0000000 00000001572 15032005261 0016544 0 ustar 00root root 0000000 0000000 Disk identifier: AFCFEA87-E41A-40E0-85AE-295C60773C7A
images/test.hdimage1:start=2048,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=92762261-E854-45C1-B4C9-FC5E752034AB,name="part1"
images/test.hdimage2:start=4096,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=41061242-1D5A-4657-892D-FCC1FDB11A6C,name="part2"
images/test.hdimage3:start=6144,size=2048,type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F,uuid=954532EA-BD86-4992-A1ED-2CDB2C18581A,name="part3"
images/test.hdimage4:start=8192,size=2048,type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7,uuid=6D04BF47-3DDF-4A75-919B-C7BF46F2EF92,name="part4"
images/test.hdimage5:start=10240,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=92762261-E854-45C1-B4C9-FC5E752034AB,name="part5"
images/test.hdimage6:start=12288,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=C9460C06-FBC0-48AE-B4F3-3E897D3EBE71,name="part6"
genimage-19/test/hdimage6.config 0000664 0000000 0000000 00000000702 15032005261 0016704 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
extended-partition = 3
}
partition part1 {
offset = 128K
size = 256K
partition-type = 0x83
}
partition part2 {
size = 3072K
partition-type = 0x83
}
partition part3 {
offset = 3686400
size = 8126464
partition-type = 0x83
}
partition part4 {
offset = 11821056
size = 16252928
partition-type = 0x83
}
partition part5 {
offset = 28082176
size = 16252928
partition-type = 0x83
}
}
genimage-19/test/hdimage6.fdisk 0000664 0000000 0000000 00000000512 15032005261 0016536 0 ustar 00root root 0000000 0000000 Disk identifier: 0x00000000
images/test.hdimage1:start=256,size=512,type=83
images/test.hdimage2:start=768,size=6144,type=83
images/test.hdimage3:start=7199,size=79393,type=f
images/test.hdimage5:start=7200,size=15872,type=83
images/test.hdimage6:start=23088,size=31744,type=83
images/test.hdimage7:start=54848,size=31744,type=83
genimage-19/test/hdimage7.config 0000664 0000000 0000000 00000003277 15032005261 0016717 0 ustar 00root root 0000000 0000000 image test.hdimage {
hdimage {
partition-table-type = "gpt"
gpt-location = 768K
disk-uuid = "afcfea87-e41a-40e0-85ae-295c60773c7a"
}
partition rescue {
image = "part1.img"
offset = 2M
size = 1M
partition-uuid = "9f60b7f0-f4c8-42d4-8469-be6c19904994"
}
partition rootfs-A {
image = "part2.img"
align = 2M
size = 8M
partition-type-uuid = "L"
partition-uuid = "0cfa71d4-3388-4f08-8fa0-f66e46ec5a0e"
}
partition rootfs-B {
image = "part2.img"
align = 2M
size = 8M
partition-type-uuid = "L"
partition-uuid = "b9cc42b2-d030-4eca-9922-5f88e32c94bc"
}
partition reserved {
image = "part1.img"
size = 128K
partition-uuid = "cb597eaf-5662-44d9-8127-dc5e8c1b830d"
}
partition sys {
image = "part1.img"
size = 4M
partition-type-uuid = "L"
partition-uuid = "c9d69b9a-a561-42ef-88df-2ba25328e6ef"
}
partition data {
image = "part1.img"
size = 4M
partition-uuid = "b7104ed8-6ac9-4f80-96e2-9d57ff5f3453"
}
partition bootloader {
image = "part2.img"
size = 1M
offset = 1M
partition-uuid = "de9980f1-0449-4e83-84bd-98e4b1ca3fe3"
}
partition env-1 {
image = "part1.img"
offset = 800K
size = 16K
partition-uuid = "eb3b107b-ae9d-4c6b-994a-ec412d36959b"
}
partition env-2 {
image = "part1.img"
offset = 832K
size = 16K
partition-uuid = "6e7c8caa-c119-43b9-8031-fcdfa34c3fae"
}
partition ucode {
image = "part1.img"
offset = 960K
size = 64K
partition-uuid = "b1a7539f-8e86-4a31-94c6-090c08f5a3d3"
}
partition SPL {
image = "part1.img"
in-partition-table = false
offset = 1K
size = 512K
}
}
genimage-19/test/hdimage7.fdisk 0000664 0000000 0000000 00000002661 15032005261 0016546 0 ustar 00root root 0000000 0000000 Disk identifier: AFCFEA87-E41A-40E0-85AE-295C60773C7A
images/test.hdimage1:start=4096,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=9F60B7F0-F4C8-42D4-8469-BE6C19904994,name="rescue"
images/test.hdimage2:start=8192,size=16384,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=0CFA71D4-3388-4F08-8FA0-F66E46EC5A0E,name="rootfs-A"
images/test.hdimage3:start=24576,size=16384,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=B9CC42B2-D030-4ECA-9922-5F88E32C94BC,name="rootfs-B"
images/test.hdimage4:start=40960,size=256,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=CB597EAF-5662-44D9-8127-DC5E8C1B830D,name="reserved"
images/test.hdimage5:start=41216,size=8192,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=C9D69B9A-A561-42EF-88DF-2BA25328E6EF,name="sys"
images/test.hdimage6:start=49408,size=8192,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=B7104ED8-6AC9-4F80-96E2-9D57FF5F3453,name="data"
images/test.hdimage7:start=2048,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=DE9980F1-0449-4E83-84BD-98E4B1CA3FE3,name="bootloader"
images/test.hdimage8:start=1600,size=32,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=EB3B107B-AE9D-4C6B-994A-EC412D36959B,name="env-1"
images/test.hdimage9:start=1664,size=32,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=6E7C8CAA-C119-43B9-8031-FCDFA34C3FAE,name="env-2"
images/test.hdimage10:start=1920,size=128,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=B1A7539F-8E86-4A31-94C6-090C08F5A3D3,name="ucode"
genimage-19/test/hole.config 0000664 0000000 0000000 00000000470 15032005261 0016151 0 ustar 00root root 0000000 0000000 image test.hole {
hdimage {
partition-table-type = "gpt"
gpt-location = ${GPT_LOCATION:-1K}
}
partition bootloader {
in-partition-table = false
offset = ${OFFSET:-0}
image = "70K.img"
}
partition foo {
offset = 129K
image = "3K.img"
}
}
image 70K.img {
file {
holes = "(440; 33K)"
}
}
genimage-19/test/include-aaa.fdisk 0000664 0000000 0000000 00000000300 15032005261 0017210 0 ustar 00root root 0000000 0000000 Disk identifier: 6A921DBB-823D-44C4-8EDC-ECB038E6D743
images/include.hdimage1:start=34,size=2048,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=59DA602D-C2EA-4F18-818F-CF7947BAD0CA,name="aaa"
genimage-19/test/include-bbb.fdisk 0000664 0000000 0000000 00000000300 15032005261 0017213 0 ustar 00root root 0000000 0000000 Disk identifier: 6A921DBB-823D-44C4-8EDC-ECB038E6D743
images/include.hdimage1:start=34,size=4096,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=284635E9-6B62-41CA-A02A-357C01517279,name="bbb"
genimage-19/test/include-ccc.fdisk 0000664 0000000 0000000 00000000300 15032005261 0017216 0 ustar 00root root 0000000 0000000 Disk identifier: 6A921DBB-823D-44C4-8EDC-ECB038E6D743
images/include.hdimage1:start=34,size=6144,type=0FC63DAF-8483-4772-8E79-3D69D8477DE4,uuid=088813B5-7028-4540-99DA-B10015FD07DA,name="ccc"
genimage-19/test/include-test.config 0000664 0000000 0000000 00000000161 15032005261 0017617 0 ustar 00root root 0000000 0000000 partition ccc {
size = 3M
partition-type-uuid = "L"
partition-uuid = "088813b5-7028-4540-99da-b10015fd07da"
}
genimage-19/test/include.config 0000664 0000000 0000000 00000000234 15032005261 0016643 0 ustar 00root root 0000000 0000000 image include.hdimage {
hdimage {
partition-table-type = "gpt"
disk-uuid = "6a921dbb-823d-44c4-8edc-ecb038e6d743"
}
include("include-test.config")
}
genimage-19/test/include/ 0000775 0000000 0000000 00000000000 15032005261 0015455 5 ustar 00root root 0000000 0000000 genimage-19/test/include/aaa/ 0000775 0000000 0000000 00000000000 15032005261 0016177 5 ustar 00root root 0000000 0000000 genimage-19/test/include/aaa/include-test.config 0000664 0000000 0000000 00000000161 15032005261 0021764 0 ustar 00root root 0000000 0000000 partition aaa {
size = 1M
partition-type-uuid = "L"
partition-uuid = "59da602d-c2ea-4f18-818f-cf7947bad0ca"
}
genimage-19/test/include/bbb/ 0000775 0000000 0000000 00000000000 15032005261 0016202 5 ustar 00root root 0000000 0000000 genimage-19/test/include/bbb/include-test.config 0000664 0000000 0000000 00000000161 15032005261 0021767 0 ustar 00root root 0000000 0000000 partition bbb {
size = 2M
partition-type-uuid = "L"
partition-uuid = "284635e9-6b62-41ca-a02a-357c01517279"
}
genimage-19/test/iso.config 0000664 0000000 0000000 00000000066 15032005261 0016015 0 ustar 00root root 0000000 0000000 image test.iso {
iso {
volume-id = "iso-test"
}
}
genimage-19/test/jffs2.config 0000664 0000000 0000000 00000000147 15032005261 0016235 0 ustar 00root root 0000000 0000000 include("flash-types.config")
image test.jffs2 {
jffs2 {
}
flashtype = "nor-64M-128k"
size = 4M
}
genimage-19/test/jffs2.md5 0000664 0000000 0000000 00000000064 15032005261 0015453 0 ustar 00root root 0000000 0000000 4c37f72de7a902286f0cfcbf13b4fde8 images/test.jffs2
genimage-19/test/mdraid.config 0000664 0000000 0000000 00000000415 15032005261 0016461 0 ustar 00root root 0000000 0000000 image test.mdraid-a {
mdraid {
level = 1
devices = 2
timestamp = 638022222
raid-uuid = "de9980f1-0449-4e83-84bd-98e4b1ca3fe3"
disk-uuid = "eb3b107b-ae9d-4c6b-994a-ec412d36959b"
}
size = 5M
}
image test.mdraid-b {
mdraid {
parent = "test.mdraid-a"
}
}
genimage-19/test/misc.test 0000775 0000000 0000000 00000011433 15032005261 0015673 0 ustar 00root root 0000000 0000000 #!/bin/bash
test_description="Misc Image Tests"
. "$(dirname "${0}")/test-setup.sh"
exec_test_set_prereq dd
exec_test_set_prereq diff
exec_test_set_prereq qemu-img
test_expect_success dd,diff,qemu-img "qemu" "
setup_test_images &&
run_genimage qemu.config test.qcow &&
qemu-img check images/test.qcow &&
zcat '${testdir}/qemu.qcow.gz' > qemu.qcow &&
qemu-img compare images/test.qcow qemu.qcow
"
setup_fit_its() {
setup_test_images &&
cp ${testdir}/fit.its input/
}
exec_test_set_prereq mkimage
exec_test_set_prereq dtc
test_expect_success mkimage,dtc "fit" "
setup_fit_its &&
run_genimage fit.config test.fit
"
setup_rauc() {
rm -rf input &&
mkdir input &&
cp -r "${testdir}"/rauc-openssl-ca input/ &&
echo "test" > input/rauc.content &&
echo "xtest2" > input/rauc2.content
}
version_lt() {
first="$(printf "${1}\n${2}" | sort -V | head -n1)"
test "${first}" == "${1}" && test "${1}" != "${2}"
}
rauc_cmp() {
if version_lt "${rauc_version}" "1.6"; then
test_cmp "${testdir}/${1}.raucb.info.1" "${1}.raucb.info"
elif version_lt "${rauc_version}" "1.9"; then
test_cmp "${testdir}/${1}.raucb.info.2" "${1}.raucb.info"
elif version_lt "${rauc_version}" "1.10"; then
test_cmp "${testdir}/${1}.raucb.info.3" "${1}.raucb.info"
else
TEST_CMP="diff -wu" test_cmp "${testdir}/${1}.raucb.info.4" "${1}.raucb.info"
fi
}
exec_test_set_prereq rauc
test_expect_success rauc "rauc" "
rauc_version="$(rauc --version | sed 's/rauc //')"
setup_rauc &&
run_genimage rauc.config test.raucb &&
rauc info \
--keyring input/rauc-openssl-ca/ca.cert.pem \
--cert input/rauc-openssl-ca/ca.cert.pem \
images/test.raucb | grep -v cms_get_enveloped_type \
| sed -e 's;O = Test Org, CN = ;/O=Test Org/CN=;' \
-e '/Bundle Format:[ \t]*plain$/d' \
> test.raucb.info &&
rauc_cmp test
rauc info \
--keyring input/rauc-openssl-ca/ca.cert.pem \
--cert input/rauc-openssl-ca/ca.cert.pem \
images/test2.raucb | grep -v cms_get_enveloped_type \
| sed -e 's;O = Test Org, CN = ;/O=Test Org/CN=;' \
-e '/Bundle Format:[ \t]*plain$/d' \
> test2.raucb.info &&
rauc_cmp test2
"
exec_test_set_prereq simg2img
test_expect_success simg2img "android-sparse" "
setup_test_images &&
# make sure there is a 4*32k hole at the end
i=16
truncate --size=\$[i*(i+1)*i*i*512+32768*4] input/interleaved
for i in \`seq 16\`; do
dd if=/dev/urandom of=input/interleaved conv=notrunc seek=\$[i*i] count=\$[i] bs=\$[i*i*512] || break
done &&
dd if=/dev/urandom of=input/not-aligned count=9 bs=1024
run_genimage sparse.config &&
# simg2img will expand the partial block
truncate --size=12k input/not-aligned
md5sum images/test.hdimage input/interleaved input/not-aligned > md5sum &&
rm images/test.hdimage input/interleaved input/not-aligned &&
check_size_range images/interleaved.sparse 9732408 9732580 &&
simg2img images/test.sparse images/test.hdimage &&
simg2img images/interleaved.sparse input/interleaved &&
simg2img images/not-aligned.sparse input/not-aligned &&
md5sum -c md5sum &&
run_genimage sparse-fill.config &&
# simg2img will expand the partial block
truncate --size=12k input/not-aligned
md5sum images/test.hdimage input/interleaved input/not-aligned > md5sum &&
rm images/test.hdimage input/interleaved input/not-aligned &&
check_size_range images/interleaved.sparse 9732408 9732580 &&
simg2img images/test.sparse images/test.hdimage &&
simg2img images/interleaved.sparse input/interleaved &&
simg2img images/not-aligned.sparse input/not-aligned &&
md5sum -c md5sum
"
exec_test_set_prereq fiptool
test_expect_success fiptool "fip" "
setup_test_images &&
run_genimage fip.config test.fip &&
check_size_range images/test.fip 12804 13056 &&
fiptool info images/test.fip
"
test_expect_success fiptool "fip-size" "
setup_test_images &&
test_must_fail run_genimage fip-size.config test.fip
"
exec_test_set_prereq mdadm
test_expect_success mdadm "mdraid" "
run_genimage_root mdraid.config test.mdraid-a &&
LANG=C mdadm --examine images/test.mdraid-a | tee images/test.mdraid-a.txt &&
LANG=C mdadm --examine images/test.mdraid-b | tee images/test.mdraid-b.txt &&
grep 'Checksum.*correct$' images/test.mdraid-a.txt &&
grep 'State.*active$' images/test.mdraid-a.txt &&
grep 'Internal Bitmap.*sectors' images/test.mdraid-a.txt &&
grep 'Bad Block Log.*entries available' images/test.mdraid-a.txt &&
grep -Ev '(Device UUID|Checksum|Device Role) :' images/test.mdraid-a.txt | tail -n +2 > images/test.mdraid-a.arr.txt &&
grep -Ev '(Device UUID|Checksum|Device Role) :' images/test.mdraid-b.txt | tail -n +2 > images/test.mdraid-b.arr.txt &&
diff images/test.mdraid-a.arr.txt images/test.mdraid-b.arr.txt
"
test_expect_success "custom" "
run_genimage custom.config test.custom &&
echo 'Hello genimage!' > images/test.custom.expect &&
test_cmp images/test.custom.expect images/test.custom
"
test_done
# vim: syntax=sh
genimage-19/test/mke2fs.0.dump 0000664 0000000 0000000 00000006165 15032005261 0016256 0 ustar 00root root 0000000 0000000 Filesystem volume name: mke2fs
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr dir_index filetype extent 64bit flex_bg sparse_super dir_nlink extra_isize quota metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 8192
Block count: 32768
Reserved block count: 1638
Free blocks: 26580
Free inodes: 8141
First block: 1
Block size: 1024
Fragment size: 1024
Group descriptor size: 64
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 2048
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: -1
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Lifetime writes: 107 kB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 32
Desired extra isize: 32
Journal inode: 8
Default directory hash: half_md4
Journal backup: inode blocks
Checksum type: crc32c
Journal features: (none)
Journal size: 4096k
Journal length: 4096
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 1-8192) csum 0xd0bb [ITABLE_ZEROED]
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2), csum 0xde29f1cb
Inode bitmap at 7 (+6), csum 0xb1052088
Inode table at 11-522 (+10)
6105 free blocks, 1997 free inodes, 18 directories, 1997 unused inodes
Free blocks: 2088-8192
Free inodes: 52-2048
Group 1: (Blocks 8193-16384) csum 0x8fde [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
Backup superblock at 8193, Group descriptors at 8194-8194
Block bitmap at 4 (bg #0 + 3), csum 0x00000000
Inode bitmap at 8 (bg #0 + 7), csum 0x00000000
Inode table at 523-1034 (bg #0 + 522)
8190 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 8195-16384
Free inodes: 2049-4096
Group 2: (Blocks 16385-24576) csum 0x720f [INODE_UNINIT, ITABLE_ZEROED]
Block bitmap at 5 (bg #0 + 4), csum 0x040008b2
Inode bitmap at 9 (bg #0 + 8), csum 0x00000000
Inode table at 1035-1546 (bg #0 + 1034)
4096 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 20481-24576
Free inodes: 4097-6144
Group 3: (Blocks 24577-32767) csum 0xd0be [INODE_UNINIT, ITABLE_ZEROED]
Backup superblock at 24577, Group descriptors at 24578-24578
Block bitmap at 6 (bg #0 + 5), csum 0x4327ef1c
Inode bitmap at 10 (bg #0 + 9), csum 0x00000000
Inode table at 1547-2058 (bg #0 + 1546)
8189 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 24579-32767
Free inodes: 6145-8192
genimage-19/test/mke2fs.1.dump 0000664 0000000 0000000 00000006317 15032005261 0016256 0 ustar 00root root 0000000 0000000 Filesystem volume name: mke2fs
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr dir_index filetype extent 64bit flex_bg sparse_super dir_nlink extra_isize quota metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 8192
Block count: 32768
Reserved block count: 1638
Overhead clusters: 6159
Free blocks: 26580
Free inodes: 8141
First block: 1
Block size: 1024
Fragment size: 1024
Group descriptor size: 64
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 2048
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: -1
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Lifetime writes: 107 kB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 32
Desired extra isize: 32
Journal inode: 8
Default directory hash: half_md4
Journal backup: inode blocks
Checksum type: crc32c
Journal features: (none)
Total journal size: 4096k
Total journal blocks: 4096
Max transaction length: 4096
Fast commit length: 0
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 1-8192) csum 0xd0bb [ITABLE_ZEROED]
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2), csum 0xde29f1cb
Inode bitmap at 7 (+6), csum 0xb1052088
Inode table at 11-522 (+10)
6105 free blocks, 1997 free inodes, 18 directories, 1997 unused inodes
Free blocks: 2088-8192
Free inodes: 52-2048
Group 1: (Blocks 8193-16384) csum 0x8fde [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
Backup superblock at 8193, Group descriptors at 8194-8194
Block bitmap at 4 (bg #0 + 3), csum 0x00000000
Inode bitmap at 8 (bg #0 + 7), csum 0x00000000
Inode table at 523-1034 (bg #0 + 522)
8190 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 8195-16384
Free inodes: 2049-4096
Group 2: (Blocks 16385-24576) csum 0x720f [INODE_UNINIT, ITABLE_ZEROED]
Block bitmap at 5 (bg #0 + 4), csum 0x040008b2
Inode bitmap at 9 (bg #0 + 8), csum 0x00000000
Inode table at 1035-1546 (bg #0 + 1034)
4096 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 20481-24576
Free inodes: 4097-6144
Group 3: (Blocks 24577-32767) csum 0xd0be [INODE_UNINIT, ITABLE_ZEROED]
Backup superblock at 24577, Group descriptors at 24578-24578
Block bitmap at 6 (bg #0 + 5), csum 0x4327ef1c
Inode bitmap at 10 (bg #0 + 9), csum 0x00000000
Inode table at 1547-2058 (bg #0 + 1546)
8189 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 24579-32767
Free inodes: 6145-8192
genimage-19/test/mke2fs.2.dump 0000664 0000000 0000000 00000006317 15032005261 0016257 0 ustar 00root root 0000000 0000000 Filesystem volume name: mke2fs
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr dir_index filetype extent 64bit flex_bg sparse_super dir_nlink extra_isize quota metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 8192
Block count: 32768
Reserved block count: 1638
Overhead clusters: 6159
Free blocks: 26580
Free inodes: 8141
First block: 1
Block size: 1024
Fragment size: 1024
Group descriptor size: 64
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 2048
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: -1
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Lifetime writes: 107 kB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 32
Desired extra isize: 32
Journal inode: 8
Default directory hash: half_md4
Journal backup: inode blocks
Checksum type: crc32c
Journal features: (none)
Total journal size: 4096k
Total journal blocks: 4096
Max transaction length: 4096
Fast commit length: 0
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 1-8192) csum 0xd0bb [ITABLE_ZEROED]
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2), csum 0xde29f1cb
Inode bitmap at 7 (+6), csum 0xb1052088
Inode table at 11-522 (+10)
6105 free blocks, 1997 free inodes, 18 directories, 1997 unused inodes
Free blocks: 2088-8192
Free inodes: 52-2048
Group 1: (Blocks 8193-16384) csum 0x8fde [INODE_UNINIT, BLOCK_UNINIT, ITABLE_ZEROED]
Backup superblock at 8193, Group descriptors at 8194-8194
Block bitmap at 4 (bg #0 + 3), csum 0x00000000
Inode bitmap at 8 (bg #0 + 7), csum 0x00000000
Inode table at 523-1034 (bg #0 + 522)
8190 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 8195-16384
Free inodes: 2049-4096
Group 2: (Blocks 16385-24576) csum 0x720f [INODE_UNINIT, ITABLE_ZEROED]
Block bitmap at 5 (bg #0 + 4), csum 0x040008b2
Inode bitmap at 9 (bg #0 + 8), csum 0x00000000
Inode table at 1035-1546 (bg #0 + 1034)
4096 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 20481-24576
Free inodes: 4097-6144
Group 3: (Blocks 24577-32767) csum 0xd0be [INODE_UNINIT, ITABLE_ZEROED]
Backup superblock at 24577, Group descriptors at 24578-24578
Block bitmap at 6 (bg #0 + 5), csum 0x4327ef1c
Inode bitmap at 10 (bg #0 + 9), csum 0x00000000
Inode table at 1547-2058 (bg #0 + 1546)
8189 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 24579-32767
Free inodes: 6145-8192
genimage-19/test/mke2fs.3.dump 0000664 0000000 0000000 00000006305 15032005261 0016255 0 ustar 00root root 0000000 0000000 Filesystem volume name: mke2fs
Last mounted on:
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr dir_index filetype extent 64bit flex_bg sparse_super dir_nlink extra_isize quota metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 8192
Block count: 32768
Reserved block count: 1638
Overhead clusters: 6159
Free blocks: 26580
Free inodes: 8141
First block: 1
Block size: 1024
Fragment size: 1024
Group descriptor size: 64
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 2048
Inode blocks per group: 512
Flex block group size: 16
Filesystem created: Sat Jan 1 00:00:00 2000
Last mount time: n/a
Last write time: Sat Jan 1 00:00:00 2000
Mount count: 0
Maximum mount count: -1
Last checked: Sat Jan 1 00:00:00 2000
Check interval: 0 ()
Lifetime writes: 110 kB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 256
Required extra isize: 32
Desired extra isize: 32
Journal inode: 8
Default directory hash: half_md4
Journal backup: inode blocks
Checksum type: crc32c
Journal features: (none)
Total journal size: 4096k
Total journal blocks: 4096
Max transaction length: 4096
Fast commit length: 0
Journal sequence: 0x00000001
Journal start: 0
Group 0: (Blocks 1-8192) csum 0xd0bb [ITABLE_ZEROED]
Primary superblock at 1, Group descriptors at 2-2
Block bitmap at 3 (+2), csum 0xde29f1cb
Inode bitmap at 7 (+6), csum 0xb1052088
Inode table at 11-522 (+10)
6105 free blocks, 1997 free inodes, 18 directories, 1997 unused inodes
Free blocks: 2088-8192
Free inodes: 52-2048
Group 1: (Blocks 8193-16384) csum 0x1510 [INODE_UNINIT, ITABLE_ZEROED]
Backup superblock at 8193, Group descriptors at 8194-8194
Block bitmap at 4 (bg #0 + 3), csum 0xc1d1d464
Inode bitmap at 8 (bg #0 + 7), csum 0x00000000
Inode table at 523-1034 (bg #0 + 522)
8190 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 8195-16384
Free inodes: 2049-4096
Group 2: (Blocks 16385-24576) csum 0x720f [INODE_UNINIT, ITABLE_ZEROED]
Block bitmap at 5 (bg #0 + 4), csum 0x040008b2
Inode bitmap at 9 (bg #0 + 8), csum 0x00000000
Inode table at 1035-1546 (bg #0 + 1034)
4096 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 20481-24576
Free inodes: 4097-6144
Group 3: (Blocks 24577-32767) csum 0xd0be [INODE_UNINIT, ITABLE_ZEROED]
Backup superblock at 24577, Group descriptors at 24578-24578
Block bitmap at 6 (bg #0 + 5), csum 0x4327ef1c
Inode bitmap at 10 (bg #0 + 9), csum 0x00000000
Inode table at 1547-2058 (bg #0 + 1546)
8189 free blocks, 2048 free inodes, 0 directories, 2048 unused inodes
Free blocks: 24579-32767
Free inodes: 6145-8192
genimage-19/test/mke2fs.conf 0000664 0000000 0000000 00000001454 15032005261 0016074 0 ustar 00root root 0000000 0000000 [defaults]
base_features = sparse_super,large_file,filetype,resize_inode,dir_index,ext_attr
default_mntopts = acl,user_xattr
enable_periodic_fsck = 0
blocksize = 4096
inode_size = 256
inode_ratio = 16384
[fs_types]
ext3 = {
features = has_journal
}
ext4 = {
features = has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize
inode_size = 256
}
small = {
blocksize = 1024
inode_size = 128
inode_ratio = 4096
}
floppy = {
blocksize = 1024
inode_size = 128
inode_ratio = 8192
}
big = {
inode_ratio = 32768
}
huge = {
inode_ratio = 65536
}
news = {
inode_ratio = 4096
}
largefile = {
inode_ratio = 1048576
blocksize = -1
}
largefile4 = {
inode_ratio = 4194304
blocksize = -1
}
hurd = {
blocksize = 4096
inode_size = 128
}
genimage-19/test/mke2fs.config 0000664 0000000 0000000 00000000375 15032005261 0016415 0 ustar 00root root 0000000 0000000 image mke2fs.ext4 {
ext4 {
label = "mke2fs"
fs-timestamp = "20000101000000"
use-mke2fs = true
mke2fs-conf = "mke2fs.conf"
extraargs = "-U 12345678-1234-1234-1234-1234567890ab -E quotatype="
features = "^resize_inode,quota"
}
size = 32M
}
genimage-19/test/qemu.config 0000664 0000000 0000000 00000000212 15032005261 0016163 0 ustar 00root root 0000000 0000000 image test.qcow {
qemu {
format = "qcow2"
}
partition part1 {
image = "part1.img"
}
partition part2 {
image = "part2.img"
}
}
genimage-19/test/qemu.qcow.gz 0000664 0000000 0000000 00000001034 15032005261 0016311 0 ustar 00root root 0000000 0000000 \ test.qcow αAKETYd7d'\%FܗWNF[!1|C;/:}KyYE8|{ htR [&K