From 972dcfcdbfe75dcfeb777150c136576cf1a71e99 Mon Sep 17 00:00:00 2001 From: Tudor Florea Date: Fri, 9 Oct 2015 22:59:03 +0200 Subject: initial commit for Enea Linux 5.0 arm Signed-off-by: Tudor Florea --- scripts/lib/bsp/__init__.py | 22 + scripts/lib/bsp/engine.py | 1947 ++++++++++++++++++++ scripts/lib/bsp/help.py | 1043 +++++++++++ scripts/lib/bsp/kernel.py | 1071 +++++++++++ .../lib/bsp/substrate/target/arch/arm/.gitignore | 0 .../xserver-xf86-config/machine.noinstall | 1 + .../xserver-xf86-config/machine/xorg.conf | 34 + .../xorg-xserver/xserver-xf86-config_0.1.bbappend | 2 + .../arch/arm/recipes-kernel/linux/files.noinstall | 1 + .../linux/files/machine-non_hardware.cfg | 31 + .../linux/files/machine-preempt-rt.scc | 14 + .../linux/files/machine-standard.scc | 14 + .../recipes-kernel/linux/files/machine-tiny.scc | 10 + .../linux/files/machine-user-config.cfg | 1 + .../linux/files/machine-user-features.scc | 1 + .../linux/files/machine-user-patches.scc | 1 + .../arm/recipes-kernel/linux/files/machine.cfg | 321 ++++ .../arm/recipes-kernel/linux/files/machine.scc | 8 + .../arm/recipes-kernel/linux/kernel-list.noinstall | 5 + .../recipes-kernel/linux/linux-yocto-dev.bbappend | 26 + .../linux/linux-yocto-rt_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.14.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.10.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.14.bbappend | 33 + .../bsp/substrate/target/arch/common/COPYING.MIT | 17 + .../lib/bsp/substrate/target/arch/common/README | 118 ++ .../substrate/target/arch/common/README.sources | 17 + .../substrate/target/arch/common/binary/.gitignore | 0 .../substrate/target/arch/common/conf/layer.conf | 10 + .../formfactor/formfactor/machine.noinstall | 1 + .../formfactor/formfactor/machine/machconfig | 5 + .../recipes-bsp/formfactor/formfactor_0.0.bbappend | 2 + .../recipes-kernel/linux/kernel-list.noinstall | 26 + .../recipes-kernel/linux/linux-yocto-custom.bb | 58 + .../linux/linux-yocto-custom.noinstall | 1 + .../linux/linux-yocto-custom/defconfig | 5 + .../linux-yocto-custom/machine-user-config.cfg | 9 + .../linux-yocto-custom/machine-user-patches.scc | 9 + .../linux/linux-yocto-custom/machine.cfg | 4 + .../linux/linux-yocto-custom/machine.scc | 18 + .../target/arch/i386/conf/machine/machine.conf | 67 + .../xserver-xf86-config/machine.noinstall | 1 + .../xserver-xf86-config/machine/xorg.conf | 1 + .../xorg-xserver/xserver-xf86-config_0.1.bbappend | 2 + .../arch/i386/recipes-kernel/linux/files.noinstall | 1 + .../linux/files/machine-preempt-rt.scc | 16 + .../linux/files/machine-standard.scc | 16 + .../recipes-kernel/linux/files/machine-tiny.scc | 10 + .../linux/files/machine-user-config.cfg | 1 + .../linux/files/machine-user-features.scc | 1 + .../linux/files/machine-user-patches.scc | 1 + .../i386/recipes-kernel/linux/files/machine.cfg | 55 + .../i386/recipes-kernel/linux/files/machine.scc | 21 + .../recipes-kernel/linux/kernel-list.noinstall | 5 + .../recipes-kernel/linux/linux-yocto-dev.bbappend | 26 + .../linux/linux-yocto-rt_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.14.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.10.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.14.bbappend | 33 + .../bsp/substrate/target/arch/layer/COPYING.MIT | 17 + scripts/lib/bsp/substrate/target/arch/layer/README | 64 + .../substrate/target/arch/layer/conf/layer.conf | 10 + .../target/arch/layer/layer-questions.noinstall | 14 + .../arch/layer/recipes-example-bbappend.noinstall | 1 + .../example-bbappend-version.bbappend | 9 + .../example-bbappend-version.noinstall | 1 + .../example-bbappend-version/example.patch | 12 + .../target/arch/layer/recipes-example.noinstall | 1 + .../recipes-example/example/example-recipe-0.1.bb | 24 + .../example/example-recipe-0.1.noinstall | 1 + .../example/example-recipe-0.1/example.patch | 12 + .../example/example-recipe-0.1/helloworld.c | 8 + .../lib/bsp/substrate/target/arch/mips/.gitignore | 0 .../target/arch/mips/conf/machine/machine.conf | 39 + .../arch/mips/recipes-kernel/linux/files.noinstall | 1 + .../linux/files/machine-preempt-rt.scc | 10 + .../linux/files/machine-standard.scc | 10 + .../recipes-kernel/linux/files/machine-tiny.scc | 10 + .../linux/files/machine-user-config.cfg | 1 + .../linux/files/machine-user-features.scc | 1 + .../linux/files/machine-user-patches.scc | 1 + .../mips/recipes-kernel/linux/files/machine.cfg | 2 + .../mips/recipes-kernel/linux/files/machine.scc | 8 + .../recipes-kernel/linux/kernel-list.noinstall | 5 + .../recipes-kernel/linux/linux-yocto-dev.bbappend | 26 + .../linux/linux-yocto-rt_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.14.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.10.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.14.bbappend | 33 + .../bsp/substrate/target/arch/powerpc/.gitignore | 0 .../target/arch/powerpc/conf/machine/machine.conf | 75 + .../powerpc/recipes-kernel/linux/files.noinstall | 1 + .../linux/files/machine-preempt-rt.scc | 10 + .../linux/files/machine-standard.scc | 10 + .../recipes-kernel/linux/files/machine-tiny.scc | 10 + .../linux/files/machine-user-config.cfg | 1 + .../linux/files/machine-user-features.scc | 1 + .../linux/files/machine-user-patches.scc | 1 + .../powerpc/recipes-kernel/linux/files/machine.cfg | 164 ++ .../powerpc/recipes-kernel/linux/files/machine.scc | 10 + .../recipes-kernel/linux/kernel-list.noinstall | 5 + .../recipes-kernel/linux/linux-yocto-dev.bbappend | 26 + .../linux/linux-yocto-rt_3.14.bbappend | 33 + .../linux/linux-yocto-tiny_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.14.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.10.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.14.bbappend | 33 + .../target/arch/qemu/conf/machine/machine.conf | 70 + .../init-ifupdown/init-ifupdown/machine.noinstall | 1 + .../init-ifupdown/init-ifupdown/machine/interfaces | 5 + .../init-ifupdown/init-ifupdown_1.0.bbappend | 1 + .../xserver-xf86-config/machine.noinstall | 1 + .../xserver-xf86-config/machine/xorg.conf | 77 + .../xorg-xserver/xserver-xf86-config_0.1.bbappend | 1 + .../arch/qemu/recipes-kernel/linux/files.noinstall | 1 + .../linux/files/machine-preempt-rt.scc | 10 + .../linux/files/machine-standard.scc | 17 + .../recipes-kernel/linux/files/machine-tiny.scc | 10 + .../linux/files/machine-user-config.cfg | 1 + .../linux/files/machine-user-features.scc | 1 + .../linux/files/machine-user-patches.scc | 1 + .../qemu/recipes-kernel/linux/files/machine.cfg | 1 + .../qemu/recipes-kernel/linux/files/machine.scc | 5 + .../recipes-kernel/linux/kernel-list.noinstall | 5 + .../recipes-kernel/linux/linux-yocto-dev.bbappend | 50 + .../linux/linux-yocto-rt_3.10.bbappend | 56 + .../linux/linux-yocto-tiny_3.10.bbappend | 56 + .../linux/linux-yocto-tiny_3.4.bbappend | 56 + .../recipes-kernel/linux/linux-yocto_3.10.bbappend | 56 + .../recipes-kernel/linux/linux-yocto_3.14.bbappend | 56 + .../bsp/substrate/target/arch/x86_64/.gitignore | 0 .../target/arch/x86_64/conf/machine/machine.conf | 57 + .../xserver-xf86-config/machine.noinstall | 1 + .../xserver-xf86-config/machine/xorg.conf | 1 + .../xorg-xserver/xserver-xf86-config_0.1.bbappend | 2 + .../x86_64/recipes-kernel/linux/files.noinstall | 1 + .../linux/files/machine-preempt-rt.scc | 16 + .../linux/files/machine-standard.scc | 16 + .../recipes-kernel/linux/files/machine-tiny.scc | 10 + .../linux/files/machine-user-config.cfg | 1 + .../linux/files/machine-user-features.scc | 1 + .../linux/files/machine-user-patches.scc | 1 + .../x86_64/recipes-kernel/linux/files/machine.cfg | 48 + .../x86_64/recipes-kernel/linux/files/machine.scc | 14 + .../recipes-kernel/linux/kernel-list.noinstall | 5 + .../recipes-kernel/linux/linux-yocto-dev.bbappend | 26 + .../linux/linux-yocto-rt_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.10.bbappend | 33 + .../linux/linux-yocto-tiny_3.14.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.10.bbappend | 33 + .../recipes-kernel/linux/linux-yocto_3.14.bbappend | 33 + scripts/lib/bsp/tags.py | 49 + scripts/lib/image/__init__.py | 22 + scripts/lib/image/canned-wks/directdisk.wks | 10 + scripts/lib/image/canned-wks/mkefidisk.wks | 11 + scripts/lib/image/canned-wks/mkgummidisk.wks | 11 + scripts/lib/image/canned-wks/sdimage-bootpart.wks | 6 + scripts/lib/image/canned-wks/uboot.wks | 17 + scripts/lib/image/config/wic.conf | 10 + scripts/lib/image/engine.py | 279 +++ scripts/lib/image/help.py | 756 ++++++++ scripts/lib/scriptpath.py | 42 + scripts/lib/wic/3rdparty/pykickstart/__init__.py | 0 scripts/lib/wic/3rdparty/pykickstart/base.py | 466 +++++ .../wic/3rdparty/pykickstart/commands/__init__.py | 20 + .../3rdparty/pykickstart/commands/bootloader.py | 216 +++ .../wic/3rdparty/pykickstart/commands/partition.py | 314 ++++ scripts/lib/wic/3rdparty/pykickstart/constants.py | 57 + scripts/lib/wic/3rdparty/pykickstart/errors.py | 103 ++ .../wic/3rdparty/pykickstart/handlers/__init__.py | 0 .../wic/3rdparty/pykickstart/handlers/control.py | 46 + .../lib/wic/3rdparty/pykickstart/handlers/f16.py | 24 + scripts/lib/wic/3rdparty/pykickstart/ko.py | 37 + scripts/lib/wic/3rdparty/pykickstart/options.py | 204 ++ scripts/lib/wic/3rdparty/pykickstart/parser.py | 619 +++++++ scripts/lib/wic/3rdparty/pykickstart/sections.py | 244 +++ scripts/lib/wic/3rdparty/pykickstart/version.py | 168 ++ scripts/lib/wic/__init__.py | 4 + scripts/lib/wic/__version__.py | 1 + scripts/lib/wic/conf.py | 102 + scripts/lib/wic/creator.py | 187 ++ scripts/lib/wic/imager/__init__.py | 0 scripts/lib/wic/imager/baseimager.py | 193 ++ scripts/lib/wic/imager/direct.py | 363 ++++ scripts/lib/wic/kickstart/__init__.py | 125 ++ .../lib/wic/kickstart/custom_commands/__init__.py | 10 + .../lib/wic/kickstart/custom_commands/micboot.py | 49 + .../wic/kickstart/custom_commands/micpartition.py | 57 + .../lib/wic/kickstart/custom_commands/partition.py | 652 +++++++ .../lib/wic/kickstart/custom_commands/wicboot.py | 57 + scripts/lib/wic/msger.py | 309 ++++ scripts/lib/wic/plugin.py | 156 ++ scripts/lib/wic/pluginbase.py | 120 ++ scripts/lib/wic/plugins/imager/direct_plugin.py | 98 + scripts/lib/wic/plugins/source/bootimg-efi.py | 236 +++ .../lib/wic/plugins/source/bootimg-partition.py | 115 ++ scripts/lib/wic/plugins/source/bootimg-pcbios.py | 200 ++ scripts/lib/wic/plugins/source/rootfs.py | 92 + scripts/lib/wic/plugins/source/uboot.py | 173 ++ scripts/lib/wic/test | 1 + scripts/lib/wic/utils/__init__.py | 0 scripts/lib/wic/utils/cmdln.py | 1586 ++++++++++++++++ scripts/lib/wic/utils/errors.py | 47 + scripts/lib/wic/utils/fs_related.py | 111 ++ scripts/lib/wic/utils/misc.py | 59 + scripts/lib/wic/utils/oe/__init__.py | 22 + scripts/lib/wic/utils/oe/misc.py | 205 +++ scripts/lib/wic/utils/oe/package_manager.py | 810 ++++++++ scripts/lib/wic/utils/partitionedfs.py | 360 ++++ scripts/lib/wic/utils/runner.py | 109 ++ 213 files changed, 17582 insertions(+) create mode 100644 scripts/lib/bsp/__init__.py create mode 100644 scripts/lib/bsp/engine.py create mode 100644 scripts/lib/bsp/help.py create mode 100644 scripts/lib/bsp/kernel.py create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/.gitignore create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-non_hardware.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-preempt-rt.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-standard.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-tiny.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-config.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-features.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-patches.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/kernel-list.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-dev.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/common/COPYING.MIT create mode 100644 scripts/lib/bsp/substrate/target/arch/common/README create mode 100644 scripts/lib/bsp/substrate/target/arch/common/README.sources create mode 100644 scripts/lib/bsp/substrate/target/arch/common/binary/.gitignore create mode 100644 scripts/lib/bsp/substrate/target/arch/common/conf/layer.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine/machconfig create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor_0.0.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/kernel-list.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.bb create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/defconfig create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-config.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-patches.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/conf/machine/machine.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-preempt-rt.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-standard.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-tiny.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-config.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-features.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-patches.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/kernel-list.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-dev.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/COPYING.MIT create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/README create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/conf/layer.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version/example.patch create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.bb create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/example.patch create mode 100644 scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/helloworld.c create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/.gitignore create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/conf/machine/machine.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-preempt-rt.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-standard.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-tiny.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-config.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-features.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-patches.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/kernel-list.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-dev.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/.gitignore create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/conf/machine/machine.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-preempt-rt.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-standard.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-tiny.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-config.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-features.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-patches.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/kernel-list.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-dev.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-rt_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/conf/machine/machine.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine/interfaces create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-preempt-rt.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-standard.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-tiny.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-config.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-features.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-patches.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/kernel-list.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-dev.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.4.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/.gitignore create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/conf/machine/machine.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-preempt-rt.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-standard.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-tiny.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-config.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-features.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-patches.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.cfg create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.scc create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/kernel-list.noinstall create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-dev.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.10.bbappend create mode 100644 scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.14.bbappend create mode 100644 scripts/lib/bsp/tags.py create mode 100644 scripts/lib/image/__init__.py create mode 100644 scripts/lib/image/canned-wks/directdisk.wks create mode 100644 scripts/lib/image/canned-wks/mkefidisk.wks create mode 100644 scripts/lib/image/canned-wks/mkgummidisk.wks create mode 100644 scripts/lib/image/canned-wks/sdimage-bootpart.wks create mode 100644 scripts/lib/image/canned-wks/uboot.wks create mode 100644 scripts/lib/image/config/wic.conf create mode 100644 scripts/lib/image/engine.py create mode 100644 scripts/lib/image/help.py create mode 100644 scripts/lib/scriptpath.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/__init__.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/base.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/commands/partition.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/constants.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/errors.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/handlers/__init__.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/handlers/control.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/ko.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/options.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/parser.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/sections.py create mode 100644 scripts/lib/wic/3rdparty/pykickstart/version.py create mode 100644 scripts/lib/wic/__init__.py create mode 100644 scripts/lib/wic/__version__.py create mode 100644 scripts/lib/wic/conf.py create mode 100644 scripts/lib/wic/creator.py create mode 100644 scripts/lib/wic/imager/__init__.py create mode 100644 scripts/lib/wic/imager/baseimager.py create mode 100644 scripts/lib/wic/imager/direct.py create mode 100644 scripts/lib/wic/kickstart/__init__.py create mode 100644 scripts/lib/wic/kickstart/custom_commands/__init__.py create mode 100644 scripts/lib/wic/kickstart/custom_commands/micboot.py create mode 100644 scripts/lib/wic/kickstart/custom_commands/micpartition.py create mode 100644 scripts/lib/wic/kickstart/custom_commands/partition.py create mode 100644 scripts/lib/wic/kickstart/custom_commands/wicboot.py create mode 100644 scripts/lib/wic/msger.py create mode 100644 scripts/lib/wic/plugin.py create mode 100644 scripts/lib/wic/pluginbase.py create mode 100644 scripts/lib/wic/plugins/imager/direct_plugin.py create mode 100644 scripts/lib/wic/plugins/source/bootimg-efi.py create mode 100644 scripts/lib/wic/plugins/source/bootimg-partition.py create mode 100644 scripts/lib/wic/plugins/source/bootimg-pcbios.py create mode 100644 scripts/lib/wic/plugins/source/rootfs.py create mode 100644 scripts/lib/wic/plugins/source/uboot.py create mode 100644 scripts/lib/wic/test create mode 100644 scripts/lib/wic/utils/__init__.py create mode 100644 scripts/lib/wic/utils/cmdln.py create mode 100644 scripts/lib/wic/utils/errors.py create mode 100644 scripts/lib/wic/utils/fs_related.py create mode 100644 scripts/lib/wic/utils/misc.py create mode 100644 scripts/lib/wic/utils/oe/__init__.py create mode 100644 scripts/lib/wic/utils/oe/misc.py create mode 100644 scripts/lib/wic/utils/oe/package_manager.py create mode 100644 scripts/lib/wic/utils/partitionedfs.py create mode 100644 scripts/lib/wic/utils/runner.py (limited to 'scripts/lib') diff --git a/scripts/lib/bsp/__init__.py b/scripts/lib/bsp/__init__.py new file mode 100644 index 0000000000..8bbb6e1530 --- /dev/null +++ b/scripts/lib/bsp/__init__.py @@ -0,0 +1,22 @@ +# +# Yocto BSP tools library +# +# Copyright (c) 2012, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# AUTHORS +# Tom Zanussi +# diff --git a/scripts/lib/bsp/engine.py b/scripts/lib/bsp/engine.py new file mode 100644 index 0000000000..7d6be239da --- /dev/null +++ b/scripts/lib/bsp/engine.py @@ -0,0 +1,1947 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2012, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module implements the templating engine used by 'yocto-bsp' to +# create BSPs. The BSP templates are simply the set of files expected +# to appear in a generated BSP, marked up with a small set of tags +# used to customize the output. The engine parses through the +# templates and generates a Python program containing all the logic +# and input elements needed to display and retrieve BSP-specific +# information from the user. The resulting program uses those results +# to generate the final BSP files. +# +# AUTHORS +# Tom Zanussi +# + +import os +import sys +from abc import ABCMeta, abstractmethod +from tags import * +import shlex +import json +import subprocess +import shutil + +class Line(): + """ + Generic (abstract) container representing a line that will appear + in the BSP-generating program. + """ + __metaclass__ = ABCMeta + + def __init__(self, line): + self.line = line + self.generated_line = "" + self.prio = sys.maxint + self.discard = False + + @abstractmethod + def gen(self, context = None): + """ + Generate the final executable line that will appear in the + BSP-generation program. + """ + pass + + def escape(self, line): + """ + Escape single and double quotes and backslashes until I find + something better (re.escape() escapes way too much). + """ + return line.replace("\\", "\\\\").replace("\"", "\\\"").replace("'", "\\'") + + def parse_error(self, msg, lineno, line): + raise SyntaxError("%s: %s" % (msg, line)) + + +class NormalLine(Line): + """ + Container for normal (non-tag) lines. + """ + def __init__(self, line): + Line.__init__(self, line) + self.is_filename = False + self.is_dirname = False + self.out_filebase = None + + def gen(self, context = None): + if self.is_filename: + line = "current_file = \"" + os.path.join(self.out_filebase, self.escape(self.line)) + "\"; of = open(current_file, \"w\")" + elif self.is_dirname: + dirname = os.path.join(self.out_filebase, self.escape(self.line)) + line = "if not os.path.exists(\"" + dirname + "\"): os.mkdir(\"" + dirname + "\")" + else: + line = "of.write(\"" + self.escape(self.line) + "\\n\")" + return line + + +class CodeLine(Line): + """ + Container for Python code tag lines. + """ + def __init__(self, line): + Line.__init__(self, line) + + def gen(self, context = None): + return self.line + + +class Assignment: + """ + Representation of everything we know about {{=name }} tags. + Instances of these are used by Assignment lines. + """ + def __init__(self, start, end, name): + self.start = start + self.end = end + self.name = name + + +class AssignmentLine(NormalLine): + """ + Container for normal lines containing assignment tags. Assignment + tags must be in ascending order of 'start' value. + """ + def __init__(self, line): + NormalLine.__init__(self, line) + self.assignments = [] + + def add_assignment(self, start, end, name): + self.assignments.append(Assignment(start, end, name)) + + def gen(self, context = None): + line = self.escape(self.line) + + for assignment in self.assignments: + replacement = "\" + " + assignment.name + " + \"" + idx = line.find(ASSIGN_TAG) + line = line[:idx] + replacement + line[idx + assignment.end - assignment.start:] + if self.is_filename: + return "current_file = \"" + os.path.join(self.out_filebase, line) + "\"; of = open(current_file, \"w\")" + elif self.is_dirname: + dirname = os.path.join(self.out_filebase, line) + return "if not os.path.exists(\"" + dirname + "\"): os.mkdir(\"" + dirname + "\")" + else: + return "of.write(\"" + line + "\\n\")" + + +class InputLine(Line): + """ + Base class for Input lines. + """ + def __init__(self, props, tag, lineno): + Line.__init__(self, tag) + self.props = props + self.lineno = lineno + + try: + self.prio = int(props["prio"]) + except KeyError: + self.prio = sys.maxint + + def gen(self, context = None): + try: + depends_on = self.props["depends-on"] + try: + depends_on_val = self.props["depends-on-val"] + except KeyError: + self.parse_error("No 'depends-on-val' for 'depends-on' property", + self.lineno, self.line) + except KeyError: + pass + + +class EditBoxInputLine(InputLine): + """ + Base class for 'editbox' Input lines. + + props: + name: example - "Load address" + msg: example - "Please enter the load address" + result: + Sets the value of the variable specified by 'name' to + whatever the user typed. + """ + def __init__(self, props, tag, lineno): + InputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + InputLine.gen(self, context) + name = self.props["name"] + if not name: + self.parse_error("No input 'name' property found", + self.lineno, self.line) + msg = self.props["msg"] + if not msg: + self.parse_error("No input 'msg' property found", + self.lineno, self.line) + + try: + default_choice = self.props["default"] + except KeyError: + default_choice = "" + + msg += " [default: " + default_choice + "]" + + line = name + " = default(raw_input(\"" + msg + " \"), " + name + ")" + + return line + + +class GitRepoEditBoxInputLine(EditBoxInputLine): + """ + Base class for 'editbox' Input lines for user input of remote git + repos. This class verifies the existence and connectivity of the + specified git repo. + + props: + name: example - "Load address" + msg: example - "Please enter the load address" + result: + Sets the value of the variable specified by 'name' to + whatever the user typed. + """ + def __init__(self, props, tag, lineno): + EditBoxInputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + EditBoxInputLine.gen(self, context) + name = self.props["name"] + if not name: + self.parse_error("No input 'name' property found", + self.lineno, self.line) + msg = self.props["msg"] + if not msg: + self.parse_error("No input 'msg' property found", + self.lineno, self.line) + + try: + default_choice = self.props["default"] + except KeyError: + default_choice = "" + + msg += " [default: " + default_choice + "]" + + line = name + " = get_verified_git_repo(\"" + msg + "\"," + name + ")" + + return line + + +class FileEditBoxInputLine(EditBoxInputLine): + """ + Base class for 'editbox' Input lines for user input of existing + files. This class verifies the existence of the specified file. + + props: + name: example - "Load address" + msg: example - "Please enter the load address" + result: + Sets the value of the variable specified by 'name' to + whatever the user typed. + """ + def __init__(self, props, tag, lineno): + EditBoxInputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + EditBoxInputLine.gen(self, context) + name = self.props["name"] + if not name: + self.parse_error("No input 'name' property found", + self.lineno, self.line) + msg = self.props["msg"] + if not msg: + self.parse_error("No input 'msg' property found", + self.lineno, self.line) + + try: + default_choice = self.props["default"] + except KeyError: + default_choice = "" + + msg += " [default: " + default_choice + "]" + + line = name + " = get_verified_file(\"" + msg + "\"," + name + ", True)" + + return line + + +class BooleanInputLine(InputLine): + """ + Base class for boolean Input lines. + props: + name: example - "keyboard" + msg: example - "Got keyboard?" + result: + Sets the value of the variable specified by 'name' to "yes" or "no" + example - keyboard = "yes" + """ + def __init__(self, props, tag, lineno): + InputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + InputLine.gen(self, context) + name = self.props["name"] + if not name: + self.parse_error("No input 'name' property found", + self.lineno, self.line) + msg = self.props["msg"] + if not msg: + self.parse_error("No input 'msg' property found", + self.lineno, self.line) + + try: + default_choice = self.props["default"] + except KeyError: + default_choice = "" + + msg += " [default: " + default_choice + "]" + + line = name + " = boolean(raw_input(\"" + msg + " \"), " + name + ")" + + return line + + +class ListInputLine(InputLine): + """ + Base class for List-based Input lines. e.g. Choicelist, Checklist. + """ + __metaclass__ = ABCMeta + + def __init__(self, props, tag, lineno): + InputLine.__init__(self, props, tag, lineno) + self.choices = [] + + def gen_choicepair_list(self): + """Generate a list of 2-item val:desc lists from self.choices.""" + if not self.choices: + return None + + choicepair_list = list() + + for choice in self.choices: + choicepair = [] + choicepair.append(choice.val) + choicepair.append(choice.desc) + choicepair_list.append(choicepair) + + return choicepair_list + + def gen_degenerate_choicepair_list(self, choices): + """Generate a list of 2-item val:desc with val=desc from passed-in choices.""" + choicepair_list = list() + + for choice in choices: + choicepair = [] + choicepair.append(choice) + choicepair.append(choice) + choicepair_list.append(choicepair) + + return choicepair_list + + def exec_listgen_fn(self, context = None): + """ + Execute the list-generating function contained as a string in + the "gen" property. + """ + retval = None + try: + fname = self.props["gen"] + modsplit = fname.split('.') + mod_fn = modsplit.pop() + mod = '.'.join(modsplit) + + __import__(mod) + # python 2.7 has a better way to do this using importlib.import_module + m = sys.modules[mod] + + fn = getattr(m, mod_fn) + if not fn: + self.parse_error("couldn't load function specified for 'gen' property ", + self.lineno, self.line) + retval = fn(context) + if not retval: + self.parse_error("function specified for 'gen' property returned nothing ", + self.lineno, self.line) + except KeyError: + pass + + return retval + + def gen_choices_str(self, choicepairs): + """ + Generate a numbered list of choices from a list of choicepairs + for display to the user. + """ + choices_str = "" + + for i, choicepair in enumerate(choicepairs): + choices_str += "\t" + str(i + 1) + ") " + choicepair[1] + "\n" + + return choices_str + + def gen_choices_val_str(self, choicepairs): + """ + Generate an array of choice values corresponding to the + numbered list generated by gen_choices_str(). + """ + choices_val_list = "[" + + for i, choicepair in enumerate(choicepairs): + choices_val_list += "\"" + choicepair[0] + "\"," + choices_val_list += "]" + + return choices_val_list + + def gen_choices_val_list(self, choicepairs): + """ + Generate an array of choice values corresponding to the + numbered list generated by gen_choices_str(). + """ + choices_val_list = [] + + for i, choicepair in enumerate(choicepairs): + choices_val_list.append(choicepair[0]) + + return choices_val_list + + def gen_choices_list(self, context = None, checklist = False): + """ + Generate an array of choice values corresponding to the + numbered list generated by gen_choices_str(). + """ + choices = self.exec_listgen_fn(context) + if choices: + if len(choices) == 0: + self.parse_error("No entries available for input list", + self.lineno, self.line) + choicepairs = self.gen_degenerate_choicepair_list(choices) + else: + if len(self.choices) == 0: + self.parse_error("No entries available for input list", + self.lineno, self.line) + choicepairs = self.gen_choicepair_list() + + return choicepairs + + def gen_choices(self, context = None, checklist = False): + """ + Generate an array of choice values corresponding to the + numbered list generated by gen_choices_str(), display it to + the user, and process the result. + """ + msg = self.props["msg"] + if not msg: + self.parse_error("No input 'msg' property found", + self.lineno, self.line) + + try: + default_choice = self.props["default"] + except KeyError: + default_choice = "" + + msg += " [default: " + default_choice + "]" + + choicepairs = self.gen_choices_list(context, checklist) + + choices_str = self.gen_choices_str(choicepairs) + choices_val_list = self.gen_choices_val_list(choicepairs) + if checklist: + choiceval = default(find_choicevals(raw_input(msg + "\n" + choices_str), choices_val_list), default_choice) + else: + choiceval = default(find_choiceval(raw_input(msg + "\n" + choices_str), choices_val_list), default_choice) + + return choiceval + + +def find_choiceval(choice_str, choice_list): + """ + Take number as string and return val string from choice_list, + empty string if oob. choice_list is a simple python list. + """ + choice_val = "" + + try: + choice_idx = int(choice_str) + if choice_idx <= len(choice_list): + choice_idx -= 1 + choice_val = choice_list[choice_idx] + except ValueError: + pass + + return choice_val + + +def find_choicevals(choice_str, choice_list): + """ + Take numbers as space-separated string and return vals list from + choice_list, empty list if oob. choice_list is a simple python + list. + """ + choice_vals = [] + + choices = choice_str.split() + for choice in choices: + choice_vals.append(find_choiceval(choice, choice_list)) + + return choice_vals + + +def default(input_str, name): + """ + Return default if no input_str, otherwise stripped input_str. + """ + if not input_str: + return name + + return input_str.strip() + + +def verify_git_repo(giturl): + """ + Verify that the giturl passed in can be connected to. This can be + used as a check for the existence of the given repo and/or basic + git remote connectivity. + + Returns True if the connection was successful, fals otherwise + """ + if not giturl: + return False + + gitcmd = "git ls-remote %s > /dev/null 2>&1" % (giturl) + rc = subprocess.call(gitcmd, shell=True) + if rc == 0: + return True + + return False + + +def get_verified_git_repo(input_str, name): + """ + Return git repo if verified, otherwise loop forever asking user + for filename. + """ + msg = input_str.strip() + " " + + giturl = default(raw_input(msg), name) + + while True: + if verify_git_repo(giturl): + return giturl + giturl = default(raw_input(msg), name) + + +def get_verified_file(input_str, name, filename_can_be_null): + """ + Return filename if the file exists, otherwise loop forever asking + user for filename. + """ + msg = input_str.strip() + " " + + filename = default(raw_input(msg), name) + + while True: + if not filename and filename_can_be_null: + return filename + if os.path.isfile(filename): + return filename + filename = default(raw_input(msg), name) + + +def replace_file(replace_this, with_this): + """ + Replace the given file with the contents of filename, retaining + the original filename. + """ + try: + replace_this.close() + shutil.copy(with_this, replace_this.name) + except IOError: + pass + + +def boolean(input_str, name): + """ + Return lowercase version of first char in string, or value in name. + """ + if not input_str: + return name + + str = input_str.lower().strip() + if str and str[0] == "y" or str[0] == "n": + return str[0] + else: + return name + + +def strip_base(input_str): + """ + strip '/base' off the end of input_str, so we can use 'base' in + the branch names we present to the user. + """ + if input_str and input_str.endswith("/base"): + return input_str[:-len("/base")] + return input_str.strip() + + +deferred_choices = {} + +def gen_choices_defer(input_line, context, checklist = False): + """ + Save the context hashed the name of the input item, which will be + passed to the gen function later. + """ + name = input_line.props["name"] + + try: + nameappend = input_line.props["nameappend"] + except KeyError: + nameappend = "" + + try: + branches_base = input_line.props["branches_base"] + except KeyError: + branches_base = "" + + filename = input_line.props["filename"] + + closetag_start = filename.find(CLOSE_TAG) + + if closetag_start != -1: + filename = filename[closetag_start + len(CLOSE_TAG):] + + filename = filename.strip() + filename = os.path.splitext(filename)[0] + + captured_context = capture_context(context) + context["filename"] = filename + captured_context["filename"] = filename + context["nameappend"] = nameappend + captured_context["nameappend"] = nameappend + context["branches_base"] = branches_base + captured_context["branches_base"] = branches_base + + deferred_choice = (input_line, captured_context, checklist) + key = name + "_" + filename + "_" + nameappend + deferred_choices[key] = deferred_choice + + +def invoke_deferred_choices(name): + """ + Invoke the choice generation function using the context hashed by + 'name'. + """ + deferred_choice = deferred_choices[name] + input_line = deferred_choice[0] + context = deferred_choice[1] + checklist = deferred_choice[2] + + context["name"] = name + + choices = input_line.gen_choices(context, checklist) + + return choices + + +class ChoicelistInputLine(ListInputLine): + """ + Base class for choicelist Input lines. + props: + name: example - "xserver_choice" + msg: example - "Please select an xserver for this machine" + result: + Sets the value of the variable specified by 'name' to whichever Choice was chosen + example - xserver_choice = "xserver_vesa" + """ + def __init__(self, props, tag, lineno): + ListInputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + InputLine.gen(self, context) + + gen_choices_defer(self, context) + name = self.props["name"] + nameappend = context["nameappend"] + filename = context["filename"] + + try: + default_choice = self.props["default"] + except KeyError: + default_choice = "" + + line = name + " = default(invoke_deferred_choices(\"" + name + "_" + filename + "_" + nameappend + "\"), \"" + default_choice + "\")" + + return line + + +class ListValInputLine(InputLine): + """ + Abstract base class for choice and checkbox Input lines. + """ + def __init__(self, props, tag, lineno): + InputLine.__init__(self, props, tag, lineno) + + try: + self.val = self.props["val"] + except KeyError: + self.parse_error("No input 'val' property found", self.lineno, self.line) + + try: + self.desc = self.props["msg"] + except KeyError: + self.parse_error("No input 'msg' property found", self.lineno, self.line) + + +class ChoiceInputLine(ListValInputLine): + """ + Base class for choicelist item Input lines. + """ + def __init__(self, props, tag, lineno): + ListValInputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + return None + + +class ChecklistInputLine(ListInputLine): + """ + Base class for checklist Input lines. + """ + def __init__(self, props, tag, lineno): + ListInputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + InputLine.gen(self, context) + + gen_choices_defer(self, context, True) + name = self.props["name"] + nameappend = context["nameappend"] + filename = context["filename"] + + try: + default_choice = self.props["default"] + except KeyError: + default_choice = "" + + line = name + " = default(invoke_deferred_choices(\"" + name + "_" + filename + "_" + nameappend + "\"), \"" + default_choice + "\")" + + return line + + +class CheckInputLine(ListValInputLine): + """ + Base class for checklist item Input lines. + """ + def __init__(self, props, tag, lineno): + ListValInputLine.__init__(self, props, tag, lineno) + + def gen(self, context = None): + return None + + +dirname_substitutions = {} + +class SubstrateBase(object): + """ + Base class for both expanded and unexpanded file and dir container + objects. + """ + def __init__(self, filename, filebase, out_filebase): + self.filename = filename + self.filebase = filebase + self.translated_filename = filename + self.out_filebase = out_filebase + self.raw_lines = [] + self.expanded_lines = [] + self.prev_choicelist = None + + def parse_error(self, msg, lineno, line): + raise SyntaxError("%s: [%s: %d]: %s" % (msg, self.filename, lineno, line)) + + def expand_input_tag(self, tag, lineno): + """ + Input tags consist of the word 'input' at the beginning, + followed by name:value property pairs which are converted into + a dictionary. + """ + propstr = tag[len(INPUT_TAG):] + + props = dict(prop.split(":", 1) for prop in shlex.split(propstr)) + props["filename"] = self.filename + + input_type = props[INPUT_TYPE_PROPERTY] + if not props[INPUT_TYPE_PROPERTY]: + self.parse_error("No input 'type' property found", lineno, tag) + + if input_type == "boolean": + return BooleanInputLine(props, tag, lineno) + if input_type == "edit": + return EditBoxInputLine(props, tag, lineno) + if input_type == "edit-git-repo": + return GitRepoEditBoxInputLine(props, tag, lineno) + if input_type == "edit-file": + return FileEditBoxInputLine(props, tag, lineno) + elif input_type == "choicelist": + self.prev_choicelist = ChoicelistInputLine(props, tag, lineno) + return self.prev_choicelist + elif input_type == "choice": + if not self.prev_choicelist: + self.parse_error("Found 'choice' input tag but no previous choicelist", + lineno, tag) + choice = ChoiceInputLine(props, tag, lineno) + self.prev_choicelist.choices.append(choice) + return choice + elif input_type == "checklist": + return ChecklistInputLine(props, tag, lineno) + elif input_type == "check": + return CheckInputLine(props, tag, lineno) + + def expand_assignment_tag(self, start, line, lineno): + """ + Expand all tags in a line. + """ + expanded_line = AssignmentLine(line.rstrip()) + + while start != -1: + end = line.find(CLOSE_TAG, start) + if end == -1: + self.parse_error("No close tag found for assignment tag", lineno, line) + else: + name = line[start + len(ASSIGN_TAG):end].strip() + expanded_line.add_assignment(start, end + len(CLOSE_TAG), name) + start = line.find(ASSIGN_TAG, end) + + return expanded_line + + def expand_tag(self, line, lineno): + """ + Returns a processed tag line, or None if there was no tag + + The rules for tags are very simple: + - No nested tags + - Tags start with {{ and end with }} + - An assign tag, {{=, can appear anywhere and will + be replaced with what the assignment evaluates to + - Any other tag occupies the whole line it is on + - if there's anything else on the tag line, it's an error + - if it starts with 'input', it's an input tag and + will only be used for prompting and setting variables + - anything else is straight Python + - tags are in effect only until the next blank line or tag or 'pass' tag + - we don't have indentation in tags, but we need some way to end a block + forcefully without blank lines or other tags - that's the 'pass' tag + - todo: implement pass tag + - directories and filenames can have tags as well, but only assignment + and 'if' code lines + - directories and filenames are the only case where normal tags can + coexist with normal text on the same 'line' + """ + start = line.find(ASSIGN_TAG) + if start != -1: + return self.expand_assignment_tag(start, line, lineno) + + start = line.find(OPEN_TAG) + if start == -1: + return None + + end = line.find(CLOSE_TAG, 0) + if end == -1: + self.parse_error("No close tag found for open tag", lineno, line) + + tag = line[start + len(OPEN_TAG):end].strip() + + if not tag.lstrip().startswith(INPUT_TAG): + return CodeLine(tag) + + return self.expand_input_tag(tag, lineno) + + def append_translated_filename(self, filename): + """ + Simply append filename to translated_filename + """ + self.translated_filename = os.path.join(self.translated_filename, filename) + + def get_substituted_file_or_dir_name(self, first_line, tag): + """ + If file or dir names contain name substitutions, return the name + to substitute. Note that this is just the file or dirname and + doesn't include the path. + """ + filename = first_line.find(tag) + if filename != -1: + filename += len(tag) + substituted_filename = first_line[filename:].strip() + this = substituted_filename.find(" this") + if this != -1: + head, tail = os.path.split(self.filename) + substituted_filename = substituted_filename[:this + 1] + tail + if tag == DIRNAME_TAG: # get rid of .noinstall in dirname + substituted_filename = substituted_filename.split('.')[0] + + return substituted_filename + + def get_substituted_filename(self, first_line): + """ + If a filename contains a name substitution, return the name to + substitute. Note that this is just the filename and doesn't + include the path. + """ + return self.get_substituted_file_or_dir_name(first_line, FILENAME_TAG) + + def get_substituted_dirname(self, first_line): + """ + If a dirname contains a name substitution, return the name to + substitute. Note that this is just the dirname and doesn't + include the path. + """ + return self.get_substituted_file_or_dir_name(first_line, DIRNAME_TAG) + + def substitute_filename(self, first_line): + """ + Find the filename in first_line and append it to translated_filename. + """ + substituted_filename = self.get_substituted_filename(first_line) + self.append_translated_filename(substituted_filename); + + def substitute_dirname(self, first_line): + """ + Find the dirname in first_line and append it to translated_filename. + """ + substituted_dirname = self.get_substituted_dirname(first_line) + self.append_translated_filename(substituted_dirname); + + def is_filename_substitution(self, line): + """ + Do we have a filename subustition? + """ + if line.find(FILENAME_TAG) != -1: + return True + return False + + def is_dirname_substitution(self, line): + """ + Do we have a dirname subustition? + """ + if line.find(DIRNAME_TAG) != -1: + return True + return False + + def translate_dirname(self, first_line): + """ + Just save the first_line mapped by filename. The later pass + through the directories will look for a dirname.noinstall + match and grab the substitution line. + """ + dirname_substitutions[self.filename] = first_line + + def translate_dirnames_in_path(self, path): + """ + Translate dirnames below this file or dir, not including tail. + dirname_substititions is keyed on actual untranslated filenames. + translated_path contains the subsititutions for each element. + """ + remainder = path[len(self.filebase)+1:] + translated_path = untranslated_path = self.filebase + + untranslated_dirs = remainder.split(os.sep) + + for dir in untranslated_dirs: + key = os.path.join(untranslated_path, dir + '.noinstall') + try: + first_line = dirname_substitutions[key] + except KeyError: + translated_path = os.path.join(translated_path, dir) + untranslated_path = os.path.join(untranslated_path, dir) + continue + substituted_dir = self.get_substituted_dirname(first_line) + translated_path = os.path.join(translated_path, substituted_dir) + untranslated_path = os.path.join(untranslated_path, dir) + + return translated_path + + def translate_file_or_dir_name(self): + """ + Originally we were allowed to use open/close/assign tags and python + code in the filename, which fit in nicely with the way we + processed the templates and generated code. Now that we can't + do that, we make those tags proper file contents and have this + pass substitute the nice but non-functional names with those + 'strange' ones, and then proceed as usual. + + So, if files or matching dir<.noinstall> files contain + filename substitutions, this function translates them into the + corresponding 'strange' names, which future passes will expand + as they always have. The resulting pathname is kept in the + file or directory's translated_filename. Another way to think + about it is that self.filename is the input filename, and + translated_filename is the output filename before expansion. + """ + # remove leaf file or dirname + head, tail = os.path.split(self.filename) + translated_path = self.translate_dirnames_in_path(head) + self.translated_filename = translated_path + + # This is a dirname - does it have a matching .noinstall with + # a substitution? If so, apply the dirname subsititution. + if not os.path.isfile(self.filename): + key = self.filename + ".noinstall" + try: + first_line = dirname_substitutions[key] + except KeyError: + self.append_translated_filename(tail) + return + self.substitute_dirname(first_line) + return + + f = open(self.filename) + first_line = f.readline() + f.close() + + # This is a normal filename not needing translation, just use + # it as-is. + if not first_line or not first_line.startswith("#"): + self.append_translated_filename(tail) + return + + # If we have a filename substitution (first line in the file + # is a FILENAME_TAG line) do the substitution now. If we have + # a dirname substitution (DIRNAME_TAG in dirname.noinstall + # meta-file), hash it so we can apply it when we see the + # matching dirname later. Otherwise we have a regular + # filename, just use it as-is. + if self.is_filename_substitution(first_line): + self.substitute_filename(first_line) + elif self.is_dirname_substitution(first_line): + self.translate_dirname(first_line) + else: + self.append_translated_filename(tail) + + def expand_file_or_dir_name(self): + """ + Expand file or dir names into codeline. Dirnames and + filenames can only have assignments or if statements. First + translate if statements into CodeLine + (dirname or filename + creation). + """ + lineno = 0 + + line = self.translated_filename[len(self.filebase):] + if line.startswith("/"): + line = line[1:] + opentag_start = -1 + + start = line.find(OPEN_TAG) + while start != -1: + if not line[start:].startswith(ASSIGN_TAG): + opentag_start = start + break + start += len(ASSIGN_TAG) + start = line.find(OPEN_TAG, start) + + if opentag_start != -1: + end = line.find(CLOSE_TAG, opentag_start) + if end == -1: + self.parse_error("No close tag found for open tag", lineno, line) + # we have a {{ tag i.e. code + tag = line[opentag_start + len(OPEN_TAG):end].strip() + if not tag.lstrip().startswith(IF_TAG): + self.parse_error("Only 'if' tags are allowed in file or directory names", + lineno, line) + self.expanded_lines.append(CodeLine(tag)) + + # everything after }} is the actual filename (possibly with assignments) + # everything before is the pathname + line = line[:opentag_start] + line[end + len(CLOSE_TAG):].strip() + + assign_start = line.find(ASSIGN_TAG) + if assign_start != -1: + assignment_tag = self.expand_assignment_tag(assign_start, line, lineno) + if isinstance(self, SubstrateFile): + assignment_tag.is_filename = True + assignment_tag.out_filebase = self.out_filebase + elif isinstance(self, SubstrateDir): + assignment_tag.is_dirname = True + assignment_tag.out_filebase = self.out_filebase + self.expanded_lines.append(assignment_tag) + return + + normal_line = NormalLine(line) + if isinstance(self, SubstrateFile): + normal_line.is_filename = True + normal_line.out_filebase = self.out_filebase + elif isinstance(self, SubstrateDir): + normal_line.is_dirname = True + normal_line.out_filebase = self.out_filebase + self.expanded_lines.append(normal_line) + + def expand(self): + """ + Expand the file or dir name first, eventually this ends up + creating the file or dir. + """ + self.translate_file_or_dir_name() + self.expand_file_or_dir_name() + + +class SubstrateFile(SubstrateBase): + """ + Container for both expanded and unexpanded substrate files. + """ + def __init__(self, filename, filebase, out_filebase): + SubstrateBase.__init__(self, filename, filebase, out_filebase) + + def read(self): + if self.raw_lines: + return + f = open(self.filename) + self.raw_lines = f.readlines() + + def expand(self): + """Expand the contents of all template tags in the file.""" + SubstrateBase.expand(self) + self.read() + + for lineno, line in enumerate(self.raw_lines): + # only first line can be a filename substitition + if lineno == 0 and line.startswith("#") and FILENAME_TAG in line: + continue # skip it - we've already expanded it + expanded_line = self.expand_tag(line, lineno + 1) # humans not 0-based + if not expanded_line: + expanded_line = NormalLine(line.rstrip()) + self.expanded_lines.append(expanded_line) + + def gen(self, context = None): + """Generate the code that generates the BSP.""" + base_indent = 0 + + indent = new_indent = base_indent + + for line in self.expanded_lines: + genline = line.gen(context) + if not genline: + continue + if isinstance(line, InputLine): + line.generated_line = genline + continue + if genline.startswith(OPEN_START): + if indent == 1: + base_indent = 1 + if indent: + if genline == BLANKLINE_STR or (not genline.startswith(NORMAL_START) + and not genline.startswith(OPEN_START)): + indent = new_indent = base_indent + if genline.endswith(":"): + new_indent = base_indent + 1 + line.generated_line = (indent * INDENT_STR) + genline + indent = new_indent + + +class SubstrateDir(SubstrateBase): + """ + Container for both expanded and unexpanded substrate dirs. + """ + def __init__(self, filename, filebase, out_filebase): + SubstrateBase.__init__(self, filename, filebase, out_filebase) + + def expand(self): + SubstrateBase.expand(self) + + def gen(self, context = None): + """Generate the code that generates the BSP.""" + indent = new_indent = 0 + for line in self.expanded_lines: + genline = line.gen(context) + if not genline: + continue + if genline.endswith(":"): + new_indent = 1 + else: + new_indent = 0 + line.generated_line = (indent * INDENT_STR) + genline + indent = new_indent + + +def expand_target(target, all_files, out_filebase): + """ + Expand the contents of all template tags in the target. This + means removing tags and categorizing or creating lines so that + future passes can process and present input lines and generate the + corresponding lines of the Python program that will be exec'ed to + actually produce the final BSP. 'all_files' includes directories. + """ + for root, dirs, files in os.walk(target): + for file in files: + if file.endswith("~") or file.endswith("#"): + continue + f = os.path.join(root, file) + sfile = SubstrateFile(f, target, out_filebase) + sfile.expand() + all_files.append(sfile) + + for dir in dirs: + d = os.path.join(root, dir) + sdir = SubstrateDir(d, target, out_filebase) + sdir.expand() + all_files.append(sdir) + + +def gen_program_machine_lines(machine, program_lines): + """ + Use the input values we got from the command line. + """ + line = "machine = \"" + machine + "\"" + program_lines.append(line) + + line = "layer_name = \"" + machine + "\"" + program_lines.append(line) + + +def sort_inputlines(input_lines): + """Sort input lines according to priority (position).""" + input_lines.sort(key = lambda l: l.prio) + + +def find_parent_dependency(lines, depends_on): + for i, line in lines: + if isinstance(line, CodeLine): + continue + if line.props["name"] == depends_on: + return i + + return -1 + + +def process_inputline_dependencies(input_lines, all_inputlines): + """If any input lines depend on others, put the others first.""" + for line in input_lines: + if isinstance(line, InputLineGroup): + group_inputlines = [] + process_inputline_dependencies(line.group, group_inputlines) + line.group = group_inputlines + all_inputlines.append(line) + continue + + if isinstance(line, CodeLine) or isinstance(line, NormalLine): + all_inputlines.append(line) + continue + + try: + depends_on = line.props["depends-on"] + depends_codeline = "if " + line.props["depends-on"] + " == \"" + line.props["depends-on-val"] + "\":" + all_inputlines.append(CodeLine(depends_codeline)) + all_inputlines.append(line) + except KeyError: + all_inputlines.append(line) + + +def conditional_filename(filename): + """ + Check if the filename itself contains a conditional statement. If + so, return a codeline for it. + """ + opentag_start = filename.find(OPEN_TAG) + + if opentag_start != -1: + if filename[opentag_start:].startswith(ASSIGN_TAG): + return None + end = filename.find(CLOSE_TAG, opentag_start) + if end == -1: + print "No close tag found for open tag in filename %s" % filename + sys.exit(1) + + # we have a {{ tag i.e. code + tag = filename[opentag_start + len(OPEN_TAG):end].strip() + if not tag.lstrip().startswith(IF_TAG): + print "Only 'if' tags are allowed in file or directory names, filename: %s" % filename + sys.exit(1) + + return CodeLine(tag) + + return None + + +class InputLineGroup(InputLine): + """ + InputLine that does nothing but group other input lines + corresponding to all the input lines in a SubstrateFile so they + can be generated as a group. prio is the only property used. + """ + def __init__(self, codeline): + InputLine.__init__(self, {}, "", 0) + self.group = [] + self.prio = sys.maxint + self.group.append(codeline) + + def append(self, line): + self.group.append(line) + if line.prio < self.prio: + self.prio = line.prio + + def len(self): + return len(self.group) + + +def gather_inputlines(files): + """ + Gather all the InputLines - we want to generate them first. + """ + all_inputlines = [] + input_lines = [] + + for file in files: + if isinstance(file, SubstrateFile): + group = None + basename = os.path.basename(file.translated_filename) + + codeline = conditional_filename(basename) + if codeline: + group = InputLineGroup(codeline) + + have_condition = False + condition_to_write = None + for line in file.expanded_lines: + if isinstance(line, CodeLine): + have_condition = True + condition_to_write = line + continue + if isinstance(line, InputLine): + if group: + if condition_to_write: + condition_to_write.prio = line.prio + condition_to_write.discard = True + group.append(condition_to_write) + condition_to_write = None + group.append(line) + else: + if condition_to_write: + condition_to_write.prio = line.prio + condition_to_write.discard = True + input_lines.append(condition_to_write) + condition_to_write = None + input_lines.append(line) + else: + if condition_to_write: + condition_to_write = None + if have_condition: + if not line.line.strip(): + line.discard = True + input_lines.append(line) + have_condition = False + + if group and group.len() > 1: + input_lines.append(group) + + sort_inputlines(input_lines) + process_inputline_dependencies(input_lines, all_inputlines) + + return all_inputlines + + +def run_program_lines(linelist, codedump): + """ + For a single file, print all the python code into a buf and execute it. + """ + buf = "\n".join(linelist) + + if codedump: + of = open("bspgen.out", "w") + of.write(buf) + of.close() + exec buf + + +def gen_target(files, context = None): + """ + Generate the python code for each file. + """ + for file in files: + file.gen(context) + + +def gen_program_header_lines(program_lines): + """ + Generate any imports we need. + """ + program_lines.append("current_file = \"\"") + + +def gen_supplied_property_vals(properties, program_lines): + """ + Generate user-specified entries for input values instead of + generating input prompts. + """ + for name, val in properties.iteritems(): + program_line = name + " = \"" + val + "\"" + program_lines.append(program_line) + + +def gen_initial_property_vals(input_lines, program_lines): + """ + Generate null or default entries for input values, so we don't + have undefined variables. + """ + for line in input_lines: + if isinstance(line, InputLineGroup): + gen_initial_property_vals(line.group, program_lines) + continue + + if isinstance(line, InputLine): + try: + name = line.props["name"] + try: + default_val = "\"" + line.props["default"] + "\"" + except: + default_val = "\"\"" + program_line = name + " = " + default_val + program_lines.append(program_line) + except KeyError: + pass + + +def gen_program_input_lines(input_lines, program_lines, context, in_group = False): + """ + Generate only the input lines used for prompting the user. For + that, we only have input lines and CodeLines that affect the next + input line. + """ + indent = new_indent = 0 + + for line in input_lines: + if isinstance(line, InputLineGroup): + gen_program_input_lines(line.group, program_lines, context, True) + continue + if not line.line.strip(): + continue + + genline = line.gen(context) + if not genline: + continue + if genline.endswith(":"): + new_indent += 1 + else: + if indent > 1 or (not in_group and indent): + new_indent -= 1 + + line.generated_line = (indent * INDENT_STR) + genline + program_lines.append(line.generated_line) + + indent = new_indent + + +def gen_program_lines(target_files, program_lines): + """ + Generate the program lines that make up the BSP generation + program. This appends the generated lines of all target_files to + program_lines, and skips input lines, which are dealt with + separately, or omitted. + """ + for file in target_files: + if file.filename.endswith("noinstall"): + continue + + for line in file.expanded_lines: + if isinstance(line, InputLine): + continue + if line.discard: + continue + + program_lines.append(line.generated_line) + + +def create_context(machine, arch, scripts_path): + """ + Create a context object for use in deferred function invocation. + """ + context = {} + + context["machine"] = machine + context["arch"] = arch + context["scripts_path"] = scripts_path + + return context + + +def capture_context(context): + """ + Create a context object for use in deferred function invocation. + """ + captured_context = {} + + captured_context["machine"] = context["machine"] + captured_context["arch"] = context["arch"] + captured_context["scripts_path"] = context["scripts_path"] + + return captured_context + + +def expand_targets(context, bsp_output_dir, expand_common=True): + """ + Expand all the tags in both the common and machine-specific + 'targets'. + + If expand_common is False, don't expand the common target (this + option is used to create special-purpose layers). + """ + target_files = [] + + machine = context["machine"] + arch = context["arch"] + scripts_path = context["scripts_path"] + + lib_path = scripts_path + '/lib' + bsp_path = lib_path + '/bsp' + arch_path = bsp_path + '/substrate/target/arch' + + if expand_common: + common = os.path.join(arch_path, "common") + expand_target(common, target_files, bsp_output_dir) + + arches = os.listdir(arch_path) + if arch not in arches or arch == "common": + print "Invalid karch, exiting\n" + sys.exit(1) + + target = os.path.join(arch_path, arch) + expand_target(target, target_files, bsp_output_dir) + + gen_target(target_files, context) + + return target_files + + +def yocto_common_create(machine, target, scripts_path, layer_output_dir, codedump, properties_file, properties_str="", expand_common=True): + """ + Common layer-creation code + + machine - user-defined machine name (if needed, will generate 'machine' var) + target - the 'target' the layer will be based on, must be one in + scripts/lib/bsp/substrate/target/arch + scripts_path - absolute path to yocto /scripts dir + layer_output_dir - dirname to create for layer + codedump - dump generated code to bspgen.out + properties_file - use values from this file if nonempty i.e no prompting + properties_str - use values from this string if nonempty i.e no prompting + expand_common - boolean, use the contents of (for bsp layers) arch/common + """ + if os.path.exists(layer_output_dir): + print "\nlayer output dir already exists, exiting. (%s)" % layer_output_dir + sys.exit(1) + + properties = None + + if properties_file: + try: + infile = open(properties_file, "r") + except IOError: + print "Couldn't open properties file %s for reading, exiting" % properties_file + sys.exit(1) + + properties = json.load(infile) + + if properties_str and not properties: + properties = json.loads(properties_str) + + os.mkdir(layer_output_dir) + + context = create_context(machine, target, scripts_path) + target_files = expand_targets(context, layer_output_dir, expand_common) + + input_lines = gather_inputlines(target_files) + + program_lines = [] + + gen_program_header_lines(program_lines) + + gen_initial_property_vals(input_lines, program_lines) + + if properties: + gen_supplied_property_vals(properties, program_lines) + + gen_program_machine_lines(machine, program_lines) + + if not properties: + gen_program_input_lines(input_lines, program_lines, context) + + gen_program_lines(target_files, program_lines) + + run_program_lines(program_lines, codedump) + + +def yocto_layer_create(layer_name, scripts_path, layer_output_dir, codedump, properties_file, properties=""): + """ + Create yocto layer + + layer_name - user-defined layer name + scripts_path - absolute path to yocto /scripts dir + layer_output_dir - dirname to create for layer + codedump - dump generated code to bspgen.out + properties_file - use values from this file if nonempty i.e no prompting + properties - use values from this string if nonempty i.e no prompting + """ + yocto_common_create(layer_name, "layer", scripts_path, layer_output_dir, codedump, properties_file, properties, False) + + print "\nNew layer created in %s.\n" % (layer_output_dir) + print "Don't forget to add it to your BBLAYERS (for details see %s\README)." % (layer_output_dir) + + +def yocto_bsp_create(machine, arch, scripts_path, bsp_output_dir, codedump, properties_file, properties=None): + """ + Create bsp + + machine - user-defined machine name + arch - the arch the bsp will be based on, must be one in + scripts/lib/bsp/substrate/target/arch + scripts_path - absolute path to yocto /scripts dir + bsp_output_dir - dirname to create for BSP + codedump - dump generated code to bspgen.out + properties_file - use values from this file if nonempty i.e no prompting + properties - use values from this string if nonempty i.e no prompting + """ + yocto_common_create(machine, arch, scripts_path, bsp_output_dir, codedump, properties_file, properties) + + print "\nNew %s BSP created in %s" % (arch, bsp_output_dir) + + +def print_dict(items, indent = 0): + """ + Print the values in a possibly nested dictionary. + """ + for key, val in items.iteritems(): + print " "*indent + "\"%s\" :" % key, + if type(val) == dict: + print "{" + print_dict(val, indent + 1) + print " "*indent + "}" + else: + print "%s" % val + + +def get_properties(input_lines): + """ + Get the complete set of properties for all the input items in the + BSP, as a possibly nested dictionary. + """ + properties = {} + + for line in input_lines: + if isinstance(line, InputLineGroup): + statement = line.group[0].line + group_properties = get_properties(line.group) + properties[statement] = group_properties + continue + + if not isinstance(line, InputLine): + continue + + if isinstance(line, ChoiceInputLine): + continue + + props = line.props + item = {} + name = props["name"] + for key, val in props.items(): + if not key == "name": + item[key] = val + properties[name] = item + + return properties + + +def yocto_layer_list_properties(arch, scripts_path, properties_file, expand_common=True): + """ + List the complete set of properties for all the input items in the + layer. If properties_file is non-null, write the complete set of + properties as a nested JSON object corresponding to a possibly + nested dictionary. + """ + context = create_context("unused", arch, scripts_path) + target_files = expand_targets(context, "unused", expand_common) + + input_lines = gather_inputlines(target_files) + + properties = get_properties(input_lines) + if properties_file: + try: + of = open(properties_file, "w") + except IOError: + print "Couldn't open properties file %s for writing, exiting" % properties_file + sys.exit(1) + + json.dump(properties, of) + + print_dict(properties) + + +def split_nested_property(property): + """ + A property name of the form x.y describes a nested property + i.e. the property y is contained within x and can be addressed + using standard JSON syntax for nested properties. Note that if a + property name itself contains '.', it should be contained in + double quotes. + """ + splittable_property = "" + in_quotes = False + for c in property: + if c == '.' and not in_quotes: + splittable_property += '\n' + continue + if c == '"': + in_quotes = not in_quotes + splittable_property += c + + split_properties = splittable_property.split('\n') + + if len(split_properties) > 1: + return split_properties + + return None + + +def find_input_line_group(substring, input_lines): + """ + Find and return the InputLineGroup containing the specified substring. + """ + for line in input_lines: + if isinstance(line, InputLineGroup): + if substring in line.group[0].line: + return line + + return None + + +def find_input_line(name, input_lines): + """ + Find the input line with the specified name. + """ + for line in input_lines: + if isinstance(line, InputLineGroup): + l = find_input_line(name, line.group) + if l: + return l + + if isinstance(line, InputLine): + try: + if line.props["name"] == name: + return line + if line.props["name"] + "_" + line.props["nameappend"] == name: + return line + except KeyError: + pass + + return None + + +def print_values(type, values_list): + """ + Print the values in the given list of values. + """ + if type == "choicelist": + for value in values_list: + print "[\"%s\", \"%s\"]" % (value[0], value[1]) + elif type == "boolean": + for value in values_list: + print "[\"%s\", \"%s\"]" % (value[0], value[1]) + + +def yocto_layer_list_property_values(arch, property, scripts_path, properties_file, expand_common=True): + """ + List the possible values for a given input property. If + properties_file is non-null, write the complete set of properties + as a JSON object corresponding to an array of possible values. + """ + context = create_context("unused", arch, scripts_path) + context["name"] = property + + target_files = expand_targets(context, "unused", expand_common) + + input_lines = gather_inputlines(target_files) + + properties = get_properties(input_lines) + + nested_properties = split_nested_property(property) + if nested_properties: + # currently the outer property of a nested property always + # corresponds to an input line group + input_line_group = find_input_line_group(nested_properties[0], input_lines) + if input_line_group: + input_lines[:] = input_line_group.group[1:] + # The inner property of a nested property name is the + # actual property name we want, so reset to that + property = nested_properties[1] + + input_line = find_input_line(property, input_lines) + if not input_line: + print "Couldn't find values for property %s" % property + return + + values_list = [] + + type = input_line.props["type"] + if type == "boolean": + values_list.append(["y", "n"]) + elif type == "choicelist" or type == "checklist": + try: + gen_fn = input_line.props["gen"] + if nested_properties: + context["filename"] = nested_properties[0] + try: + context["branches_base"] = input_line.props["branches_base"] + except KeyError: + context["branches_base"] = None + values_list = input_line.gen_choices_list(context, False) + except KeyError: + for choice in input_line.choices: + choicepair = [] + choicepair.append(choice.val) + choicepair.append(choice.desc) + values_list.append(choicepair) + + if properties_file: + try: + of = open(properties_file, "w") + except IOError: + print "Couldn't open properties file %s for writing, exiting" % properties_file + sys.exit(1) + + json.dump(values_list, of) + + print_values(type, values_list) + + +def yocto_bsp_list(args, scripts_path, properties_file): + """ + Print available architectures, or the complete list of properties + defined by the BSP, or the possible values for a particular BSP + property. + """ + if len(args) < 1: + return False + + if args[0] == "karch": + lib_path = scripts_path + '/lib' + bsp_path = lib_path + '/bsp' + arch_path = bsp_path + '/substrate/target/arch' + print "Architectures available:" + for arch in os.listdir(arch_path): + if arch == "common" or arch == "layer": + continue + print " %s" % arch + return True + else: + arch = args[0] + + if len(args) < 2 or len(args) > 3: + return False + + if len(args) == 2: + if args[1] == "properties": + yocto_layer_list_properties(arch, scripts_path, properties_file) + else: + return False + + if len(args) == 3: + if args[1] == "property": + yocto_layer_list_property_values(arch, args[2], scripts_path, properties_file) + else: + return False + + return True + + +def yocto_layer_list(args, scripts_path, properties_file): + """ + Print the complete list of input properties defined by the layer, + or the possible values for a particular layer property. + """ + if len(args) < 1: + return False + + if len(args) < 1 or len(args) > 2: + return False + + if len(args) == 1: + if args[0] == "properties": + yocto_layer_list_properties("layer", scripts_path, properties_file, False) + else: + return False + + if len(args) == 2: + if args[0] == "property": + yocto_layer_list_property_values("layer", args[1], scripts_path, properties_file, False) + else: + return False + + return True + + +def map_standard_kbranch(need_new_kbranch, new_kbranch, existing_kbranch): + """ + Return the linux-yocto bsp branch to use with the specified + kbranch. This handles the -standard variants for 3.4 and 3.8; the + other variants don't need mappings. + """ + if need_new_kbranch == "y": + kbranch = new_kbranch + else: + kbranch = existing_kbranch + + if kbranch.startswith("standard/common-pc-64"): + return "bsp/common-pc-64/common-pc-64-standard.scc" + if kbranch.startswith("standard/common-pc"): + return "bsp/common-pc/common-pc-standard.scc" + else: + return "ktypes/standard/standard.scc" + + +def map_preempt_rt_kbranch(need_new_kbranch, new_kbranch, existing_kbranch): + """ + Return the linux-yocto bsp branch to use with the specified + kbranch. This handles the -preempt-rt variants for 3.4 and 3.8; + the other variants don't need mappings. + """ + if need_new_kbranch == "y": + kbranch = new_kbranch + else: + kbranch = existing_kbranch + + if kbranch.startswith("standard/preempt-rt/common-pc-64"): + return "bsp/common-pc-64/common-pc-64-preempt-rt.scc" + if kbranch.startswith("standard/preempt-rt/common-pc"): + return "bsp/common-pc/common-pc-preempt-rt.scc" + else: + return "ktypes/preempt-rt/preempt-rt.scc" + + +def map_tiny_kbranch(need_new_kbranch, new_kbranch, existing_kbranch): + """ + Return the linux-yocto bsp branch to use with the specified + kbranch. This handles the -tiny variants for 3.4 and 3.8; the + other variants don't need mappings. + """ + if need_new_kbranch == "y": + kbranch = new_kbranch + else: + kbranch = existing_kbranch + + if kbranch.startswith("standard/tiny/common-pc"): + return "bsp/common-pc/common-pc-tiny.scc" + else: + return "ktypes/tiny/tiny.scc" diff --git a/scripts/lib/bsp/help.py b/scripts/lib/bsp/help.py new file mode 100644 index 0000000000..7c436d6be0 --- /dev/null +++ b/scripts/lib/bsp/help.py @@ -0,0 +1,1043 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2012, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module implements some basic help invocation functions along +# with the bulk of the help topic text for the Yocto BSP Tools. +# +# AUTHORS +# Tom Zanussi +# + +import subprocess +import logging + + +def subcommand_error(args): + logging.info("invalid subcommand %s" % args[0]) + + +def display_help(subcommand, subcommands): + """ + Display help for subcommand. + """ + if subcommand not in subcommands: + return False + + help = subcommands.get(subcommand, subcommand_error)[2] + pager = subprocess.Popen('less', stdin=subprocess.PIPE) + pager.communicate(help) + + return True + + +def yocto_help(args, usage_str, subcommands): + """ + Subcommand help dispatcher. + """ + if len(args) == 1 or not display_help(args[1], subcommands): + print(usage_str) + + +def invoke_subcommand(args, parser, main_command_usage, subcommands): + """ + Dispatch to subcommand handler borrowed from combo-layer. + Should use argparse, but has to work in 2.6. + """ + if not args: + logging.error("No subcommand specified, exiting") + parser.print_help() + elif args[0] == "help": + yocto_help(args, main_command_usage, subcommands) + elif args[0] not in subcommands: + logging.error("Unsupported subcommand %s, exiting\n" % (args[0])) + parser.print_help() + else: + usage = subcommands.get(args[0], subcommand_error)[1] + subcommands.get(args[0], subcommand_error)[0](args[1:], usage) + + +## +# yocto-bsp help and usage strings +## + +yocto_bsp_usage = """ + + Create a customized Yocto BSP layer. + + usage: yocto-bsp [--version] [--help] COMMAND [ARGS] + + Current 'yocto-bsp' commands are: + create Create a new Yocto BSP + list List available values for options and BSP properties + + See 'yocto-bsp help COMMAND' for more information on a specific command. +""" + +yocto_bsp_help_usage = """ + + usage: yocto-bsp help + + This command displays detailed help for the specified subcommand. +""" + +yocto_bsp_create_usage = """ + + Create a new Yocto BSP + + usage: yocto-bsp create [-o | --outdir ] + [-i | --infile ] + + This command creates a Yocto BSP based on the specified parameters. + The new BSP will be a new Yocto BSP layer contained by default within + the top-level directory specified as 'meta-bsp-name'. The -o option + can be used to place the BSP layer in a directory with a different + name and location. + + The value of the 'karch' parameter determines the set of files that + will be generated for the BSP, along with the specific set of + 'properties' that will be used to fill out the BSP-specific portions + of the BSP. The possible values for the 'karch' paramter can be + listed via 'yocto-bsp list karch'. + + NOTE: Once created, you should add your new layer to your + bblayers.conf file in order for it to be subsequently seen and + modified by the yocto-kernel tool. + + See 'yocto bsp help create' for more detailed instructions. +""" + +yocto_bsp_create_help = """ + +NAME + yocto-bsp create - Create a new Yocto BSP + +SYNOPSIS + yocto-bsp create [-o | --outdir ] + [-i | --infile ] + +DESCRIPTION + This command creates a Yocto BSP based on the specified + parameters. The new BSP will be a new Yocto BSP layer contained + by default within the top-level directory specified as + 'meta-bsp-name'. The -o option can be used to place the BSP layer + in a directory with a different name and location. + + The value of the 'karch' parameter determines the set of files + that will be generated for the BSP, along with the specific set of + 'properties' that will be used to fill out the BSP-specific + portions of the BSP. The possible values for the 'karch' paramter + can be listed via 'yocto-bsp list karch'. + + The BSP-specific properties that define the values that will be + used to generate a particular BSP can be specified on the + command-line using the -i option and supplying a JSON object + consisting of the set of name:value pairs needed by the BSP. + + If the -i option is not used, the user will be interactively + prompted for each of the required property values, which will then + be used as values for BSP generation. + + The set of properties available for a given architecture can be + listed using the 'yocto-bsp list' command. + + Specifying -c causes the Python code generated and executed to + create the BSP to be dumped to the 'bspgen.out' file in the + current directory, and is useful for debugging. + + NOTE: Once created, you should add your new layer to your + bblayers.conf file in order for it to be subsequently seen and + modified by the yocto-kernel tool. + + For example, assuming your poky repo is at /path/to/poky, your new + BSP layer is at /path/to/poky/meta-mybsp, and your build directory + is /path/to/build: + + $ gedit /path/to/build/conf/bblayers.conf + + BBLAYERS ?= " \\ + /path/to/poky/meta \\ + /path/to/poky/meta-yocto \\ + /path/to/poky/meta-mybsp \\ + " +""" + +yocto_bsp_list_usage = """ + + usage: yocto-bsp list karch + yocto-bsp list properties + [-o | --outfile ] + yocto-bsp list property + [-o | --outfile ] + + This command enumerates the complete set of possible values for a + specified option or property needed by the BSP creation process. + + The first form enumerates all the possible values that exist and can + be specified for the 'karch' parameter to the 'yocto bsp create' + command. + + The second form enumerates all the possible properties that exist and + must have values specified for them in the 'yocto bsp create' command + for the given 'karch'. + + The third form enumerates all the possible values that exist and can + be specified for any of the enumerable properties of the given + 'karch' in the 'yocto bsp create' command. + + See 'yocto-bsp help list' for more details. +""" + +yocto_bsp_list_help = """ + +NAME + yocto-bsp list - List available values for options and BSP properties + +SYNOPSIS + yocto-bsp list karch + yocto-bsp list properties + [--o | -outfile ] + yocto-bsp list property + [--o | -outfile ] + +DESCRIPTION + This command enumerates the complete set of possible values for a + specified option or property needed by the BSP creation process. + + The first form enumerates all the possible values that exist and + can be specified for the 'karch' parameter to the 'yocto bsp + create' command. Example output for the 'list karch' command: + + $ yocto-bsp list karch + Architectures available: + arm + powerpc + i386 + mips + x86_64 + qemu + + The second form enumerates all the possible properties that exist + and must have values specified for them in the 'yocto bsp create' + command for the given 'karch'. This command is mainly meant to + allow the development user interface alternatives to the default + text-based prompting interface. If the -o option is specified, + the list of properties, in addition to being displayed, will be + written to the specified file as a JSON object. In this case, the + object will consist of the set of name:value pairs corresponding + to the (possibly nested) dictionary of properties defined by the + input statements used by the BSP. Some example output for the + 'list properties' command: + + $ yocto-bsp list arm properties + "touchscreen" : { + "msg" : Does your BSP have a touchscreen? (y/N) + "default" : n + "type" : boolean + } + "uboot_loadaddress" : { + "msg" : Please specify a value for UBOOT_LOADADDRESS. + "default" : 0x80008000 + "type" : edit + "prio" : 40 + } + "kernel_choice" : { + "prio" : 10 + "default" : linux-yocto_3.2 + "depends-on" : use_default_kernel + "depends-on-val" : n + "msg" : Please choose the kernel to use in this BSP => + "type" : choicelist + "gen" : bsp.kernel.kernels + } + "if kernel_choice == "linux-yocto_3.0":" : { + "base_kbranch_linux_yocto_3_0" : { + "prio" : 20 + "default" : yocto/standard + "depends-on" : new_kbranch_linux_yocto_3_0 + "depends-on-val" : y + "msg" : Please choose a machine branch to base this BSP on => + "type" : choicelist + "gen" : bsp.kernel.all_branches + } + . + . + . + + Each entry in the output consists of the name of the input element + e.g. "touchscreen", followed by the properties defined for that + element enclosed in braces. This information should provide + sufficient information to create a complete user interface with. + Two features of the scheme provide for conditional input. First, + if a Python "if" statement appears in place of an input element + name, the set of enclosed input elements apply and should be + presented to the user only if the 'if' statement evaluates to + true. The test in the if statement will always reference another + input element in the list, which means that the element being + tested should be presented to the user before the elements + enclosed by the if block. Secondly, in a similar way, some + elements contain "depends-on" and depends-on-val" tags, which mean + that the affected input element should only be presented to the + user if the element it depends on has already been presented to + the user and the user has selected the specified value for that + element. + + The third form enumerates all the possible values that exist and + can be specified for any of the enumerable properties of the given + 'karch' in the 'yocto bsp create' command. If the -o option is + specified, the list of values for the given property, in addition + to being displayed, will be written to the specified file as a + JSON object. In this case, the object will consist of the set of + name:value pairs corresponding to the array of property values + associated with the property. + + $ yocto-bsp list i386 property xserver_choice + ["xserver_vesa", "VESA xserver support"] + ["xserver_i915", "i915 xserver support"] + + $ yocto-bsp list arm property base_kbranch_linux_yocto_3_0 + Getting branches from remote repo git://git.yoctoproject.org/linux-yocto-3.0... + ["yocto/base", "yocto/base"] + ["yocto/eg20t", "yocto/eg20t"] + ["yocto/gma500", "yocto/gma500"] + ["yocto/pvr", "yocto/pvr"] + ["yocto/standard/arm-versatile-926ejs", "yocto/standard/arm-versatile-926ejs"] + ["yocto/standard/base", "yocto/standard/base"] + ["yocto/standard/cedartrail", "yocto/standard/cedartrail"] + . + . + . + ["yocto/standard/qemu-ppc32", "yocto/standard/qemu-ppc32"] + ["yocto/standard/routerstationpro", "yocto/standard/routerstationpro"] + + The third form as well is meant mainly for developers of + alternative interfaces - it allows the developer to fetch the + possible values for a given input element on-demand. This + on-demand capability is especially valuable for elements that + require relatively expensive remote operations to fulfill, such as + the example that returns the set of branches available in a remote + git tree above. + +""" + +## +# yocto-kernel help and usage strings +## + +yocto_kernel_usage = """ + + Modify and list Yocto BSP kernel config items and patches. + + usage: yocto-kernel [--version] [--help] COMMAND [ARGS] + + Current 'yocto-kernel' commands are: + config list List the modifiable set of bare kernel config options for a BSP + config add Add or modify bare kernel config options for a BSP + config rm Remove bare kernel config options from a BSP + patch list List the patches associated with a BSP + patch add Patch the Yocto kernel for a BSP + patch rm Remove patches from a BSP + feature list List the features used by a BSP + feature add Have a BSP use a feature + feature rm Have a BSP stop using a feature + features list List the features available to BSPs + feature describe Describe a particular feature + feature create Create a new BSP-local feature + feature destroy Remove a BSP-local feature + + See 'yocto-kernel help COMMAND' for more information on a specific command. + +""" + + +yocto_kernel_help_usage = """ + + usage: yocto-kernel help + + This command displays detailed help for the specified subcommand. +""" + +yocto_kernel_config_list_usage = """ + + List the modifiable set of bare kernel config options for a BSP + + usage: yocto-kernel config list + + This command lists the 'modifiable' config items for a BSP i.e. the + items which are eligible for modification or removal by other + yocto-kernel commands. + + 'modifiable' config items are the config items contained a BSP's + user-config.cfg base config. +""" + + +yocto_kernel_config_list_help = """ + +NAME + yocto-kernel config list - List the modifiable set of bare kernel + config options for a BSP + +SYNOPSIS + yocto-kernel config list + +DESCRIPTION + This command lists the 'modifiable' config items for a BSP + i.e. the items which are eligible for modification or removal by + other yocto-kernel commands. +""" + + +yocto_kernel_config_add_usage = """ + + Add or modify bare kernel config options for a BSP + + usage: yocto-kernel config add [ ...] + + This command adds one or more CONFIG_XXX=x items to a BSP's user-config.cfg + base config. +""" + + +yocto_kernel_config_add_help = """ + +NAME + yocto-kernel config add - Add or modify bare kernel config options + for a BSP + +SYNOPSIS + yocto-kernel config add [ ...] + +DESCRIPTION + This command adds one or more CONFIG_XXX=x items to a BSP's + foo.cfg base config. + + NOTE: It's up to the user to determine whether or not the config + options being added make sense or not - this command does no + sanity checking or verification of any kind to ensure that a + config option really makes sense and will actually be set in in + the final config. For example, if a config option depends on + other config options, it will be turned off by kconfig if the + other options aren't set correctly. +""" + + +yocto_kernel_config_rm_usage = """ + + Remove bare kernel config options from a BSP + + usage: yocto-kernel config rm + + This command removes (turns off) one or more CONFIG_XXX items from a + BSP's user-config.cfg base config. + + The set of config items available to be removed by this command for a + BSP is listed and the user prompted for the specific items to remove. +""" + + +yocto_kernel_config_rm_help = """ + +NAME + yocto-kernel config rm - Remove bare kernel config options from a + BSP + +SYNOPSIS + yocto-kernel config rm + +DESCRIPTION + This command removes (turns off) one or more CONFIG_XXX items from a + BSP's user-config.cfg base config. + + The set of config items available to be removed by this command + for a BSP is listed and the user prompted for the specific items + to remove. +""" + + +yocto_kernel_patch_list_usage = """ + + List the patches associated with the kernel for a BSP + + usage: yocto-kernel patch list + + This command lists the patches associated with a BSP. + + NOTE: this only applies to patches listed in the kernel recipe's + user-patches.scc file (and currently repeated in its SRC_URI). +""" + + +yocto_kernel_patch_list_help = """ + +NAME + yocto-kernel patch list - List the patches associated with the kernel + for a BSP + +SYNOPSIS + yocto-kernel patch list + +DESCRIPTION + This command lists the patches associated with a BSP. + + NOTE: this only applies to patches listed in the kernel recipe's + user-patches.scc file (and currently repeated in its SRC_URI). +""" + + +yocto_kernel_patch_add_usage = """ + + Patch the Yocto kernel for a specific BSP + + usage: yocto-kernel patch add [ ...] + + This command adds one or more patches to a BSP's machine branch. The + patch will be added to the BSP's linux-yocto kernel user-patches.scc + file (and currently repeated in its SRC_URI) and will be guaranteed + to be applied in the order specified. +""" + + +yocto_kernel_patch_add_help = """ + +NAME + yocto-kernel patch add - Patch the Yocto kernel for a specific BSP + +SYNOPSIS + yocto-kernel patch add [ ...] + +DESCRIPTION + This command adds one or more patches to a BSP's machine branch. + The patch will be added to the BSP's linux-yocto kernel + user-patches.scc file (and currently repeated in its SRC_URI) and + will be guaranteed to be applied in the order specified. + + NOTE: It's up to the user to determine whether or not the patches + being added makes sense or not - this command does no sanity + checking or verification of any kind to ensure that a patch can + actually be applied to the BSP's kernel branch; it's assumed that + the user has already done that. +""" + + +yocto_kernel_patch_rm_usage = """ + + Remove a patch from the Yocto kernel for a specific BSP + + usage: yocto-kernel patch rm + + This command removes one or more patches from a BSP's machine branch. + The patch will be removed from the BSP's linux-yocto kernel + user-patches.scc file (and currently repeated in its SRC_URI) and + kernel SRC_URI dir. + + The set of patches available to be removed by this command for a BSP + is listed and the user prompted for the specific patches to remove. +""" + + +yocto_kernel_patch_rm_help = """ + +NAME + yocto-kernel patch rm - Remove a patch from the Yocto kernel for a specific BSP + +SYNOPSIS + yocto-kernel patch rm + +DESCRIPTION + This command removes one or more patches from a BSP's machine + branch. The patch will be removed from the BSP's linux-yocto + kernel user-patches.scc file (and currently repeated in its + SRC_URI). + + The set of patches available to be removed by this command for a + BSP is listed and the user prompted for the specific patches to + remove. +""" + +yocto_kernel_feature_list_usage = """ + + List the BSP features that are being used by a BSP + + usage: yocto-kernel feature list + + This command lists the features being used by a BSP i.e. the features + which are eligible for modification or removal by other yocto-kernel + commands. + + 'modifiable' features are the features listed in a BSP's + user-features.scc file. +""" + + +yocto_kernel_feature_list_help = """ + +NAME + yocto-kernel feature list - List the modifiable set of features + being used by a BSP + +SYNOPSIS + yocto-kernel feature list + +DESCRIPTION + This command lists the 'modifiable' features being used by a BSP + i.e. the features which are eligible for modification or removal + by other yocto-kernel commands. +""" + + +yocto_kernel_feature_add_usage = """ + + Add to or modify the list of features being used for a BSP + + usage: yocto-kernel feature add [/xxxx/yyyy/feature.scc ...] + + This command adds one or more feature items to a BSP's kernel + user-features.scc file, which is the file used to manage features in + a yocto-bsp-generated BSP. Features to be added must be specified as + fully-qualified feature names. +""" + + +yocto_kernel_feature_add_help = """ + +NAME + yocto-kernel feature add - Add to or modify the list of features + being used for a BSP + +SYNOPSIS + yocto-kernel feature add [/xxxx/yyyy/feature.scc ...] + +DESCRIPTION + This command adds one or more feature items to a BSP's + user-features.scc file, which is the file used to manage features + in a yocto-bsp-generated BSP. Features to be added must be + specified as fully-qualified feature names. +""" + + +yocto_kernel_feature_rm_usage = """ + + Remove a feature from the list of features being used for a BSP + + usage: yocto-kernel feature rm + + This command removes (turns off) one or more features from a BSP's + user-features.scc file, which is the file used to manage features in + a yocto-bsp-generated BSP. + + The set of features available to be removed by this command for a BSP + is listed and the user prompted for the specific items to remove. +""" + + +yocto_kernel_feature_rm_help = """ + +NAME + yocto-kernel feature rm - Remove a feature from the list of + features being used for a BSP + +SYNOPSIS + yocto-kernel feature rm + +DESCRIPTION + This command removes (turns off) one or more features from a BSP's + user-features.scc file, which is the file used to manage features + in a yocto-bsp-generated BSP. + + The set of features available to be removed by this command for a + BSP is listed and the user prompted for the specific items to + remove. +""" + + +yocto_kernel_available_features_list_usage = """ + + List the set of kernel features available to a BSP + + usage: yocto-kernel features list + + This command lists the complete set of kernel features available to a + BSP. This includes the features contained in linux-yocto meta + branches as well as recipe-space features defined locally to the BSP. +""" + + +yocto_kernel_available_features_list_help = """ + +NAME + yocto-kernel features list - List the set of kernel features + available to a BSP + +SYNOPSIS + yocto-kernel features list + +DESCRIPTION + This command lists the complete set of kernel features available + to a BSP. This includes the features contained in linux-yocto + meta branches as well as recipe-space features defined locally to + the BSP. +""" + + +yocto_kernel_feature_describe_usage = """ + + Print the description and compatibility information for a given kernel feature + + usage: yocto-kernel feature describe [/xxxx/yyyy/feature.scc ...] + + This command prints the description and compatibility of a specific + feature in the format 'description [compatibility]. +""" + + +yocto_kernel_feature_describe_help = """ + +NAME + yocto-kernel feature describe - print the description and + compatibility information for a given kernel feature + +SYNOPSIS + yocto-kernel feature describe [/xxxx/yyyy/feature.scc ...] + +DESCRIPTION + This command prints the description and compatibility of a + specific feature in the format 'description [compatibility]. If + the feature doesn't define a description or compatibility, a + string with generic unknown values will be printed. +""" + + +yocto_kernel_feature_create_usage = """ + + Create a recipe-space kernel feature in a BSP + + usage: yocto-kernel feature create newfeature.scc \ + "Feature Description" capabilities [ ...] [ ...] + + This command creates a new kernel feature from the bare config + options and patches specified on the command-line. +""" + + +yocto_kernel_feature_create_help = """ + +NAME + yocto-kernel feature create - create a recipe-space kernel feature + in a BSP + +SYNOPSIS + yocto-kernel feature create newfeature.scc \ + "Feature Description" capabilities [ ...] [ ...] + +DESCRIPTION + This command creates a new kernel feature from the bare config + options and patches specified on the command-line. The new + feature will be created in recipe-space, specifically in either + the kernel .bbappend's /files/cfg or /files/features subdirectory, + depending on whether or not the feature contains config items only + or config items along with patches. The named feature must end + with .scc and must not contain a feature directory to contain the + feature (this will be determined automatically), and a feature + decription in double-quotes along with a capabilities string + (which for the time being can be one of: 'all' or 'board'). +""" + + +yocto_kernel_feature_destroy_usage = """ + + Destroy a recipe-space kernel feature in a BSP + + usage: yocto-kernel feature destroy feature.scc + + This command destroys a kernel feature defined in the specified BSP's + recipe-space kernel definition. +""" + + +yocto_kernel_feature_destroy_help = """ + +NAME + yocto-kernel feature destroy feature.scc - destroy a + recipe-space kernel feature in a BSP + +SYNOPSIS + yocto-kernel feature destroy feature.scc + +DESCRIPTION + This command destroys a kernel feature defined in the specified + BSP's recipe-space kernel definition. The named feature must end + with .scc and must not contain a feature directory to contain the + feature (this will be determined automatically). If the kernel + feature is in use by a BSP, it can't be removed until the BSP + stops using it (see yocto-kernel feature rm to stop using it). +""" + +## +# yocto-layer help and usage strings +## + +yocto_layer_usage = """ + + Create a generic Yocto layer. + + usage: yocto-layer [--version] [--help] COMMAND [ARGS] + + Current 'yocto-layer' commands are: + create Create a new generic Yocto layer + list List available values for input options and properties + + See 'yocto-layer help COMMAND' for more information on a specific command. +""" + +yocto_layer_help_usage = """ + + usage: yocto-layer help + + This command displays detailed help for the specified subcommand. +""" + +yocto_layer_create_usage = """ + + Create a new generic Yocto layer + + usage: yocto-layer create [layer_priority] + [-o | --outdir ] + [-i | --infile ] + + This command creates a generic Yocto layer based on the specified + parameters. The new layer will be a new Yocto layer contained by + default within the top-level directory specified as + 'meta-layer-name'. The -o option can be used to place the layer in a + directory with a different name and location. + + If layer_priority is specified, a simple layer will be created using + the given layer priority, and the user will not be prompted for + further input. + + NOTE: Once created, you should add your new layer to your + bblayers.conf file in order for it to be subsequently seen and + modified by the yocto-kernel tool. Instructions for doing this can + be found in the README file generated in the layer's top-level + directory. + + See 'yocto layer help create' for more detailed instructions. +""" + +yocto_layer_create_help = """ + +NAME + yocto-layer create - Create a new generic Yocto layer + +SYNOPSIS + yocto-layer create [layer_priority] + [-o | --outdir ] + [-i | --infile ] + +DESCRIPTION + This command creates a generic Yocto layer based on the specified + parameters. The new layer will be a new Yocto layer contained by + default within the top-level directory specified as + 'meta-layer-name'. The -o option can be used to place the layer + in a directory with a different name and location. + + If layer_priority is specified, a simple layer will be created + using the given layer priority, and the user will not be prompted + for further input. + + The layer-specific properties that define the values that will be + used to generate the layer can be specified on the command-line + using the -i option and supplying a JSON object consisting of the + set of name:value pairs needed by the layer. + + If the -i option is not used, the user will be interactively + prompted for each of the required property values, which will then + be used as values for layer generation. + + The set of properties available can be listed using the + 'yocto-layer list' command. + + Specifying -c causes the Python code generated and executed to + create the layer to be dumped to the 'bspgen.out' file in the + current directory, and is useful for debugging. + + NOTE: Once created, you should add your new layer to your + bblayers.conf file in order for it to be subsequently seen and + modified by the yocto-kernel tool. Instructions for doing this + can be found in the README file generated in the layer's top-level + directory. + + For example, assuming your poky repo is at /path/to/poky, your new + layer is at /path/to/poky/meta-mylayer, and your build directory + is /path/to/build: + + $ gedit /path/to/build/conf/bblayers.conf + + BBLAYERS ?= " \\ + /path/to/poky/meta \\ + /path/to/poky/meta-yocto \\ + /path/to/poky/meta-mylayer \\ + " +""" + +yocto_layer_list_usage = """ + + usage: yocto-layer list properties + [-o | --outfile ] + yocto-layer list property + [-o | --outfile ] + + This command enumerates the complete set of possible values for a + specified option or property needed by the layer creation process. + + The first form enumerates all the possible properties that exist and + must have values specified for them in the 'yocto-layer create' + command. + + The second form enumerates all the possible values that exist and can + be specified for any of the enumerable properties in the 'yocto-layer + create' command. + + See 'yocto-layer help list' for more details. +""" + +yocto_layer_list_help = """ + +NAME + yocto-layer list - List available values for layer input options and properties + +SYNOPSIS + yocto-layer list properties + [--o | -outfile ] + yocto-layer list property + [--o | -outfile ] + +DESCRIPTION + This command enumerates the complete set of possible values for a + specified option or property needed by the layer creation process. + + The first form enumerates all the possible properties that exist + and must have values specified for them in the 'yocto-layer + create' command. This command is mainly meant to aid the + development of user interface alternatives to the default + text-based prompting interface. If the -o option is specified, + the list of properties, in addition to being displayed, will be + written to the specified file as a JSON object. In this case, the + object will consist of the set of name:value pairs corresponding + to the (possibly nested) dictionary of properties defined by the + input statements used by the BSP. Some example output for the + 'list properties' command: + + $ yocto-layer list properties + "example_bbappend_name" : { + "default" : example + "msg" : Please enter the name you'd like to use for your bbappend file: + "type" : edit + "prio" : 20 + "filename" : /home/trz/yocto/yocto-layer-dev/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall + } + "create_example_recipe" : { + "default" : n + "msg" : Would you like to have an example recipe created? (y/n) + "type" : boolean + "prio" : 20 + "filename" : /home/trz/yocto/yocto-layer-dev/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall + } + "example_recipe_name" : { + "default" : example + "msg" : Please enter the name you'd like to use for your example recipe: + "type" : edit + "prio" : 20 + "filename" : /home/trz/yocto/yocto-layer-dev/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall + } + "layer_priority" : { + "default" : 6 + "msg" : Please enter the layer priority you'd like to use for the layer: + "type" : edit + "prio" : 20 + "filename" : /home/trz/yocto/yocto-layer-dev/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall + } + "create_example_bbappend" : { + "default" : n + "msg" : Would you like to have an example bbappend file created? (y/n) + "type" : boolean + "prio" : 20 + "filename" : /home/trz/yocto/yocto-layer-dev/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall + } + "example_bbappend_version" : { + "default" : 0.1 + "msg" : Please enter the version number you'd like to use for your bbappend file (this should match the recipe you're appending to): + "type" : edit + "prio" : 20 + "filename" : /home/trz/yocto/yocto-layer-dev/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall + } + + Each entry in the output consists of the name of the input element + e.g. "layer_priority", followed by the properties defined for that + element enclosed in braces. This information should provide + sufficient information to create a complete user interface. Two + features of the scheme provide for conditional input. First, if a + Python "if" statement appears in place of an input element name, + the set of enclosed input elements apply and should be presented + to the user only if the 'if' statement evaluates to true. The + test in the if statement will always reference another input + element in the list, which means that the element being tested + should be presented to the user before the elements enclosed by + the if block. Secondly, in a similar way, some elements contain + "depends-on" and depends-on-val" tags, which mean that the + affected input element should only be presented to the user if the + element it depends on has already been presented to the user and + the user has selected the specified value for that element. + + The second form enumerates all the possible values that exist and + can be specified for any of the enumerable properties in the + 'yocto-layer create' command. If the -o option is specified, the + list of values for the given property, in addition to being + displayed, will be written to the specified file as a JSON object. + In this case, the object will consist of the set of name:value + pairs corresponding to the array of property values associated + with the property. + + $ yocto-layer list property layer_priority + [no output - layer_priority is a text field that has no enumerable values] + + The second form as well is meant mainly for developers of + alternative interfaces - it allows the developer to fetch the + possible values for a given input element on-demand. This + on-demand capability is especially valuable for elements that + require relatively expensive remote operations to fulfill, such as + the example that returns the set of branches available in a remote + git tree above. + +""" + +## +# test code +## + +test_bsp_properties = { + 'smp': 'yes', + 'touchscreen': 'yes', + 'keyboard': 'no', + 'xserver': 'yes', + 'xserver_choice': 'xserver-i915', + 'features': ['goodfeature', 'greatfeature'], + 'tunefile': 'tune-quark', +} + diff --git a/scripts/lib/bsp/kernel.py b/scripts/lib/bsp/kernel.py new file mode 100644 index 0000000000..ba68b60fcb --- /dev/null +++ b/scripts/lib/bsp/kernel.py @@ -0,0 +1,1071 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2012, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module implements the kernel-related functions used by +# 'yocto-kernel' to manage kernel config items and patches for Yocto +# BSPs. +# +# AUTHORS +# Tom Zanussi +# + +import sys +import os +import shutil +from tags import * +import glob +import subprocess +from engine import create_context + + +def find_bblayers(): + """ + Find and return a sanitized list of the layers found in BBLAYERS. + """ + try: + builddir = os.environ["BUILDDIR"] + except KeyError: + print "BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)" + sys.exit(1) + bblayers_conf = os.path.join(builddir, "conf/bblayers.conf") + + layers = [] + + bitbake_env_cmd = "bitbake -e" + bitbake_env_lines = subprocess.Popen(bitbake_env_cmd, shell=True, + stdout=subprocess.PIPE).stdout.read() + + if not bitbake_env_lines: + print "Couldn't get '%s' output, exiting." % bitbake_env_cmd + sys.exit(1) + + for line in bitbake_env_lines.split('\n'): + bblayers = get_line_val(line, "BBLAYERS") + if (bblayers): + break + + if not bblayers: + print "Couldn't find BBLAYERS in %s output, exiting." % \ + bitbake_env_cmd + sys.exit(1) + + raw_layers = bblayers.split() + + for layer in raw_layers: + if layer == 'BBLAYERS' or '=' in layer: + continue + layers.append(layer) + + return layers + + +def get_line_val(line, key): + """ + Extract the value from the VAR="val" string + """ + if line.startswith(key + "="): + stripped_line = line.split('=')[1] + stripped_line = stripped_line.replace('\"', '') + return stripped_line + return None + + +def find_meta_layer(): + """ + Find and return the meta layer in BBLAYERS. + """ + layers = find_bblayers() + + for layer in layers: + if layer.endswith("meta"): + return layer + + return None + + +def find_bsp_layer(machine): + """ + Find and return a machine's BSP layer in BBLAYERS. + """ + layers = find_bblayers() + + for layer in layers: + if layer.endswith(machine): + return layer + + print "Unable to find the BSP layer for machine %s." % machine + print "Please make sure it is listed in bblayers.conf" + sys.exit(1) + + +def gen_choices_str(choices): + """ + Generate a numbered list of choices from a list of choices for + display to the user. + """ + choices_str = "" + + for i, choice in enumerate(choices): + choices_str += "\t" + str(i + 1) + ") " + choice + "\n" + + return choices_str + + +def open_user_file(scripts_path, machine, userfile, mode): + """ + Find one of the user files (user-config.cfg, user-patches.scc) + associated with the machine (could be in files/, + linux-yocto-custom/, etc). Returns the open file if found, None + otherwise. + + The caller is responsible for closing the file returned. + """ + layer = find_bsp_layer(machine) + linuxdir = os.path.join(layer, "recipes-kernel/linux") + linuxdir_list = os.listdir(linuxdir) + for fileobj in linuxdir_list: + fileobj_path = os.path.join(linuxdir, fileobj) + if os.path.isdir(fileobj_path): + userfile_name = os.path.join(fileobj_path, userfile) + try: + f = open(userfile_name, mode) + return f + except IOError: + continue + return None + + +def read_config_items(scripts_path, machine): + """ + Find and return a list of config items (CONFIG_XXX) in a machine's + user-defined config fragment [${machine}-user-config.cfg]. + """ + config_items = [] + + f = open_user_file(scripts_path, machine, machine+"-user-config.cfg", "r") + lines = f.readlines() + for line in lines: + s = line.strip() + if s and not s.startswith("#"): + config_items.append(s) + f.close() + + return config_items + + +def write_config_items(scripts_path, machine, config_items): + """ + Write (replace) the list of config items (CONFIG_XXX) in a + machine's user-defined config fragment [${machine}=user-config.cfg]. + """ + f = open_user_file(scripts_path, machine, machine+"-user-config.cfg", "w") + for item in config_items: + f.write(item + "\n") + f.close() + + kernel_contents_changed(scripts_path, machine) + + +def yocto_kernel_config_list(scripts_path, machine): + """ + Display the list of config items (CONFIG_XXX) in a machine's + user-defined config fragment [${machine}-user-config.cfg]. + """ + config_items = read_config_items(scripts_path, machine) + + print "The current set of machine-specific kernel config items for %s is:" % machine + print gen_choices_str(config_items) + + +def yocto_kernel_config_rm(scripts_path, machine): + """ + Display the list of config items (CONFIG_XXX) in a machine's + user-defined config fragment [${machine}-user-config.cfg], prompt the user + for one or more to remove, and remove them. + """ + config_items = read_config_items(scripts_path, machine) + + print "Specify the kernel config items to remove:" + input = raw_input(gen_choices_str(config_items)) + rm_choices = input.split() + rm_choices.sort() + + removed = [] + + for choice in reversed(rm_choices): + try: + idx = int(choice) - 1 + except ValueError: + print "Invalid choice (%s), exiting" % choice + sys.exit(1) + if idx < 0 or idx >= len(config_items): + print "Invalid choice (%d), exiting" % (idx + 1) + sys.exit(1) + removed.append(config_items.pop(idx)) + + write_config_items(scripts_path, machine, config_items) + + print "Removed items:" + for r in removed: + print "\t%s" % r + + +def yocto_kernel_config_add(scripts_path, machine, config_items): + """ + Add one or more config items (CONFIG_XXX) to a machine's + user-defined config fragment [${machine}-user-config.cfg]. + """ + new_items = [] + dup_items = [] + + cur_items = read_config_items(scripts_path, machine) + + for item in config_items: + if not item.startswith("CONFIG") or (not "=y" in item and not "=m" in item): + print "Invalid config item (%s), exiting" % item + sys.exit(1) + if item not in cur_items and item not in new_items: + new_items.append(item) + else: + dup_items.append(item) + + if len(new_items) > 0: + cur_items.extend(new_items) + write_config_items(scripts_path, machine, cur_items) + print "Added item%s:" % ("" if len(new_items)==1 else "s") + for n in new_items: + print "\t%s" % n + + if len(dup_items) > 0: + output="The following item%s already exist%s in the current configuration, ignoring %s:" % \ + (("","s", "it") if len(dup_items)==1 else ("s", "", "them" )) + print output + for n in dup_items: + print "\t%s" % n + +def find_current_kernel(bsp_layer, machine): + """ + Determine the kernel and version currently being used in the BSP. + """ + machine_conf = os.path.join(bsp_layer, "conf/machine/" + machine + ".conf") + + preferred_kernel = preferred_kernel_version = preferred_version_varname = None + + f = open(machine_conf, "r") + lines = f.readlines() + for line in lines: + if line.strip().startswith("PREFERRED_PROVIDER_virtual/kernel"): + preferred_kernel = line.split()[-1] + preferred_kernel = preferred_kernel.replace('\"','') + preferred_version_varname = "PREFERRED_VERSION_" + preferred_kernel + if preferred_version_varname and line.strip().startswith(preferred_version_varname): + preferred_kernel_version = line.split()[-1] + preferred_kernel_version = preferred_kernel_version.replace('\"','') + preferred_kernel_version = preferred_kernel_version.replace('%','') + + if preferred_kernel and preferred_kernel_version: + return preferred_kernel + "_" + preferred_kernel_version + elif preferred_kernel: + return preferred_kernel + + +def find_filesdir(scripts_path, machine): + """ + Find the name of the 'files' dir associated with the machine + (could be in files/, linux-yocto-custom/, etc). Returns the name + of the files dir if found, None otherwise. + """ + layer = find_bsp_layer(machine) + filesdir = None + linuxdir = os.path.join(layer, "recipes-kernel/linux") + linuxdir_list = os.listdir(linuxdir) + for fileobj in linuxdir_list: + fileobj_path = os.path.join(linuxdir, fileobj) + if os.path.isdir(fileobj_path): + # this could be files/ or linux-yocto-custom/, we have no way of distinguishing + # so we take the first (and normally only) dir we find as the 'filesdir' + filesdir = fileobj_path + + return filesdir + + +def read_patch_items(scripts_path, machine): + """ + Find and return a list of patch items in a machine's user-defined + patch list [${machine}-user-patches.scc]. + """ + patch_items = [] + + f = open_user_file(scripts_path, machine, machine+"-user-patches.scc", "r") + lines = f.readlines() + for line in lines: + s = line.strip() + if s and not s.startswith("#"): + fields = s.split() + if not fields[0] == "patch": + continue + patch_items.append(fields[1]) + f.close() + + return patch_items + + +def write_patch_items(scripts_path, machine, patch_items): + """ + Write (replace) the list of patches in a machine's user-defined + patch list [${machine}-user-patches.scc]. + """ + f = open_user_file(scripts_path, machine, machine+"-user-patches.scc", "w") + for item in patch_items: + f.write("patch " + item + "\n") + f.close() + + kernel_contents_changed(scripts_path, machine) + + +def yocto_kernel_patch_list(scripts_path, machine): + """ + Display the list of patches in a machine's user-defined patch list + [${machine}-user-patches.scc]. + """ + patches = read_patch_items(scripts_path, machine) + + print "The current set of machine-specific patches for %s is:" % machine + print gen_choices_str(patches) + + +def yocto_kernel_patch_rm(scripts_path, machine): + """ + Remove one or more patches from a machine's user-defined patch + list [${machine}-user-patches.scc]. + """ + patches = read_patch_items(scripts_path, machine) + + print "Specify the patches to remove:" + input = raw_input(gen_choices_str(patches)) + rm_choices = input.split() + rm_choices.sort() + + removed = [] + + filesdir = find_filesdir(scripts_path, machine) + if not filesdir: + print "Couldn't rm patch(es) since we couldn't find a 'files' dir" + sys.exit(1) + + for choice in reversed(rm_choices): + try: + idx = int(choice) - 1 + except ValueError: + print "Invalid choice (%s), exiting" % choice + sys.exit(1) + if idx < 0 or idx >= len(patches): + print "Invalid choice (%d), exiting" % (idx + 1) + sys.exit(1) + filesdir_patch = os.path.join(filesdir, patches[idx]) + if os.path.isfile(filesdir_patch): + os.remove(filesdir_patch) + removed.append(patches[idx]) + patches.pop(idx) + + write_patch_items(scripts_path, machine, patches) + + print "Removed patches:" + for r in removed: + print "\t%s" % r + + +def yocto_kernel_patch_add(scripts_path, machine, patches): + """ + Add one or more patches to a machine's user-defined patch list + [${machine}-user-patches.scc]. + """ + existing_patches = read_patch_items(scripts_path, machine) + + for patch in patches: + if os.path.basename(patch) in existing_patches: + print "Couldn't add patch (%s) since it's already been added" % os.path.basename(patch) + sys.exit(1) + + filesdir = find_filesdir(scripts_path, machine) + if not filesdir: + print "Couldn't add patch (%s) since we couldn't find a 'files' dir to add it to" % os.path.basename(patch) + sys.exit(1) + + new_patches = [] + + for patch in patches: + if not os.path.isfile(patch): + print "Couldn't find patch (%s), exiting" % patch + sys.exit(1) + basename = os.path.basename(patch) + filesdir_patch = os.path.join(filesdir, basename) + shutil.copyfile(patch, filesdir_patch) + new_patches.append(basename) + + cur_items = read_patch_items(scripts_path, machine) + cur_items.extend(new_patches) + write_patch_items(scripts_path, machine, cur_items) + + print "Added patches:" + for n in new_patches: + print "\t%s" % n + + +def inc_pr(line): + """ + Add 1 to the PR value in the given bbappend PR line. For the PR + lines in kernel .bbappends after modifications. Handles PRs of + the form PR := "${PR}.1" as well as PR = "r0". + """ + idx = line.find("\"") + + pr_str = line[idx:] + pr_str = pr_str.replace('\"','') + fields = pr_str.split('.') + if len(fields) > 1: + fields[1] = str(int(fields[1]) + 1) + pr_str = "\"" + '.'.join(fields) + "\"\n" + else: + pr_val = pr_str[1:] + pr_str = "\"" + "r" + str(int(pr_val) + 1) + "\"\n" + idx2 = line.find("\"", idx + 1) + line = line[:idx] + pr_str + + return line + + +def kernel_contents_changed(scripts_path, machine): + """ + Do what we need to do to notify the system that the kernel + recipe's contents have changed. + """ + layer = find_bsp_layer(machine) + + kernel = find_current_kernel(layer, machine) + if not kernel: + print "Couldn't determine the kernel for this BSP, exiting." + sys.exit(1) + + kernel_bbfile = os.path.join(layer, "recipes-kernel/linux/" + kernel + ".bbappend") + if not os.path.isfile(kernel_bbfile): + kernel_bbfile = os.path.join(layer, "recipes-kernel/linux/" + kernel + ".bb") + if not os.path.isfile(kernel_bbfile): + return + kernel_bbfile_prev = kernel_bbfile + ".prev" + shutil.copyfile(kernel_bbfile, kernel_bbfile_prev) + + ifile = open(kernel_bbfile_prev, "r") + ofile = open(kernel_bbfile, "w") + ifile_lines = ifile.readlines() + for ifile_line in ifile_lines: + if ifile_line.strip().startswith("PR"): + ifile_line = inc_pr(ifile_line) + ofile.write(ifile_line) + ofile.close() + ifile.close() + + +def kernels(context): + """ + Return the list of available kernels in the BSP i.e. corresponding + to the kernel .bbappends found in the layer. + """ + archdir = os.path.join(context["scripts_path"], "lib/bsp/substrate/target/arch/" + context["arch"]) + kerndir = os.path.join(archdir, "recipes-kernel/linux") + bbglob = os.path.join(kerndir, "*.bbappend") + + bbappends = glob.glob(bbglob) + + kernels = [] + + for kernel in bbappends: + filename = os.path.splitext(os.path.basename(kernel))[0] + idx = filename.find(CLOSE_TAG) + if idx != -1: + filename = filename[idx + len(CLOSE_TAG):].strip() + kernels.append(filename) + + kernels.append("custom") + + return kernels + + +def extract_giturl(file): + """ + Extract the git url of the kernel repo from the kernel recipe's + SRC_URI. + """ + url = None + f = open(file, "r") + lines = f.readlines() + for line in lines: + line = line.strip() + if line.startswith("SRC_URI"): + line = line[len("SRC_URI"):].strip() + if line.startswith("="): + line = line[1:].strip() + if line.startswith("\""): + line = line[1:].strip() + prot = "git" + for s in line.split(";"): + if s.startswith("git://"): + url = s + if s.startswith("protocol="): + prot = s.split("=")[1] + if url: + url = prot + url[3:] + return url + + +def find_giturl(context): + """ + Find the git url of the kernel repo from the kernel recipe's + SRC_URI. + """ + name = context["name"] + filebase = context["filename"] + scripts_path = context["scripts_path"] + + meta_layer = find_meta_layer() + + kerndir = os.path.join(meta_layer, "recipes-kernel/linux") + bbglob = os.path.join(kerndir, "*.bb") + bbs = glob.glob(bbglob) + for kernel in bbs: + filename = os.path.splitext(os.path.basename(kernel))[0] + if filename in filebase: + giturl = extract_giturl(kernel) + return giturl + + return None + + +def read_features(scripts_path, machine): + """ + Find and return a list of features in a machine's user-defined + features fragment [${machine}-user-features.scc]. + """ + features = [] + + f = open_user_file(scripts_path, machine, machine+"-user-features.scc", "r") + lines = f.readlines() + for line in lines: + s = line.strip() + if s and not s.startswith("#"): + feature_include = s.split() + features.append(feature_include[1].strip()) + f.close() + + return features + + +def write_features(scripts_path, machine, features): + """ + Write (replace) the list of feature items in a + machine's user-defined features fragment [${machine}=user-features.cfg]. + """ + f = open_user_file(scripts_path, machine, machine+"-user-features.scc", "w") + for item in features: + f.write("include " + item + "\n") + f.close() + + kernel_contents_changed(scripts_path, machine) + + +def yocto_kernel_feature_list(scripts_path, machine): + """ + Display the list of features used in a machine's user-defined + features fragment [${machine}-user-features.scc]. + """ + features = read_features(scripts_path, machine) + + print "The current set of machine-specific features for %s is:" % machine + print gen_choices_str(features) + + +def yocto_kernel_feature_rm(scripts_path, machine): + """ + Display the list of features used in a machine's user-defined + features fragment [${machine}-user-features.scc], prompt the user + for one or more to remove, and remove them. + """ + features = read_features(scripts_path, machine) + + print "Specify the features to remove:" + input = raw_input(gen_choices_str(features)) + rm_choices = input.split() + rm_choices.sort() + + removed = [] + + for choice in reversed(rm_choices): + try: + idx = int(choice) - 1 + except ValueError: + print "Invalid choice (%s), exiting" % choice + sys.exit(1) + if idx < 0 or idx >= len(features): + print "Invalid choice (%d), exiting" % (idx + 1) + sys.exit(1) + removed.append(features.pop(idx)) + + write_features(scripts_path, machine, features) + + print "Removed features:" + for r in removed: + print "\t%s" % r + + +def yocto_kernel_feature_add(scripts_path, machine, features): + """ + Add one or more features a machine's user-defined features + fragment [${machine}-user-features.scc]. + """ + new_items = [] + + for item in features: + if not item.endswith(".scc"): + print "Invalid feature (%s), exiting" % item + sys.exit(1) + new_items.append(item) + + cur_items = read_features(scripts_path, machine) + cur_items.extend(new_items) + + write_features(scripts_path, machine, cur_items) + + print "Added features:" + for n in new_items: + print "\t%s" % n + + +def find_feature_url(git_url): + """ + Find the url of the kern-features.rc kernel for the kernel repo + specified from the BSP's kernel recipe SRC_URI. + """ + feature_url = "" + if git_url.startswith("git://"): + git_url = git_url[len("git://"):].strip() + s = git_url.split("/") + if s[1].endswith(".git"): + s[1] = s[1][:len(s[1]) - len(".git")] + feature_url = "http://" + s[0] + "/cgit/cgit.cgi/" + s[1] + \ + "/plain/meta/cfg/kern-features.rc?h=meta" + + return feature_url + + +def find_feature_desc(lines): + """ + Find the feature description and compatibility in the passed-in + set of lines. Returns a string string of the form 'desc + [compat]'. + """ + desc = "no description available" + compat = "unknown" + + for line in lines: + idx = line.find("KFEATURE_DESCRIPTION") + if idx != -1: + desc = line[idx + len("KFEATURE_DESCRIPTION"):].strip() + if desc.startswith("\""): + desc = desc[1:] + if desc.endswith("\""): + desc = desc[:-1] + else: + idx = line.find("KFEATURE_COMPATIBILITY") + if idx != -1: + compat = line[idx + len("KFEATURE_COMPATIBILITY"):].strip() + + return desc + " [" + compat + "]" + + +def print_feature_descs(layer, feature_dir): + """ + Print the feature descriptions for the features in feature_dir. + """ + kernel_files_features = os.path.join(layer, "recipes-kernel/linux/files/" + + feature_dir) + for root, dirs, files in os.walk(kernel_files_features): + for file in files: + if file.endswith("~") or file.endswith("#"): + continue + if file.endswith(".scc"): + fullpath = os.path.join(layer, "recipes-kernel/linux/files/" + + feature_dir + "/" + file) + f = open(fullpath) + feature_desc = find_feature_desc(f.readlines()) + print feature_dir + "/" + file + ": " + feature_desc + + +def yocto_kernel_available_features_list(scripts_path, machine): + """ + Display the list of all the kernel features available for use in + BSPs, as gathered from the set of feature sources. + """ + layer = find_bsp_layer(machine) + kernel = find_current_kernel(layer, machine) + if not kernel: + print "Couldn't determine the kernel for this BSP, exiting." + sys.exit(1) + + context = create_context(machine, "arch", scripts_path) + context["name"] = "name" + context["filename"] = kernel + giturl = find_giturl(context) + feature_url = find_feature_url(giturl) + + feature_cmd = "wget -q -O - " + feature_url + tmp = subprocess.Popen(feature_cmd, shell=True, stdout=subprocess.PIPE).stdout.read() + + print "The current set of kernel features available to %s is:\n" % machine + + if tmp: + tmpline = tmp.split("\n") + in_kernel_options = False + for line in tmpline: + if not "=" in line: + if in_kernel_options: + break + if "kernel-options" in line: + in_kernel_options = True + continue + if in_kernel_options: + feature_def = line.split("=") + feature_type = feature_def[0].strip() + feature = feature_def[1].strip() + desc = get_feature_desc(giturl, feature) + print "%s: %s" % (feature, desc) + + print "[local]" + + print_feature_descs(layer, "cfg") + print_feature_descs(layer, "features") + + +def find_feature_desc_url(git_url, feature): + """ + Find the url of the kernel feature in the kernel repo specified + from the BSP's kernel recipe SRC_URI. + """ + feature_desc_url = "" + if git_url.startswith("git://"): + git_url = git_url[len("git://"):].strip() + s = git_url.split("/") + if s[1].endswith(".git"): + s[1] = s[1][:len(s[1]) - len(".git")] + feature_desc_url = "http://" + s[0] + "/cgit/cgit.cgi/" + s[1] + \ + "/plain/meta/cfg/kernel-cache/" + feature + "?h=meta" + + return feature_desc_url + + +def get_feature_desc(git_url, feature): + """ + Return a feature description of the form 'description [compatibility] + BSPs, as gathered from the set of feature sources. + """ + feature_desc_url = find_feature_desc_url(git_url, feature) + feature_desc_cmd = "wget -q -O - " + feature_desc_url + tmp = subprocess.Popen(feature_desc_cmd, shell=True, stdout=subprocess.PIPE).stdout.read() + + return find_feature_desc(tmp.split("\n")) + + +def yocto_kernel_feature_describe(scripts_path, machine, feature): + """ + Display the description of a specific kernel feature available for + use in a BSP. + """ + layer = find_bsp_layer(machine) + + kernel = find_current_kernel(layer, machine) + if not kernel: + print "Couldn't determine the kernel for this BSP, exiting." + sys.exit(1) + + context = create_context(machine, "arch", scripts_path) + context["name"] = "name" + context["filename"] = kernel + giturl = find_giturl(context) + + desc = get_feature_desc(giturl, feature) + + print desc + + +def check_feature_name(feature_name): + """ + Sanity-check the feature name for create/destroy. Return False if not OK. + """ + if not feature_name.endswith(".scc"): + print "Invalid feature name (must end with .scc) [%s], exiting" % feature_name + return False + + if "/" in feature_name: + print "Invalid feature name (don't specify directory) [%s], exiting" % feature_name + return False + + return True + + +def check_create_input(feature_items): + """ + Sanity-check the create input. Return False if not OK. + """ + if not check_feature_name(feature_items[0]): + return False + + if feature_items[1].endswith(".patch") or feature_items[1].startswith("CONFIG_"): + print "Missing description and/or compatibilty [%s], exiting" % feature_items[1] + return False + + if feature_items[2].endswith(".patch") or feature_items[2].startswith("CONFIG_"): + print "Missing description and/or compatibility [%s], exiting" % feature_items[1] + return False + + return True + + +def yocto_kernel_feature_create(scripts_path, machine, feature_items): + """ + Create a recipe-space kernel feature in a BSP. + """ + if not check_create_input(feature_items): + sys.exit(1) + + feature = feature_items[0] + feature_basename = feature.split(".")[0] + feature_description = feature_items[1] + feature_compat = feature_items[2] + + patches = [] + cfg_items = [] + + for item in feature_items[3:]: + if item.endswith(".patch"): + patches.append(item) + elif item.startswith("CONFIG"): + if ("=y" in item or "=m" in item): + cfg_items.append(item) + else: + print "Invalid feature item (must be .patch or CONFIG_*) [%s], exiting" % item + sys.exit(1) + + feature_dirname = "cfg" + if patches: + feature_dirname = "features" + + filesdir = find_filesdir(scripts_path, machine) + if not filesdir: + print "Couldn't add feature (%s), no 'files' dir found" % feature + sys.exit(1) + + featdir = os.path.join(filesdir, feature_dirname) + if not os.path.exists(featdir): + os.mkdir(featdir) + + for patch in patches: + if not os.path.isfile(patch): + print "Couldn't find patch (%s), exiting" % patch + sys.exit(1) + basename = os.path.basename(patch) + featdir_patch = os.path.join(featdir, basename) + shutil.copyfile(patch, featdir_patch) + + new_cfg_filename = os.path.join(featdir, feature_basename + ".cfg") + new_cfg_file = open(new_cfg_filename, "w") + for cfg_item in cfg_items: + new_cfg_file.write(cfg_item + "\n") + new_cfg_file.close() + + new_feature_filename = os.path.join(featdir, feature_basename + ".scc") + new_feature_file = open(new_feature_filename, "w") + new_feature_file.write("define KFEATURE_DESCRIPTION \"" + feature_description + "\"\n") + new_feature_file.write("define KFEATURE_COMPATIBILITY " + feature_compat + "\n\n") + + for patch in patches: + patch_dir, patch_file = os.path.split(patch) + new_feature_file.write("patch " + patch_file + "\n") + + new_feature_file.write("kconf non-hardware " + feature_basename + ".cfg\n") + new_feature_file.close() + + print "Added feature:" + print "\t%s" % feature_dirname + "/" + feature + + +def feature_in_use(scripts_path, machine, feature): + """ + Determine whether the specified feature is in use by the BSP. + Return True if so, False otherwise. + """ + features = read_features(scripts_path, machine) + for f in features: + if f == feature: + return True + return False + + +def feature_remove(scripts_path, machine, feature): + """ + Remove the specified feature from the available recipe-space + features defined for the BSP. + """ + features = read_features(scripts_path, machine) + new_features = [] + for f in features: + if f == feature: + continue + new_features.append(f) + write_features(scripts_path, machine, new_features) + + +def yocto_kernel_feature_destroy(scripts_path, machine, feature): + """ + Remove a recipe-space kernel feature from a BSP. + """ + if not check_feature_name(feature): + sys.exit(1) + + if feature_in_use(scripts_path, machine, "features/" + feature) or \ + feature_in_use(scripts_path, machine, "cfg/" + feature): + print "Feature %s is in use (use 'feature rm' to un-use it first), exiting" % feature + sys.exit(1) + + filesdir = find_filesdir(scripts_path, machine) + if not filesdir: + print "Couldn't destroy feature (%s), no 'files' dir found" % feature + sys.exit(1) + + feature_dirname = "features" + featdir = os.path.join(filesdir, feature_dirname) + if not os.path.exists(featdir): + print "Couldn't find feature directory (%s)" % feature_dirname + sys.exit(1) + + feature_fqn = os.path.join(featdir, feature) + if not os.path.exists(feature_fqn): + feature_dirname = "cfg" + featdir = os.path.join(filesdir, feature_dirname) + if not os.path.exists(featdir): + print "Couldn't find feature directory (%s)" % feature_dirname + sys.exit(1) + feature_fqn = os.path.join(featdir, feature_filename) + if not os.path.exists(feature_fqn): + print "Couldn't find feature (%s)" % feature + sys.exit(1) + + f = open(feature_fqn, "r") + lines = f.readlines() + for line in lines: + s = line.strip() + if s.startswith("patch ") or s.startswith("kconf "): + split_line = s.split() + filename = os.path.join(featdir, split_line[-1]) + if os.path.exists(filename): + os.remove(filename) + f.close() + os.remove(feature_fqn) + + feature_remove(scripts_path, machine, feature) + + print "Removed feature:" + print "\t%s" % feature_dirname + "/" + feature + + +def base_branches(context): + """ + Return a list of the base branches found in the kernel git repo. + """ + giturl = find_giturl(context) + + print "Getting branches from remote repo %s..." % giturl + + gitcmd = "git ls-remote %s *heads* 2>&1" % (giturl) + tmp = subprocess.Popen(gitcmd, shell=True, stdout=subprocess.PIPE).stdout.read() + + branches = [] + + if tmp: + tmpline = tmp.split("\n") + for line in tmpline: + if len(line)==0: + break; + if not line.endswith("base"): + continue; + idx = line.find("refs/heads/") + kbranch = line[idx + len("refs/heads/"):] + if kbranch.find("/") == -1 and kbranch.find("base") == -1: + continue + idx = kbranch.find("base") + branches.append(kbranch[:idx - 1]) + + return branches + + +def all_branches(context): + """ + Return a list of all the branches found in the kernel git repo. + """ + giturl = find_giturl(context) + + print "Getting branches from remote repo %s..." % giturl + + gitcmd = "git ls-remote %s *heads* 2>&1" % (giturl) + tmp = subprocess.Popen(gitcmd, shell=True, stdout=subprocess.PIPE).stdout.read() + + branches = [] + + base_prefixes = None + + try: + branches_base = context["branches_base"] + if branches_base: + base_prefixes = branches_base.split(":") + except KeyError: + pass + + arch = context["arch"] + + if tmp: + tmpline = tmp.split("\n") + for line in tmpline: + if len(line)==0: + break; + idx = line.find("refs/heads/") + kbranch = line[idx + len("refs/heads/"):] + kbranch_prefix = kbranch.rsplit("/", 1)[0] + + if base_prefixes: + for base_prefix in base_prefixes: + if kbranch_prefix == base_prefix: + branches.append(kbranch) + continue + + if (kbranch.find("/") != -1 and + (kbranch.find("standard") != -1 or kbranch.find("base") != -1) or + kbranch == "base"): + branches.append(kbranch) + continue + + return branches diff --git a/scripts/lib/bsp/substrate/target/arch/arm/.gitignore b/scripts/lib/bsp/substrate/target/arch/arm/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall b/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall new file mode 100644 index 0000000000..b442d02d57 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=machine}} diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf b/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf new file mode 100644 index 0000000000..bc52893e2a --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf @@ -0,0 +1,34 @@ +# yocto-bsp-filename {{ if xserver == "y": }} this +Section "Module" + Load "extmod" + Load "dbe" + Load "glx" + Load "freetype" + Load "type1" + Load "record" + Load "dri" +EndSection + +Section "Monitor" + Identifier "Builtin Default Monitor" +EndSection + +Section "Device" + Identifier "Builtin Default fbdev Device 0" + Driver "omapfb" +EndSection + +Section "Screen" + Identifier "Builtin Default fbdev Screen 0" + Device "Builtin Default fbdev Device 0" + Monitor "Builtin Default Monitor" +EndSection + +Section "ServerLayout" + Identifier "Builtin Default Layout" + Screen "Builtin Default fbdev Screen 0" +EndSection + +Section "ServerFlags" + Option "DontZap" "0" +EndSection diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend b/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend new file mode 100644 index 0000000000..30830031ed --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend @@ -0,0 +1,2 @@ +# yocto-bsp-filename {{ if xserver == "y": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files.noinstall b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files.noinstall new file mode 100644 index 0000000000..1e0d92c55c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if kernel_choice != "custom": }} files diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-non_hardware.cfg b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-non_hardware.cfg new file mode 100644 index 0000000000..9bfc90c6f2 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-non_hardware.cfg @@ -0,0 +1,31 @@ +# yocto-bsp-filename {{=machine}}-non_hardware.cfg +# +# Miscellaneous filesystems +# +CONFIG_NFS_DEF_FILE_IO_SIZE=1024 + +# +# Multiple Device Support +# +# CONFIG_MD is not set + +# Kernel Features +# +CONFIG_NO_HZ=y + +# +# CPUIdle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# Kernel hacking +# +CONFIG_DEBUG_FS=y + +# +# Power management options +# +CONFIG_PM_DEBUG=y diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-preempt-rt.scc b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-preempt-rt.scc new file mode 100644 index 0000000000..ca5f3b5be9 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-preempt-rt.scc @@ -0,0 +1,14 @@ +# yocto-bsp-filename {{=machine}}-preempt-rt.scc +define KMACHINE {{=machine}} +define KTYPE preempt-rt +define KARCH arm + +include {{=map_preempt_rt_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc + +# default policy for preempt-rt kernels +include features/latencytop/latencytop.scc +include features/profiling/profiling.scc diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-standard.scc b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-standard.scc new file mode 100644 index 0000000000..9014c2c97e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-standard.scc @@ -0,0 +1,14 @@ +# yocto-bsp-filename {{=machine}}-standard.scc +define KMACHINE {{=machine}} +define KTYPE standard +define KARCH arm + +include {{=map_standard_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc + +# default policy for standard kernels +include features/latencytop/latencytop.scc +include features/profiling/profiling.scc diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-tiny.scc b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-tiny.scc new file mode 100644 index 0000000000..3f1c252232 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-tiny.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-tiny.scc +define KMACHINE {{=machine}} +define KTYPE tiny +define KARCH arm + +include {{=map_tiny_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-config.cfg b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-config.cfg new file mode 100644 index 0000000000..47489e44e9 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-config.cfg @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-config.cfg diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-features.scc b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-features.scc new file mode 100644 index 0000000000..582759e612 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-features.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-features.scc diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-patches.scc b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-patches.scc new file mode 100644 index 0000000000..97f747fa07 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine-user-patches.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.cfg b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.cfg new file mode 100644 index 0000000000..a2e1ae0f75 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.cfg @@ -0,0 +1,321 @@ +# yocto-bsp-filename {{=machine}}.cfg +# +# System Type +# +CONFIG_ARCH_OMAP=y + +# +# TI OMAP Implementations +# +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y + +# +# TI OMAP Common Features +# +CONFIG_ARCH_OMAP2PLUS=y + +# +# OMAP Feature Selections +# +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_SMARTREFLEX=y +CONFIG_OMAP_SMARTREFLEX_CLASS3=y +CONFIG_OMAP_MBOX_FWK=m +CONFIG_OMAP_MBOX_KFIFO_SIZE=256 + +# +# OMAP Board Type +# +CONFIG_MACH_OMAP3_BEAGLE=y + +# +# Processor Features +# +CONFIG_ARM_THUMBEE=y +CONFIG_ARM_ERRATA_430973=y + +# +# Kernel Features +# +CONFIG_LEDS=y + + +# +# Serial drivers +# +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_NEON=y + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_RUNTIME=y + +# +# Generic Driver Options +# +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y + +# +# Disk-On-Chip Device Drivers +# +CONFIG_MTD_NAND=y + +CONFIG_MTD_NAND_OMAP2=y + +CONFIG_MTD_UBI=y + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_SMSC911X=y +CONFIG_USB_NET_SMSC95XX=y + +# +# Userland interfaces +# +CONFIG_INPUT_EVDEV=y + +# +# Input Device Drivers +# +CONFIG_KEYBOARD_TWL4030=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y + +# +# Miscellaneous I2C Chip support +# +CONFIG_I2C=y +CONFIG_I2C_OMAP=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_OMAP24XX=y + +# +# I2C GPIO expanders: +# +CONFIG_GPIO_TWL4030=y + +# +# SPI GPIO expanders: +# +CONFIG_OMAP_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Multifunction device drivers +# +CONFIG_TWL4030_CORE=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_DUMMY=y +CONFIG_REGULATOR_TWL4030=y + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_DRM=m +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRFB=y +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=14 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set +CONFIG_OMAP2_DSS_DPI=y +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +CONFIG_OMAP2_DSS_DSI=y +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +CONFIG_FB_OMAP2_NUM_FBS=2 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC_DPI=y +CONFIG_PANEL_DVI=y +CONFIG_PANEL_SHARP_LS037V7DW01=y +# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set +# CONFIG_PANEL_TAAL is not set +CONFIG_PANEL_TPO_TD043MTEA1=m +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set + +# +# Console display driver support +# +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +# CONFIG_VGA_CONSOLE is not set + +# DMA Devices +CONFIG_DMADEVICES=y +CONFIG_DMA_OMAP=y +CONFIG_DMA_OF=y + +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_OMAP_TWL4030=y + +# +# USB Input Devices +# +CONFIG_USB=y +CONFIG_USB_SUPPORT=y + +# +# Miscellaneous USB options +# +CONFIG_USB_OTG=y +# CONFIG_USB_OTG_WHITELIST is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_OMAP2PLUS=y +CONFIG_USB_OMAP=y + +# +# OMAP 343x high speed USB support +# +CONFIG_USB_MUSB_OTG=y +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_MUSB_HDRC_HCD=y +CONFIG_USB_INVENTRA_DMA=y + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_OTG_UTILS=y +CONFIG_TWL4030_USB=y + +# USB gadget modules +CONFIG_USB_G_NCM=y +CONFIG_USB_MASS_STORAGE=y + +CONFIG_MMC=y + +# +# MMC/SD Host Controller Drivers +# +CONFIG_MMC_OMAP_HS=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_TWL4030=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_VFAT_FS=y + +# +# Multimedia core support +# + +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Advanced Power Management Emulation support +# +CONFIG_APM_EMULATION=y diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.scc b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.scc new file mode 100644 index 0000000000..828400df40 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/files/machine.scc @@ -0,0 +1,8 @@ +# yocto-bsp-filename {{=machine}}.scc +kconf hardware {{=machine}}.cfg +kconf non-hardware {{machine}}-non_hardware.cfg + +include features/usb-net/usb-net.scc + +kconf hardware {{=machine}}-user-config.cfg +include {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/kernel-list.noinstall b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/kernel-list.noinstall new file mode 100644 index 0000000000..a04e6c7852 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/kernel-list.noinstall @@ -0,0 +1,5 @@ +{{ if kernel_choice != "custom": }} +{{ input type:"boolean" name:"use_default_kernel" prio:"10" msg:"Would you like to use the default (3.14) kernel? (y/n)" default:"y"}} + +{{ if kernel_choice != "custom" and use_default_kernel == "n": }} +{{ input type:"choicelist" name:"kernel_choice" gen:"bsp.kernel.kernels" prio:"10" msg:"Please choose the kernel to use in this BSP:" default:"linux-yocto_3.14"}} diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-dev.bbappend b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-dev.bbappend new file mode 100644 index 0000000000..2fa6231cbf --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-dev.bbappend @@ -0,0 +1,26 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-dev": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend new file mode 100644 index 0000000000..35b0958582 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-rt_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-preempt-rt.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-rt_{{=machine}} ?= "f35992f80c81dc5fa1a97165dfd5cbb84661f7cb" +#SRCREV_meta_pn-linux-yocto-rt_{{=machine}} ?= "1b534b2f8bbe9b8a773268cfa30a4850346f6f5f" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend new file mode 100644 index 0000000000..f04dd0cce4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend new file mode 100644 index 0000000000..471ccbcc3e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.10.bbappend new file mode 100644 index 0000000000..badb3aa239 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "19f7e43b54aef08d58135ed2a897d77b624b320a" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "459165c1dd61c4e843c36e6a1abeb30949a20ba7" +#LINUX_VERSION = "3.10.9" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.14.bbappend new file mode 100644 index 0000000000..1e1cc51315 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/arm/recipes-kernel/linux/linux-yocto_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/common/COPYING.MIT b/scripts/lib/bsp/substrate/target/arch/common/COPYING.MIT new file mode 100644 index 0000000000..fb950dc69f --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/COPYING.MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/scripts/lib/bsp/substrate/target/arch/common/README b/scripts/lib/bsp/substrate/target/arch/common/README new file mode 100644 index 0000000000..928659f302 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/README @@ -0,0 +1,118 @@ +This README file contains information on building the meta-{{=machine}} +BSP layer, and booting the images contained in the /binary directory. +Please see the corresponding sections below for details. + + +Dependencies +============ + +This layer depends on: + + URI: git://git.openembedded.org/bitbake + branch: master + + URI: git://git.openembedded.org/openembedded-core + layers: meta + branch: master + + URI: git://git.yoctoproject.org/xxxx + layers: xxxx + branch: master + + +Patches +======= + +Please submit any patches against this BSP to the Yocto mailing list +(yocto@yoctoproject.org) and cc: the maintainer: + +Maintainer: XXX YYYYYY + +Please see the meta-xxxx/MAINTAINERS file for more details. + + +Table of Contents +================= + + I. Building the meta-{{=machine}} BSP layer + II. Booting the images in /binary + + +I. Building the meta-{{=machine}} BSP layer +======================================== + +--- replace with specific instructions for your layer --- + +In order to build an image with BSP support for a given release, you +need to download the corresponding BSP tarball from the 'Board Support +Package (BSP) Downloads' page of the Yocto Project website. + +Having done that, and assuming you extracted the BSP tarball contents +at the top-level of your yocto build tree, you can build a +{{=machine}} image by adding the location of the meta-{{=machine}} +layer to bblayers.conf, along with any other layers needed (to access +common metadata shared between BSPs) e.g.: + + yocto/meta-xxxx \ + yocto/meta-xxxx/meta-{{=machine}} \ + +To enable the {{=machine}} layer, add the {{=machine}} MACHINE to local.conf: + + MACHINE ?= "{{=machine}}" + +You should then be able to build a {{=machine}} image as such: + + $ source oe-init-build-env + $ bitbake core-image-sato + +At the end of a successful build, you should have a live image that +you can boot from a USB flash drive (see instructions on how to do +that below, in the section 'Booting the images from /binary'). + +As an alternative to downloading the BSP tarball, you can also work +directly from the meta-xxxx git repository. For each BSP in the +'meta-xxxx' repository, there are multiple branches, one corresponding +to each major release starting with 'laverne' (0.90), in addition to +the latest code which tracks the current master (note that not all +BSPs are present in every release). Instead of extracting a BSP +tarball at the top level of your yocto build tree, you can +equivalently check out the appropriate branch from the meta-xxxx +repository at the same location. + + +II. Booting the images in /binary +================================= + +--- replace with specific instructions for your platform --- + +This BSP contains bootable live images, which can be used to directly +boot Yocto off of a USB flash drive. + +Under Linux, insert a USB flash drive. Assuming the USB flash drive +takes device /dev/sdf, use dd to copy the live image to it. For +example: + +# dd if=core-image-sato-{{=machine}}-20101207053738.hddimg of=/dev/sdf +# sync +# eject /dev/sdf + +This should give you a bootable USB flash device. Insert the device +into a bootable USB socket on the target, and power on. This should +result in a system booted to the Sato graphical desktop. + +If you want a terminal, use the arrows at the top of the UI to move to +different pages of available applications, one of which is named +'Terminal'. Clicking that should give you a root terminal. + +If you want to ssh into the system, you can use the root terminal to +ifconfig the IP address and use that to ssh in. The root password is +empty, so to log in type 'root' for the user name and hit 'Enter' at +the Password prompt: and you should be in. + +---- + +If you find you're getting corrupt images on the USB (it doesn't show +the syslinux boot: prompt, or the boot: prompt contains strange +characters), try doing this first: + +# dd if=/dev/zero of=/dev/sdf bs=1M count=512 diff --git a/scripts/lib/bsp/substrate/target/arch/common/README.sources b/scripts/lib/bsp/substrate/target/arch/common/README.sources new file mode 100644 index 0000000000..3c4cb7b435 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/README.sources @@ -0,0 +1,17 @@ +The sources for the packages comprising the images shipped with this +BSP can be found at the following location: + +http://downloads.yoctoproject.org/mirror/sources/ + +The metadata used to generate the images shipped with this BSP, in +addition to the code contained in this BSP, can be found at the +following location: + +http://www.yoctoproject.org/downloads/yocto-1.1/poky-edison-6.0.tar.bz2 + +The metadata used to generate the images shipped with this BSP, in +addition to the code contained in this BSP, can also be found at the +following locations: + +git://git.yoctoproject.org/poky.git +git://git.yoctoproject.org/meta-xxxx diff --git a/scripts/lib/bsp/substrate/target/arch/common/binary/.gitignore b/scripts/lib/bsp/substrate/target/arch/common/binary/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/bsp/substrate/target/arch/common/conf/layer.conf b/scripts/lib/bsp/substrate/target/arch/common/conf/layer.conf new file mode 100644 index 0000000000..5529f45954 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/conf/layer.conf @@ -0,0 +1,10 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have a recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "{{=machine}}" +BBFILE_PATTERN_{{=machine}} = "^${LAYERDIR}/" +BBFILE_PRIORITY_{{=machine}} = "6" diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine.noinstall b/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine.noinstall new file mode 100644 index 0000000000..b442d02d57 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=machine}} diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine/machconfig b/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine/machconfig new file mode 100644 index 0000000000..3b85d3821f --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor/machine/machconfig @@ -0,0 +1,5 @@ +# Assume a USB mouse and keyboard are connected +{{ input type:"boolean" name:"touchscreen" msg:"Does your BSP have a touchscreen? (y/n)" default:"n" }} +HAVE_TOUCHSCREEN={{=touchscreen}} +{{ input type:"boolean" name:"keyboard" msg:"Does your BSP have a keyboard? (y/n)" default:"y" }} +HAVE_KEYBOARD={{=keyboard}} diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor_0.0.bbappend b/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor_0.0.bbappend new file mode 100644 index 0000000000..6d4804d127 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-bsp/formfactor/formfactor_0.0.bbappend @@ -0,0 +1,2 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/kernel-list.noinstall b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/kernel-list.noinstall new file mode 100644 index 0000000000..03b7d84ec2 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/kernel-list.noinstall @@ -0,0 +1,26 @@ +{{ if kernel_choice == "custom": }} +{{ input type:"boolean" name:"custom_kernel_remote" prio:"20" msg:"Is the custom kernel you'd like to use in a remote git repo? (y/n)" default:"y"}} + +{{ if kernel_choice == "custom" and custom_kernel_remote == "y": }} +{{ input type:"edit-git-repo" name:"custom_kernel_remote_path" prio:"20" msg:"Please enter the full URI to the remote git repo (the default corresponds to linux-stable v3.13.9)" default:"git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git"}} + +{{ if kernel_choice == "custom" and custom_kernel_remote == "n": }} +{{ input type:"edit-git-repo" name:"custom_kernel_local_path" prio:"20" msg:"You've indicated that you're not using a remote git repo. Please enter the full path to the local git repo you want to use (the default assumes a local linux-stable v3.13.9)" default:"/home/trz/yocto/kernels/linux-stable.git"}} + +{{ if kernel_choice == "custom": }} +{{ input type:"boolean" name:"custom_kernel_need_kbranch" prio:"20" msg:"Do you need to use a specific (non-master) branch? (y/n)" default:"n"}} + +{{ if kernel_choice == "custom" and custom_kernel_need_kbranch == "y": }} +{{ input type:"edit" name:"custom_kernel_kbranch" prio:"20" msg:"Please enter the branch you want to use (the default branch corresponds to the linux-stable 'linux-3.13.y' branch):" default:"linux-3.13.y"}} + +{{ if kernel_choice == "custom": }} +{{ input type:"edit" name:"custom_kernel_srcrev" prio:"20" msg:"Please enter the SRCREV (commit id) you'd like to use (use '${AUTOREV}' to track the current HEAD):" default:"${AUTOREV}"}} + +{{ if kernel_choice == "custom": }} +{{ input type:"edit" name:"custom_kernel_linux_version" prio:"20" msg:"Please enter the Linux version of the kernel you've specified:" default:"3.13.9"}} + +{{ if kernel_choice == "custom": }} +{{ input type:"edit" name:"custom_kernel_linux_version_extension" prio:"20" msg:"Please enter a Linux version extension if you want (it will show up at the end of the kernel name shown by uname):" default:"-custom"}} + +{{ if kernel_choice == "custom": }} +{{ input type:"edit-file" name:"custom_kernel_defconfig" prio:"20" msg:"It's recommended (but not required) that custom kernels be built using a defconfig. Please enter the full path to the defconfig for your kernel (NOTE: if you don't specify a defconfig the kernel probably won't build or boot):" default:""}} diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.bb b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.bb new file mode 100644 index 0000000000..80a52e7cae --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.bb @@ -0,0 +1,58 @@ +# yocto-bsp-filename {{ if kernel_choice == "custom": }} this +# This file was derived from the linux-yocto-custom.bb recipe in +# oe-core. +# +# linux-yocto-custom.bb: +# +# A yocto-bsp-generated kernel recipe that uses the linux-yocto and +# oe-core kernel classes to apply a subset of yocto kernel +# management to git managed kernel repositories. +# +# Warning: +# +# Building this kernel without providing a defconfig or BSP +# configuration will result in build or boot errors. This is not a +# bug. +# +# Notes: +# +# patches: patches can be merged into to the source git tree itself, +# added via the SRC_URI, or controlled via a BSP +# configuration. +# +# example configuration addition: +# SRC_URI += "file://smp.cfg" +# example patch addition: +# SRC_URI += "file://0001-linux-version-tweak.patch +# example feature addition: +# SRC_URI += "file://feature.scc" +# + +inherit kernel +require recipes-kernel/linux/linux-yocto.inc + +{{ if kernel_choice == "custom" and custom_kernel_remote == "y": }} +SRC_URI = "{{=custom_kernel_remote_path}};protocol=git;bareclone=1;branch=${KBRANCH}" +{{ if kernel_choice == "custom" and custom_kernel_remote == "n": }} +SRC_URI = "git://{{=custom_kernel_local_path}};protocol=file;bareclone=1;branch=${KBRANCH}" + +SRC_URI += "file://defconfig" + +SRC_URI += "file://{{=machine}}.scc \ + file://{{=machine}}.cfg \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + " + +{{ if kernel_choice == "custom" and custom_kernel_need_kbranch == "y" and custom_kernel_kbranch and custom_kernel_kbranch != "master": }} +KBRANCH = "{{=custom_kernel_kbranch}}" + +LINUX_VERSION ?= "{{=custom_kernel_linux_version}}" +LINUX_VERSION_EXTENSION ?= "{{=custom_kernel_linux_version_extension}}" + +SRCREV="{{=custom_kernel_srcrev}}" + +PR = "r0" +PV = "${LINUX_VERSION}+git${SRCPV}" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.noinstall b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.noinstall new file mode 100644 index 0000000000..017d206c24 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if kernel_choice == "custom": }} linux-yocto-custom diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/defconfig b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/defconfig new file mode 100644 index 0000000000..ceb0ffa30c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/defconfig @@ -0,0 +1,5 @@ +# +# Placeholder for custom default kernel configuration. yocto-bsp will +# replace this file with a user-specified defconfig. +# +{{ if custom_kernel_defconfig: replace_file(of, custom_kernel_defconfig) }} diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-config.cfg b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-config.cfg new file mode 100644 index 0000000000..922309d5ab --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-config.cfg @@ -0,0 +1,9 @@ +# yocto-bsp-filename {{=machine}}-user-config.cfg +# +# Used by yocto-kernel to manage config options. +# +# yocto-kernel may change the contents of this file in any +# way it sees fit, including removing comments like this, +# so don't manually make any modifications you don't want +# to lose. +# diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-patches.scc b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-patches.scc new file mode 100644 index 0000000000..6d1138f42a --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine-user-patches.scc @@ -0,0 +1,9 @@ +# yocto-bsp-filename {{=machine}}-user-patches.scc +# +# Used by yocto-kernel to manage patches. +# +# yocto-kernel may change the contents of this file in any +# way it sees fit, including removing comments like this, +# so don't manually make any modifications you don't want +# to lose. +# diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.cfg b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.cfg new file mode 100644 index 0000000000..1ba8201f16 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.cfg @@ -0,0 +1,4 @@ +# yocto-bsp-filename {{=machine}}.cfg +# +# A convenient place to add config options, nothing more. +# diff --git a/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.scc b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.scc new file mode 100644 index 0000000000..0b6b413377 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/common/recipes-kernel/linux/linux-yocto-custom/machine.scc @@ -0,0 +1,18 @@ +# yocto-bsp-filename {{=machine}}.scc +# +# The top-level 'feature' for the {{=machine}} custom kernel. +# +# Essentially this is a convenient top-level container or starting +# point for adding lower-level config fragements and features. +# + +# {{=machine}}.cfg in the linux-yocto-custom subdir is just a +# convenient place for adding random config fragments. + +kconf hardware {{=machine}}.cfg + +# These are used by yocto-kernel to add config fragments and features. +# Don't remove if you plan on using yocto-kernel with this BSP. + +kconf hardware {{=machine}}-user-config.cfg +include {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/i386/conf/machine/machine.conf b/scripts/lib/bsp/substrate/target/arch/i386/conf/machine/machine.conf new file mode 100644 index 0000000000..43e38d06d0 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/conf/machine/machine.conf @@ -0,0 +1,67 @@ +# yocto-bsp-filename {{=machine}}.conf +#@TYPE: Machine +#@NAME: {{=machine}} + +#@DESCRIPTION: Machine configuration for {{=machine}} systems + +{{ if kernel_choice == "custom": preferred_kernel = "linux-yocto-custom" }} +{{ if kernel_choice == "linux-yocto-dev": preferred_kernel = "linux-yocto-dev" }} +{{ if kernel_choice == "custom" or kernel_choice == "linux-yocto-dev" : }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" + +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel = kernel_choice.split('_')[0] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel_version = kernel_choice.split('_')[1] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" +PREFERRED_VERSION_{{=preferred_kernel}} ?= "{{=preferred_kernel_version}}%" + +{{ input type:"choicelist" name:"tunefile" prio:"40" msg:"Which machine tuning would you like to use?" default:"tune_core2" }} +{{ input type:"choice" val:"tune_i586" msg:"i586 tuning optimizations" }} +{{ input type:"choice" val:"tune_atom" msg:"Atom tuning optimizations" }} +{{ input type:"choice" val:"tune_core2" msg:"Core2 tuning optimizations" }} +{{ if tunefile == "tune_i586": }} +require conf/machine/include/tune-i586.inc +{{ if tunefile == "tune_atom": }} +require conf/machine/include/tune-atom.inc +{{ if tunefile == "tune_core2": }} +DEFAULTTUNE="core2-32" +require conf/machine/include/tune-core2.inc + +require conf/machine/include/x86-base.inc + +MACHINE_FEATURES += "wifi efi pcbios" + +{{ input type:"boolean" name:"xserver" prio:"50" msg:"Do you need support for X? (y/n)" default:"y" }} + +{{ if xserver == "y" and (kernel_choice == "linux-yocto_3.14" or kernel_choice == "linux-yocto_3.10"): }} +{{ input type:"choicelist" name:"xserver_choice" prio:"50" msg:"Please select an xserver for this machine:" default:"xserver_i915" }} +{{ input type:"choice" val:"xserver_vesa" msg:"VESA xserver support" }} +{{ input type:"choice" val:"xserver_i915" msg:"i915 xserver support" }} +{{ input type:"choice" val:"xserver_i965" msg:"i965 xserver support" }} + +{{ if xserver == "y" and kernel_choice == "custom": }} +{{ input type:"choicelist" name:"xserver_choice" prio:"50" msg:"Please select an xserver for this machine:" default:"xserver_i915" }} +{{ input type:"choice" val:"xserver_vesa" msg:"VESA xserver support" }} +{{ input type:"choice" val:"xserver_i915" msg:"i915 xserver support" }} +{{ input type:"choice" val:"xserver_i965" msg:"i965 xserver support" }} + +{{ if xserver == "y" and kernel_choice != "linux-yocto_3.14" and kernel_choice != "linux-yocto_3.10" and kernel_choice != "custom": xserver_choice = "xserver_i915" }} + +{{ if xserver == "y": }} +XSERVER ?= "${XSERVER_X86_BASE} \ + ${XSERVER_X86_EXT} \ +{{ if xserver == "y" and xserver_choice == "xserver_vesa": }} + ${XSERVER_X86_VESA} \ +{{ if xserver == "y" and xserver_choice == "xserver_i915": }} + ${XSERVER_X86_I915} \ +{{ if xserver == "y" and xserver_choice == "xserver_i965": }} + ${XSERVER_X86_I965} \ +{{ if xserver == "y": }} + " + +MACHINE_EXTRA_RRECOMMENDS += "linux-firmware v86d" + +EXTRA_OECONF_append_pn-matchbox-panel-2 = " --with-battery=acpi" + +{{ if xserver == "y" and xserver_choice == "xserver_vesa": }} +APPEND += "video=vesafb vga=0x318" diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall b/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall new file mode 100644 index 0000000000..b442d02d57 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=machine}} diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf b/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf new file mode 100644 index 0000000000..ac9a0f1bb0 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf @@ -0,0 +1 @@ +# yocto-bsp-filename {{ if xserver == "y": }} this diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend b/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend new file mode 100644 index 0000000000..30830031ed --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend @@ -0,0 +1,2 @@ +# yocto-bsp-filename {{ if xserver == "y": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files.noinstall b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files.noinstall new file mode 100644 index 0000000000..1e0d92c55c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if kernel_choice != "custom": }} files diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-preempt-rt.scc b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-preempt-rt.scc new file mode 100644 index 0000000000..619ee3f367 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-preempt-rt.scc @@ -0,0 +1,16 @@ +# yocto-bsp-filename {{=machine}}-preempt-rt.scc +define KMACHINE {{=machine}} +define KTYPE preempt-rt +define KARCH i386 + +include {{=map_preempt_rt_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc + +# default policy for preempt-rt kernels +include cfg/usb-mass-storage.scc +include cfg/boot-live.scc +include features/latencytop/latencytop.scc +include features/profiling/profiling.scc diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-standard.scc b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-standard.scc new file mode 100644 index 0000000000..682012fafc --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-standard.scc @@ -0,0 +1,16 @@ +# yocto-bsp-filename {{=machine}}-standard.scc +define KMACHINE {{=machine}} +define KTYPE standard +define KARCH i386 + +include {{=map_standard_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc + +# default policy for standard kernels +include cfg/usb-mass-storage.scc +include cfg/boot-live.scc +include features/latencytop/latencytop.scc +include features/profiling/profiling.scc diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-tiny.scc b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-tiny.scc new file mode 100644 index 0000000000..cc7519699a --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-tiny.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-tiny.scc +define KMACHINE {{=machine}} +define KTYPE tiny +define KARCH i386 + +include {{=map_tiny_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-config.cfg b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-config.cfg new file mode 100644 index 0000000000..69efdcc759 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-config.cfg @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-config.cfg \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-features.scc b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-features.scc new file mode 100644 index 0000000000..85be26de97 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-features.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-features.scc \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-patches.scc b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-patches.scc new file mode 100644 index 0000000000..4c59daac46 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine-user-patches.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-patches.scc \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.cfg b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.cfg new file mode 100644 index 0000000000..3b168b7e36 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.cfg @@ -0,0 +1,55 @@ +# yocto-bsp-filename {{=machine}}.cfg +CONFIG_X86_32=y +CONFIG_MATOM=y +CONFIG_PRINTK=y + +# Basic hardware support for the box - network, USB, PCI, sound +CONFIG_NETDEVICES=y +CONFIG_ATA=y +CONFIG_ATA_GENERIC=y +CONFIG_ATA_SFF=y +CONFIG_PCI=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_USB_SUPPORT=y +CONFIG_USB=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_R8169=y +CONFIG_PATA_SCH=y +CONFIG_MMC_SDHCI_PCI=y +CONFIG_USB_EHCI_HCD=y +CONFIG_PCIEPORTBUS=y +CONFIG_NET=y +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_HDA_INTEL=y +CONFIG_SATA_AHCI=y +CONFIG_AGP=y +CONFIG_PM=y +CONFIG_ACPI=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_INPUT=y + +# Make sure these are on, otherwise the bootup won't be fun +CONFIG_EXT3_FS=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_MODULES=y +CONFIG_SHMEM=y +CONFIG_TMPFS=y +CONFIG_PACKET=y + +# Needed for booting (and using) USB memory sticks +CONFIG_BLK_DEV_LOOP=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y + +CONFIG_RD_GZIP=y + +# Needed for booting (and using) CD images +CONFIG_BLK_DEV_SR=y diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.scc b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.scc new file mode 100644 index 0000000000..3d32f111b0 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/files/machine.scc @@ -0,0 +1,21 @@ +# yocto-bsp-filename {{=machine}}.scc +kconf hardware {{=machine}}.cfg + +include features/intel-e1xxxx/intel-e100.scc +include features/intel-e1xxxx/intel-e1xxxx.scc + +{{ if xserver == "y" and xserver_choice == "xserver_i915" or xserver_choice == "xserver_i965": }} +include features/i915/i915.scc + +include features/serial/8250.scc +include features/ericsson-3g/f5521gw.scc + +{{ if xserver == "y" and xserver_choice == "xserver_vesa": }} +include cfg/vesafb.scc + +include cfg/usb-mass-storage.scc +include cfg/boot-live.scc +include features/power/intel.scc + +kconf hardware {{=machine}}-user-config.cfg +include {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/kernel-list.noinstall b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/kernel-list.noinstall new file mode 100644 index 0000000000..a04e6c7852 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/kernel-list.noinstall @@ -0,0 +1,5 @@ +{{ if kernel_choice != "custom": }} +{{ input type:"boolean" name:"use_default_kernel" prio:"10" msg:"Would you like to use the default (3.14) kernel? (y/n)" default:"y"}} + +{{ if kernel_choice != "custom" and use_default_kernel == "n": }} +{{ input type:"choicelist" name:"kernel_choice" gen:"bsp.kernel.kernels" prio:"10" msg:"Please choose the kernel to use in this BSP:" default:"linux-yocto_3.14"}} diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-dev.bbappend b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-dev.bbappend new file mode 100644 index 0000000000..2fa6231cbf --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-dev.bbappend @@ -0,0 +1,26 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-dev": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend new file mode 100644 index 0000000000..35b0958582 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-rt_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-preempt-rt.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-rt_{{=machine}} ?= "f35992f80c81dc5fa1a97165dfd5cbb84661f7cb" +#SRCREV_meta_pn-linux-yocto-rt_{{=machine}} ?= "1b534b2f8bbe9b8a773268cfa30a4850346f6f5f" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend new file mode 100644 index 0000000000..f04dd0cce4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend new file mode 100644 index 0000000000..471ccbcc3e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.10.bbappend new file mode 100644 index 0000000000..1cfc611949 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "19f7e43b54aef08d58135ed2a897d77b624b320a" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "459165c1dd61c4e843c36e6a1abeb30949a20ba7" +#LINUX_VERSION = "3.10.9" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.14.bbappend new file mode 100644 index 0000000000..fbb49edb26 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/i386/recipes-kernel/linux/linux-yocto_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/layer/COPYING.MIT b/scripts/lib/bsp/substrate/target/arch/layer/COPYING.MIT new file mode 100644 index 0000000000..89de354795 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/COPYING.MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/scripts/lib/bsp/substrate/target/arch/layer/README b/scripts/lib/bsp/substrate/target/arch/layer/README new file mode 100644 index 0000000000..943dfc4412 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/README @@ -0,0 +1,64 @@ +This README file contains information on the contents of the +{{=layer_name}} layer. + +Please see the corresponding sections below for details. + + +Dependencies +============ + +This layer depends on: + + URI: git://git.openembedded.org/bitbake + branch: master + + URI: git://git.openembedded.org/openembedded-core + layers: meta + branch: master + + URI: git://git.yoctoproject.org/xxxx + layers: xxxx + branch: master + + +Patches +======= + +Please submit any patches against the {{=layer_name}} layer to the +xxxx mailing list (xxxx@zzzz.org) and cc: the maintainer: + +Maintainer: XXX YYYYYY + + +Table of Contents +================= + + I. Adding the {{=layer_name}} layer to your build + II. Misc + + +I. Adding the {{=layer_name}} layer to your build +================================================= + +--- replace with specific instructions for the {{=layer_name}} layer --- + +In order to use this layer, you need to make the build system aware of +it. + +Assuming the {{=layer_name}} layer exists at the top-level of your +yocto build tree, you can add it to the build system by adding the +location of the {{=layer_name}} layer to bblayers.conf, along with any +other layers needed. e.g.: + + BBLAYERS ?= " \ + /path/to/yocto/meta \ + /path/to/yocto/meta-yocto \ + /path/to/yocto/meta-yocto-bsp \ + /path/to/yocto/meta-{{=layer_name}} \ + " + + +II. Misc +======== + +--- replace with specific information about the {{=layer_name}} layer --- diff --git a/scripts/lib/bsp/substrate/target/arch/layer/conf/layer.conf b/scripts/lib/bsp/substrate/target/arch/layer/conf/layer.conf new file mode 100644 index 0000000000..bdffe17195 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/conf/layer.conf @@ -0,0 +1,10 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "{{=layer_name}}" +BBFILE_PATTERN_{{=layer_name}} = "^${LAYERDIR}/" +BBFILE_PRIORITY_{{=layer_name}} = "{{=layer_priority}}" diff --git a/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall b/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall new file mode 100644 index 0000000000..e2a89c3b5d --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/layer-questions.noinstall @@ -0,0 +1,14 @@ +{{ input type:"edit" name:"layer_priority" prio:"20" msg:"Please enter the layer priority you'd like to use for the layer:" default:"6"}} + +{{ input type:"boolean" name:"create_example_recipe" prio:"20" msg:"Would you like to have an example recipe created? (y/n)" default:"n"}} + +{{ if create_example_recipe == "y": }} +{{ input type:"edit" name:"example_recipe_name" prio:"20" msg:"Please enter the name you'd like to use for your example recipe:" default:"example"}} + +{{ input type:"boolean" name:"create_example_bbappend" prio:"20" msg:"Would you like to have an example bbappend file created? (y/n)" default:"n"}} + +{{ if create_example_bbappend == "y": }} +{{ input type:"edit" name:"example_bbappend_name" prio:"20" msg:"Please enter the name you'd like to use for your bbappend file:" default:"example"}} + +{{ if create_example_bbappend == "y": }} +{{ input type:"edit" name:"example_bbappend_version" prio:"20" msg:"Please enter the version number you'd like to use for your bbappend file (this should match the recipe you're appending to):" default:"0.1"}} diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend.noinstall b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend.noinstall new file mode 100644 index 0000000000..3594e6583c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if create_example_bbappend == "y": }} recipes-example-bbappend diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.bbappend b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.bbappend new file mode 100644 index 0000000000..353133080a --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.bbappend @@ -0,0 +1,9 @@ +# yocto-bsp-filename {{=example_bbappend_name}}_{{=example_bbappend_version}}.bbappend +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}:" + +# +# This .bbappend doesn't yet do anything - replace this text with +# modifications to the example_0.1.bb recipe, or whatever recipe it is +# that you want to modify with this .bbappend (make sure you change +# the recipe name (PN) and version (PV) to match). +# diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.noinstall b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.noinstall new file mode 100644 index 0000000000..46df8a8e04 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=example_bbappend_name}}-{{=example_bbappend_version}} diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version/example.patch b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version/example.patch new file mode 100644 index 0000000000..2000a34da5 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example-bbappend/example-bbappend/example-bbappend-version/example.patch @@ -0,0 +1,12 @@ +# +# This is a non-functional placeholder file, here for example purposes +# only. +# +# If you had a patch for your recipe, you'd put it in this directory +# and reference it from your recipe's SRC_URI: +# +# SRC_URI += "file://example.patch" +# +# Note that you could also rename the directory containing this patch +# to remove the version number or simply rename it 'files'. Doing so +# allows you to use the same directory for multiple recipes. diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example.noinstall b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example.noinstall new file mode 100644 index 0000000000..b0069b1a5a --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if create_example_recipe == "y": }} recipes-example diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.bb b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.bb new file mode 100644 index 0000000000..ba1ccb16c6 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.bb @@ -0,0 +1,24 @@ +# yocto-bsp-filename {{=example_recipe_name}}_0.1.bb +# +# This file was derived from the 'Hello World!' example recipe in the +# Yocto Project Development Manual. +# + +DESCRIPTION = "Simple helloworld application" +SECTION = "examples" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" +PR = "r0" + +SRC_URI = "file://helloworld.c" + +S = "${WORKDIR}" + +do_compile() { + ${CC} helloworld.c -o helloworld +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 helloworld ${D}${bindir} +} diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.noinstall b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.noinstall new file mode 100644 index 0000000000..c319c19c57 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=example_recipe_name}}-0.1 diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/example.patch b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/example.patch new file mode 100644 index 0000000000..2000a34da5 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/example.patch @@ -0,0 +1,12 @@ +# +# This is a non-functional placeholder file, here for example purposes +# only. +# +# If you had a patch for your recipe, you'd put it in this directory +# and reference it from your recipe's SRC_URI: +# +# SRC_URI += "file://example.patch" +# +# Note that you could also rename the directory containing this patch +# to remove the version number or simply rename it 'files'. Doing so +# allows you to use the same directory for multiple recipes. diff --git a/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/helloworld.c b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/helloworld.c new file mode 100644 index 0000000000..71f2e46b4e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/layer/recipes-example/example/example-recipe-0.1/helloworld.c @@ -0,0 +1,8 @@ +#include + +int main(int argc, char **argv) +{ + printf("Hello World!\n"); + + return 0; +} diff --git a/scripts/lib/bsp/substrate/target/arch/mips/.gitignore b/scripts/lib/bsp/substrate/target/arch/mips/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/bsp/substrate/target/arch/mips/conf/machine/machine.conf b/scripts/lib/bsp/substrate/target/arch/mips/conf/machine/machine.conf new file mode 100644 index 0000000000..b319d626f4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/conf/machine/machine.conf @@ -0,0 +1,39 @@ +# yocto-bsp-filename {{=machine}}.conf +#@TYPE: Machine +#@NAME: {{=machine}} + +#@DESCRIPTION: Machine configuration for {{=machine}} systems + +require conf/machine/include/tune-mips32.inc + +MACHINE_FEATURES = "screen keyboard pci usbhost ext2 ext3 serial" + +KERNEL_IMAGETYPE = "vmlinux" +KERNEL_ALT_IMAGETYPE = "vmlinux.bin" +KERNEL_IMAGE_STRIP_EXTRA_SECTIONS = ".comment" + +{{ if kernel_choice == "custom": preferred_kernel = "linux-yocto-custom" }} +{{ if kernel_choice == "linux-yocto-dev": preferred_kernel = "linux-yocto-dev" }} +{{ if kernel_choice == "custom" or kernel_choice == "linux-yocto-dev" : }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" + +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel = kernel_choice.split('_')[0] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel_version = kernel_choice.split('_')[1] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" +PREFERRED_VERSION_{{=preferred_kernel}} ?= "{{=preferred_kernel_version}}%" + +{{ input type:"boolean" name:"xserver" prio:"50" msg:"Do you need support for X? (y/n)" default:"y" }} +{{ if xserver == "y": }} +PREFERRED_PROVIDER_virtual/xserver ?= "xserver-xorg" +XSERVER ?= "xserver-xorg \ + xf86-input-evdev \ + xf86-video-fbdev" + +SERIAL_CONSOLE = "115200 ttyS0" +USE_VT ?= "0" + +MACHINE_EXTRA_RRECOMMENDS = " kernel-modules" + +IMAGE_FSTYPES ?= "jffs2 tar.bz2" +JFFS2_ERASEBLOCK = "0x10000" diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files.noinstall b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files.noinstall new file mode 100644 index 0000000000..1e0d92c55c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if kernel_choice != "custom": }} files diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-preempt-rt.scc b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-preempt-rt.scc new file mode 100644 index 0000000000..176190cd2e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-preempt-rt.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-preempt-rt.scc +define KMACHINE {{=machine}} +define KTYPE preempt-rt +define KARCH mips + +include {{=map_preempt_rt_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-standard.scc b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-standard.scc new file mode 100644 index 0000000000..f05dd851d2 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-standard.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-standard.scc +define KMACHINE {{=machine}} +define KTYPE standard +define KARCH mips + +include {{=map_standard_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-tiny.scc b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-tiny.scc new file mode 100644 index 0000000000..f71c775397 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-tiny.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-tiny.scc +define KMACHINE {{=machine}} +define KTYPE tiny +define KARCH mips + +include {{=map_tiny_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-config.cfg b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-config.cfg new file mode 100644 index 0000000000..47489e44e9 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-config.cfg @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-config.cfg diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-features.scc b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-features.scc new file mode 100644 index 0000000000..85be26de97 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-features.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-features.scc \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-patches.scc b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-patches.scc new file mode 100644 index 0000000000..97f747fa07 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine-user-patches.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.cfg b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.cfg new file mode 100644 index 0000000000..2fe476691c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.cfg @@ -0,0 +1,2 @@ +# yocto-bsp-filename {{=machine}}.cfg +CONFIG_MIPS=y diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.scc b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.scc new file mode 100644 index 0000000000..f39dc3edf1 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/files/machine.scc @@ -0,0 +1,8 @@ +# yocto-bsp-filename {{=machine}}.scc +kconf hardware {{=machine}}.cfg + +include cfg/usb-mass-storage.scc +include cfg/fs/vfat.scc + +kconf hardware {{=machine}}-user-config.cfg +include {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/kernel-list.noinstall b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/kernel-list.noinstall new file mode 100644 index 0000000000..a04e6c7852 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/kernel-list.noinstall @@ -0,0 +1,5 @@ +{{ if kernel_choice != "custom": }} +{{ input type:"boolean" name:"use_default_kernel" prio:"10" msg:"Would you like to use the default (3.14) kernel? (y/n)" default:"y"}} + +{{ if kernel_choice != "custom" and use_default_kernel == "n": }} +{{ input type:"choicelist" name:"kernel_choice" gen:"bsp.kernel.kernels" prio:"10" msg:"Please choose the kernel to use in this BSP:" default:"linux-yocto_3.14"}} diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-dev.bbappend b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-dev.bbappend new file mode 100644 index 0000000000..2fa6231cbf --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-dev.bbappend @@ -0,0 +1,26 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-dev": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend new file mode 100644 index 0000000000..35b0958582 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-rt_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-preempt-rt.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-rt_{{=machine}} ?= "f35992f80c81dc5fa1a97165dfd5cbb84661f7cb" +#SRCREV_meta_pn-linux-yocto-rt_{{=machine}} ?= "1b534b2f8bbe9b8a773268cfa30a4850346f6f5f" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend new file mode 100644 index 0000000000..f04dd0cce4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend new file mode 100644 index 0000000000..c7e7989821 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.10.bbappend new file mode 100644 index 0000000000..badb3aa239 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "19f7e43b54aef08d58135ed2a897d77b624b320a" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "459165c1dd61c4e843c36e6a1abeb30949a20ba7" +#LINUX_VERSION = "3.10.9" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.14.bbappend new file mode 100644 index 0000000000..1e1cc51315 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/mips/recipes-kernel/linux/linux-yocto_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/.gitignore b/scripts/lib/bsp/substrate/target/arch/powerpc/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/conf/machine/machine.conf b/scripts/lib/bsp/substrate/target/arch/powerpc/conf/machine/machine.conf new file mode 100644 index 0000000000..bee0ec3772 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/conf/machine/machine.conf @@ -0,0 +1,75 @@ +# yocto-bsp-filename {{=machine}}.conf +#@TYPE: Machine +#@NAME: {{=machine}} + +#@DESCRIPTION: Machine configuration for {{=machine}} systems + +TARGET_FPU = "" + +{{ input type:"choicelist" name:"tunefile" prio:"40" msg:"Which machine tuning would you like to use?" default:"tune_ppce300c3" }} +{{ input type:"choice" val:"tune_ppc476" msg:"ppc476 tuning optimizations" }} +{{ input type:"choice" val:"tune_ppc603e" msg:"ppc603e tuning optimizations" }} +{{ input type:"choice" val:"tune_ppc7400" msg:"ppc7400 tuning optimizations" }} +{{ input type:"choice" val:"tune_ppce300c2" msg:"ppce300c2 tuning optimizations" }} +{{ input type:"choice" val:"tune_ppce300c3" msg:"ppce300c3 tuning optimizations" }} +{{ input type:"choice" val:"tune_ppce500" msg:"ppce500 tuning optimizations" }} +{{ input type:"choice" val:"tune_ppce500mc" msg:"ppce500mc tuning optimizations" }} +{{ input type:"choice" val:"tune_ppce500v2" msg:"ppce500v2 tuning optimizations" }} +{{ input type:"choice" val:"tune_ppce5500" msg:"ppce5500 tuning optimizations" }} +{{ input type:"choice" val:"tune_ppce6500" msg:"ppce6500 tuning optimizations" }} +{{ if tunefile == "tune_ppc476": }} +include conf/machine/include/tune-ppc476.inc +{{ if tunefile == "tune_ppc603e": }} +include conf/machine/include/tune-ppc603e.inc +{{ if tunefile == "tune_ppc7400": }} +include conf/machine/include/tune-ppc7400.inc +{{ if tunefile == "tune_ppce300c2": }} +include conf/machine/include/tune-ppce300c2.inc +{{ if tunefile == "tune_ppce300c3": }} +include conf/machine/include/tune-ppce300c3.inc +{{ if tunefile == "tune_ppce500": }} +include conf/machine/include/tune-ppce500.inc +{{ if tunefile == "tune_ppce500mc": }} +include conf/machine/include/tune-ppce500mc.inc +{{ if tunefile == "tune_ppce500v2": }} +include conf/machine/include/tune-ppce500v2.inc +{{ if tunefile == "tune_ppce5500": }} +include conf/machine/include/tune-ppce5500.inc +{{ if tunefile == "tune_ppce6500": }} +include conf/machine/include/tune-ppce6500.inc + +KERNEL_IMAGETYPE = "uImage" + +EXTRA_IMAGEDEPENDS += "u-boot" +UBOOT_MACHINE_{{=machine}} = "MPC8315ERDB_config" + +SERIAL_CONSOLE = "115200 ttyS0" + +MACHINE_FEATURES = "keyboard pci ext2 ext3 serial" + +{{ if kernel_choice == "custom": preferred_kernel = "linux-yocto-custom" }} +{{ if kernel_choice == "linux-yocto-dev": preferred_kernel = "linux-yocto-dev" }} +{{ if kernel_choice == "custom" or kernel_choice == "linux-yocto-dev" : }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" + +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel = kernel_choice.split('_')[0] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel_version = kernel_choice.split('_')[1] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" +PREFERRED_VERSION_{{=preferred_kernel}} ?= "{{=preferred_kernel_version}}%" + +{{ input type:"boolean" name:"xserver" prio:"50" msg:"Do you need support for X? (y/n)" default:"y" }} +{{ if xserver == "y": }} +PREFERRED_PROVIDER_virtual/xserver ?= "xserver-xorg" +XSERVER ?= "xserver-xorg \ + xf86-input-evdev \ + xf86-video-fbdev" + +PREFERRED_VERSION_u-boot ?= "v2013.07%" +{{ input type:"edit" name:"uboot_entrypoint" prio:"40" msg:"Please specify a value for UBOOT_ENTRYPOINT:" default:"0x00000000" }} +UBOOT_ENTRYPOINT = "{{=uboot_entrypoint}}" + +{{ input type:"edit" name:"kernel_devicetree" prio:"40" msg:"Please specify a [arch/powerpc/boot/dts/xxx] value for KERNEL_DEVICETREE:" default:"mpc8315erdb.dts" }} +KERNEL_DEVICETREE = "${S}/arch/powerpc/boot/dts/{{=kernel_devicetree}}" + +MACHINE_EXTRA_RRECOMMENDS = " kernel-modules" diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files.noinstall b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files.noinstall new file mode 100644 index 0000000000..1e0d92c55c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if kernel_choice != "custom": }} files diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-preempt-rt.scc b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-preempt-rt.scc new file mode 100644 index 0000000000..40c9267831 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-preempt-rt.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-preempt-rt.scc +define KMACHINE {{=machine}} +define KTYPE preempt-rt +define KARCH powerpc + +include {{=map_preempt_rt_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-standard.scc b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-standard.scc new file mode 100644 index 0000000000..7a1d35be1e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-standard.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-standard.scc +define KMACHINE {{=machine}} +define KTYPE standard +define KARCH powerpc + +include {{=map_standard_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-tiny.scc b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-tiny.scc new file mode 100644 index 0000000000..1bf94b2d05 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-tiny.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-tiny.scc +define KMACHINE {{=machine}} +define KTYPE tiny +define KARCH powerpc + +include {{=map_tiny_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-config.cfg b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-config.cfg new file mode 100644 index 0000000000..47489e44e9 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-config.cfg @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-config.cfg diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-features.scc b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-features.scc new file mode 100644 index 0000000000..582759e612 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-features.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-features.scc diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-patches.scc b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-patches.scc new file mode 100644 index 0000000000..97f747fa07 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine-user-patches.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.cfg b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.cfg new file mode 100644 index 0000000000..5bfe1fe4b0 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.cfg @@ -0,0 +1,164 @@ +# yocto-bsp-filename {{=machine}}.cfg +.......................................................................... +. WARNING +. +. This file is a kernel configuration fragment, and not a full kernel +. configuration file. The final kernel configuration is made up of +. an assembly of processed fragments, each of which is designed to +. capture a specific part of the final configuration (e.g. platform +. configuration, feature configuration, and board specific hardware +. configuration). For more information on kernel configuration, please +. consult the product documentation. +. +.......................................................................... +CONFIG_PPC32=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y + +# +# Processor support +# +CONFIG_PPC_83xx=y + +# +# Platform support +# +CONFIG_MPC831x_RDB=y +# CONFIG_PPC_CHRP is not set +# CONFIG_PPC_PMAC is not set + +# +# Bus options +# +CONFIG_PCI=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y + +# +# Mapping drivers for chip access +# +CONFIG_MTD_PHYSMAP_OF=y + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y + +# +# Ethernet (1000 Mbit) +# +CONFIG_GIANFAR=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 + +# +# Watchdog Device Drivers +# +CONFIG_8xxx_WDT=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Hardware Bus support +# +CONFIG_I2C_MPC=y + +CONFIG_SENSORS_LM75=y + +CONFIG_MISC_DEVICES=y + +# +# Miscellaneous I2C Chip support +# +CONFIG_EEPROM_AT24=y + +# +# SPI support +# +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_MPC8xxx=y + +# +# SPI Protocol Masters +# +CONFIG_HWMON=y + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_SCSI_LOGGING=y + +CONFIG_ATA=y +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_SATA_FSL=y +CONFIG_ATA_SFF=y + +# +# USB support +# +CONFIG_USB=m +CONFIG_USB_DEVICEFS=y + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_FSL=y +CONFIG_USB_STORAGE=m + +# +# Real Time Clock +# +CONFIG_RTC_CLASS=y + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=y + +CONFIG_KGDB_8250=m + +CONFIG_CRYPTO_DEV_TALITOS=m + +CONFIG_FSL_DMA=y + +CONFIG_MMC=y +CONFIG_MMC_SPI=m + +CONFIG_USB_FSL_MPH_DR_OF=y diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.scc b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.scc new file mode 100644 index 0000000000..7aac8b0801 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/files/machine.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}.scc +kconf hardware {{=machine}}.cfg + +include cfg/usb-mass-storage.scc +include cfg/fs/vfat.scc + +include cfg/dmaengine.scc + +kconf hardware {{=machine}}-user-config.cfg +include {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/kernel-list.noinstall b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/kernel-list.noinstall new file mode 100644 index 0000000000..a04e6c7852 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/kernel-list.noinstall @@ -0,0 +1,5 @@ +{{ if kernel_choice != "custom": }} +{{ input type:"boolean" name:"use_default_kernel" prio:"10" msg:"Would you like to use the default (3.14) kernel? (y/n)" default:"y"}} + +{{ if kernel_choice != "custom" and use_default_kernel == "n": }} +{{ input type:"choicelist" name:"kernel_choice" gen:"bsp.kernel.kernels" prio:"10" msg:"Please choose the kernel to use in this BSP:" default:"linux-yocto_3.14"}} diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-dev.bbappend b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-dev.bbappend new file mode 100644 index 0000000000..2fa6231cbf --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-dev.bbappend @@ -0,0 +1,26 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-dev": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-rt_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-rt_3.14.bbappend new file mode 100644 index 0000000000..7a2544617f --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-rt_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-rt_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-preempt-rt.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-rt_{{=machine}} ?= "f35992f80c81dc5fa1a97165dfd5cbb84661f7cb" +#SRCREV_meta_pn-linux-yocto-rt_{{=machine}} ?= "1b534b2f8bbe9b8a773268cfa30a4850346f6f5f" +#LINUX_VERSION = "3.14" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend new file mode 100644 index 0000000000..f04dd0cce4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend new file mode 100644 index 0000000000..471ccbcc3e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.10.bbappend new file mode 100644 index 0000000000..15b4b973c9 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "19f7e43b54aef08d58135ed2a897d77b624b320a" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "459165c1dd61c4e843c36e6a1abeb30949a20ba7" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.14.bbappend new file mode 100644 index 0000000000..e688384020 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/powerpc/recipes-kernel/linux/linux-yocto_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/conf/machine/machine.conf b/scripts/lib/bsp/substrate/target/arch/qemu/conf/machine/machine.conf new file mode 100644 index 0000000000..52f1866b5b --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/conf/machine/machine.conf @@ -0,0 +1,70 @@ +# yocto-bsp-filename {{=machine}}.conf +#@TYPE: Machine +#@NAME: {{=machine}} + +#@DESCRIPTION: Machine configuration for {{=machine}} systems + +{{ if kernel_choice == "custom": preferred_kernel = "linux-yocto-custom" }} +{{ if kernel_choice == "linux-yocto-dev": preferred_kernel = "linux-yocto-dev" }} +{{ if kernel_choice == "custom" or kernel_choice == "linux-yocto-dev" : }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" + +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel = kernel_choice.split('_')[0] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel_version = kernel_choice.split('_')[1] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" +PREFERRED_VERSION_{{=preferred_kernel}} ?= "{{=preferred_kernel_version}}%" + +{{ if qemuarch == "i386" or qemuarch == "x86_64": }} +PREFERRED_PROVIDER_virtual/xserver ?= "xserver-xorg" +PREFERRED_PROVIDER_virtual/libgl ?= "mesa" +PREFERRED_PROVIDER_virtual/libgles1 ?= "mesa" +PREFERRED_PROVIDER_virtual/libgles2 ?= "mesa" + +{{ input type:"choicelist" name:"qemuarch" prio:"5" msg:"Which qemu architecture would you like to use?" default:"i386" }} +{{ input type:"choice" val:"i386" msg:"i386 (32-bit)" }} +{{ input type:"choice" val:"x86_64" msg:"x86_64 (64-bit)" }} +{{ input type:"choice" val:"arm" msg:"ARM (32-bit)" }} +{{ input type:"choice" val:"powerpc" msg:"PowerPC (32-bit)" }} +{{ input type:"choice" val:"mips" msg:"MIPS (32-bit)" }} +{{ if qemuarch == "i386": }} +require conf/machine/include/qemu.inc +require conf/machine/include/tune-i586.inc +{{ if qemuarch == "x86_64": }} +require conf/machine/include/qemu.inc +DEFAULTTUNE ?= "core2-64" +require conf/machine/include/tune-core2.inc +{{ if qemuarch == "arm": }} +require conf/machine/include/qemu.inc +require conf/machine/include/tune-arm926ejs.inc +{{ if qemuarch == "powerpc": }} +require conf/machine/include/qemu.inc +require conf/machine/include/tune-ppc7400.inc +{{ if qemuarch == "mips": }} +require conf/machine/include/qemu.inc +require conf/machine/include/tune-mips32.inc + +{{ if qemuarch == "i386" or qemuarch == "x86_64": }} +MACHINE_FEATURES += "x86" +KERNEL_IMAGETYPE = "bzImage" +SERIAL_CONSOLE = "115200 ttyS0" +XSERVER = "xserver-xorg \ + ${@bb.utils.contains('DISTRO_FEATURES', 'opengl', 'mesa-driver-swrast', '', d)} \ + xf86-input-vmmouse \ + xf86-input-keyboard \ + xf86-input-evdev \ + xf86-video-vmware" + +{{ if qemuarch == "arm": }} +KERNEL_IMAGETYPE = "zImage" +SERIAL_CONSOLE = "115200 ttyAMA0" + +{{ if qemuarch == "powerpc": }} +KERNEL_IMAGETYPE = "vmlinux" +SERIAL_CONSOLE = "115200 ttyS0" + +{{ if qemuarch == "mips": }} +KERNEL_IMAGETYPE = "vmlinux" +KERNEL_ALT_IMAGETYPE = "vmlinux.bin" +SERIAL_CONSOLE = "115200 ttyS0" +MACHINE_EXTRA_RRECOMMENDS = " kernel-modules" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine.noinstall b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine.noinstall new file mode 100644 index 0000000000..b442d02d57 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=machine}} diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine/interfaces b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine/interfaces new file mode 100644 index 0000000000..16967763e5 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown/machine/interfaces @@ -0,0 +1,5 @@ +# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8) + +# The loopback interface +auto lo +iface lo inet loopback diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend new file mode 100644 index 0000000000..72d991c7e5 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-core/init-ifupdown/init-ifupdown_1.0.bbappend @@ -0,0 +1 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall new file mode 100644 index 0000000000..b442d02d57 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=machine}} diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf new file mode 100644 index 0000000000..13519804bc --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf @@ -0,0 +1,77 @@ + +Section "Files" +EndSection + +Section "InputDevice" + Identifier "Generic Keyboard" + Driver "evdev" + Option "CoreKeyboard" + Option "Device" "/dev/input/by-path/platform-i8042-serio-0-event-kbd" + Option "XkbRules" "xorg" + Option "XkbModel" "evdev" + Option "XkbLayout" "us" +EndSection + +Section "InputDevice" + Identifier "Configured Mouse" +{{ if qemuarch == "arm" or qemuarch == "powerpc" or qemuarch == "mips": }} + Driver "mouse" +{{ if qemuarch == "i386" or qemuarch == "x86_64": }} + Driver "vmmouse" + + Option "CorePointer" + Option "Device" "/dev/input/mice" + Option "Protocol" "ImPS/2" + Option "ZAxisMapping" "4 5" + Option "Emulate3Buttons" "true" +EndSection + +Section "InputDevice" + Identifier "Qemu Tablet" + Driver "evdev" + Option "CorePointer" + Option "Device" "/dev/input/touchscreen0" + Option "USB" "on" +EndSection + +Section "Device" + Identifier "Graphics Controller" +{{ if qemuarch == "arm" or qemuarch == "powerpc" or qemuarch == "mips": }} + Driver "fbdev" +{{ if qemuarch == "i386" or qemuarch == "x86_64": }} + Driver "vmware" + +EndSection + +Section "Monitor" + Identifier "Generic Monitor" + Option "DPMS" + # 1024x600 59.85 Hz (CVT) hsync: 37.35 kHz; pclk: 49.00 MHz + Modeline "1024x600_60.00" 49.00 1024 1072 1168 1312 600 603 613 624 -hsync +vsync + # 640x480 @ 60Hz (Industry standard) hsync: 31.5kHz + ModeLine "640x480" 25.2 640 656 752 800 480 490 492 525 -hsync -vsync + # 640x480 @ 72Hz (VESA) hsync: 37.9kHz + ModeLine "640x480" 31.5 640 664 704 832 480 489 491 520 -hsync -vsync + # 640x480 @ 75Hz (VESA) hsync: 37.5kHz + ModeLine "640x480" 31.5 640 656 720 840 480 481 484 500 -hsync -vsync + # 640x480 @ 85Hz (VESA) hsync: 43.3kHz + ModeLine "640x480" 36.0 640 696 752 832 480 481 484 509 -hsync -vsync +EndSection + +Section "Screen" + Identifier "Default Screen" + Device "Graphics Controller" + Monitor "Generic Monitor" + SubSection "Display" + Modes "640x480" + EndSubSection +EndSection + +Section "ServerLayout" + Identifier "Default Layout" + Screen "Default Screen" + InputDevice "Generic Keyboard" + # InputDevice "Configured Mouse" + InputDevice "QEMU Tablet" + Option "AllowEmptyInput" "no" +EndSection diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend new file mode 100644 index 0000000000..72d991c7e5 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend @@ -0,0 +1 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files.noinstall b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files.noinstall new file mode 100644 index 0000000000..0fb5283a8d --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if kernel_choice != "custom": }} files \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-preempt-rt.scc b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-preempt-rt.scc new file mode 100644 index 0000000000..6aaffb8184 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-preempt-rt.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-preempt-rt.scc +define KMACHINE {{=machine}} +define KTYPE preempt-rt +define KARCH {{=qemuarch}} + +include {{=map_preempt_rt_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-standard.scc b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-standard.scc new file mode 100644 index 0000000000..695f488064 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-standard.scc @@ -0,0 +1,17 @@ +# yocto-bsp-filename {{=machine}}-standard.scc +define KMACHINE {{=machine}} +define KTYPE standard +define KARCH {{=qemuarch}} + +{{ if qemuarch == "i386" or qemuarch == "x86_64": }} +include {{=map_standard_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if qemuarch == "arm": }} +include bsp/arm-versatile-926ejs/arm-versatile-926ejs-standard +{{ if qemuarch == "powerpc": }} +include bsp/qemu-ppc32/qemu-ppc32-standard +{{ if qemuarch == "mips": }} +include bsp/mti-malta32/mti-malta32-be-standard +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-tiny.scc b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-tiny.scc new file mode 100644 index 0000000000..6c098fed21 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-tiny.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-tiny.scc +define KMACHINE {{=machine}} +define KTYPE tiny +define KARCH {{=qemuarch}} + +include {{=map_tiny_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-config.cfg b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-config.cfg new file mode 100644 index 0000000000..69efdcc759 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-config.cfg @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-config.cfg \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-features.scc b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-features.scc new file mode 100644 index 0000000000..582759e612 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-features.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-features.scc diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-patches.scc b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-patches.scc new file mode 100644 index 0000000000..4c59daac46 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine-user-patches.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-patches.scc \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.cfg b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.cfg new file mode 100644 index 0000000000..d560784b56 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.cfg @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}.cfg \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.scc b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.scc new file mode 100644 index 0000000000..8301e05f7d --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/files/machine.scc @@ -0,0 +1,5 @@ +# yocto-bsp-filename {{=machine}}.scc +kconf hardware {{=machine}}.cfg + +kconf hardware {{=machine}}-user-config.cfg +include {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/kernel-list.noinstall b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/kernel-list.noinstall new file mode 100644 index 0000000000..a04e6c7852 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/kernel-list.noinstall @@ -0,0 +1,5 @@ +{{ if kernel_choice != "custom": }} +{{ input type:"boolean" name:"use_default_kernel" prio:"10" msg:"Would you like to use the default (3.14) kernel? (y/n)" default:"y"}} + +{{ if kernel_choice != "custom" and use_default_kernel == "n": }} +{{ input type:"choicelist" name:"kernel_choice" gen:"bsp.kernel.kernels" prio:"10" msg:"Please choose the kernel to use in this BSP:" default:"linux-yocto_3.14"}} diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-dev.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-dev.bbappend new file mode 100644 index 0000000000..a2b86d2568 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-dev.bbappend @@ -0,0 +1,50 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-dev": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base your new BSP branch on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose an existing machine branch to use for this BSP:" default:"standard/arm-versatile-926ejs" }} + +{{ if need_new_kbranch == "y" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/qemuppc" }} + +{{ if need_new_kbranch == "y" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/mti-malta32" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend new file mode 100644 index 0000000000..aa87c28ff8 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend @@ -0,0 +1,56 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-rt_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"arm" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"arm" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/qemuppc" }} + +{{ if need_new_kbranch == "y" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-preempt-rt.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-rt_{{=machine}} ?= "f35992f80c81dc5fa1a97165dfd5cbb84661f7cb" +#SRCREV_meta_pn-linux-yocto-rt_{{=machine}} ?= "1b534b2f8bbe9b8a773268cfa30a4850346f6f5f" +#LINUX_VERSION = "3.10.35" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend new file mode 100644 index 0000000000..001317ac92 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend @@ -0,0 +1,56 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"arm" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"arm" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/common-pc" }} + +{{ if need_new_kbranch == "y" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.10.35" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.4.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.4.bbappend new file mode 100644 index 0000000000..32c96c9df8 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto-tiny_3.4.bbappend @@ -0,0 +1,56 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.4": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"arm" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"arm" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/common-pc" }} + +{{ if need_new_kbranch == "y" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "0143c6ebb4a2d63b241df5f608b19f483f7eb9e0" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "8f55bee2403176a50cc0dd41811aa60fcf07243c" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.10.bbappend new file mode 100644 index 0000000000..9e3b7fb683 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.10.bbappend @@ -0,0 +1,56 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base your new BSP branch on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose an existing machine branch to use for this BSP:" default:"standard/arm-versatile-926ejs" }} + +{{ if need_new_kbranch == "y" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/qemuppc" }} + +{{ if need_new_kbranch == "y" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/mti-malta32" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "b170394a475b96ecc92cbc9e4b002bed0a9f69c5" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "c2ed0f16fdec628242a682897d5d86df4547cf24" +#LINUX_VERSION = "3.10.35" diff --git a/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.14.bbappend new file mode 100644 index 0000000000..e63c897f60 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/qemu/recipes-kernel/linux/linux-yocto_3.14.bbappend @@ -0,0 +1,56 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base your new BSP branch on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "arm": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose an existing machine branch to use for this BSP:" default:"standard/arm-versatile-926ejs" }} + +{{ if need_new_kbranch == "y" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "powerpc": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"powerpc" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/qemuppc" }} + +{{ if need_new_kbranch == "y" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "i386": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "x86_64": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"x86_64" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "y" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n" and qemuarch == "mips": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"mips" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/mti-malta32" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "0143c6ebb4a2d63b241df5f608b19f483f7eb9e0" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "8f55bee2403176a50cc0dd41811aa60fcf07243c" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/.gitignore b/scripts/lib/bsp/substrate/target/arch/x86_64/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/conf/machine/machine.conf b/scripts/lib/bsp/substrate/target/arch/x86_64/conf/machine/machine.conf new file mode 100644 index 0000000000..79b38e6b35 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/conf/machine/machine.conf @@ -0,0 +1,57 @@ +# yocto-bsp-filename {{=machine}}.conf +#@TYPE: Machine +#@NAME: {{=machine}} + +#@DESCRIPTION: Machine configuration for {{=machine}} systems + +{{ if kernel_choice == "custom": preferred_kernel = "linux-yocto-custom" }} +{{ if kernel_choice == "linux-yocto-dev": preferred_kernel = "linux-yocto-dev" }} +{{ if kernel_choice == "custom" or kernel_choice == "linux-yocto-dev" : }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" + +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel = kernel_choice.split('_')[0] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": preferred_kernel_version = kernel_choice.split('_')[1] }} +{{ if kernel_choice != "custom" and kernel_choice != "linux-yocto-dev": }} +PREFERRED_PROVIDER_virtual/kernel ?= "{{=preferred_kernel}}" +PREFERRED_VERSION_{{=preferred_kernel}} ?= "{{=preferred_kernel_version}}%" + +{{ input type:"choicelist" name:"tunefile" prio:"40" msg:"Which machine tuning would you like to use?" default:"tune_core2" }} +{{ input type:"choice" val:"tune_core2" msg:"Core2 tuning optimizations" }} +{{ input type:"choice" val:"tune_corei7" msg:"Corei7 tuning optimizations" }} +{{ if tunefile == "tune_core2": }} +DEFAULTTUNE ?= "core2-64" +require conf/machine/include/tune-core2.inc +{{ if tunefile == "tune_corei7": }} +DEFAULTTUNE ?= "corei7-64" +require conf/machine/include/tune-corei7.inc + +require conf/machine/include/x86-base.inc + +MACHINE_FEATURES += "wifi efi pcbios" + +{{ input type:"boolean" name:"xserver" prio:"50" msg:"Do you need support for X? (y/n)" default:"y" }} + +{{ if xserver == "y": }} +{{ input type:"choicelist" name:"xserver_choice" prio:"50" msg:"Please select an xserver for this machine:" default:"xserver_i915" }} + +{{ input type:"choice" val:"xserver_vesa" msg:"VESA xserver support" }} +{{ input type:"choice" val:"xserver_i915" msg:"i915 xserver support" }} +{{ input type:"choice" val:"xserver_i965" msg:"i965 xserver support" }} +{{ if xserver == "y": }} +XSERVER ?= "${XSERVER_X86_BASE} \ + ${XSERVER_X86_EXT} \ +{{ if xserver == "y" and xserver_choice == "xserver_vesa": }} + ${XSERVER_X86_VESA} \ +{{ if xserver == "y" and xserver_choice == "xserver_i915": }} + ${XSERVER_X86_I915} \ +{{ if xserver == "y" and xserver_choice == "xserver_i965": }} + ${XSERVER_X86_I965} \ +{{ if xserver == "y": }} + " + +MACHINE_EXTRA_RRECOMMENDS += "linux-firmware v86d" + +EXTRA_OECONF_append_pn-matchbox-panel-2 = " --with-battery=acpi" + +{{ if xserver == "y" and xserver_choice == "xserver_vesa": }} +APPEND += "video=vesafb vga=0x318" diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall new file mode 100644 index 0000000000..b442d02d57 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{=machine}} diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf new file mode 100644 index 0000000000..ac9a0f1bb0 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config/machine/xorg.conf @@ -0,0 +1 @@ +# yocto-bsp-filename {{ if xserver == "y": }} this diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend new file mode 100644 index 0000000000..30830031ed --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend @@ -0,0 +1,2 @@ +# yocto-bsp-filename {{ if xserver == "y": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files.noinstall b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files.noinstall new file mode 100644 index 0000000000..1e0d92c55c --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files.noinstall @@ -0,0 +1 @@ +# yocto-bsp-dirname {{ if kernel_choice != "custom": }} files diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-preempt-rt.scc b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-preempt-rt.scc new file mode 100644 index 0000000000..fd5320ba1e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-preempt-rt.scc @@ -0,0 +1,16 @@ +# yocto-bsp-filename {{=machine}}-preempt-rt.scc +define KMACHINE {{=machine}} +define KTYPE preempt-rt +define KARCH x86_64 + +include {{=map_preempt_rt_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc + +# default policy for preempt-rt kernels +include cfg/usb-mass-storage.scc +include cfg/boot-live.scc +include features/latencytop/latencytop.scc +include features/profiling/profiling.scc diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-standard.scc b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-standard.scc new file mode 100644 index 0000000000..569f967c6a --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-standard.scc @@ -0,0 +1,16 @@ +# yocto-bsp-filename {{=machine}}-standard.scc +define KMACHINE {{=machine}} +define KTYPE standard +define KARCH x86_64 + +include {{=map_standard_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc + +# default policy for standard kernels +include cfg/usb-mass-storage.scc +include cfg/boot-live.scc +include features/latencytop/latencytop.scc +include features/profiling/profiling.scc diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-tiny.scc b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-tiny.scc new file mode 100644 index 0000000000..fb21432a4f --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-tiny.scc @@ -0,0 +1,10 @@ +# yocto-bsp-filename {{=machine}}-tiny.scc +define KMACHINE {{=machine}} +define KTYPE tiny +define KARCH x86_64 + +include {{=map_tiny_kbranch(need_new_kbranch, new_kbranch, existing_kbranch)}} +{{ if need_new_kbranch == "y": }} +branch {{=machine}} + +include {{=machine}}.scc diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-config.cfg b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-config.cfg new file mode 100644 index 0000000000..47489e44e9 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-config.cfg @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-config.cfg diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-features.scc b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-features.scc new file mode 100644 index 0000000000..582759e612 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-features.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-features.scc diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-patches.scc b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-patches.scc new file mode 100644 index 0000000000..97f747fa07 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine-user-patches.scc @@ -0,0 +1 @@ +# yocto-bsp-filename {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.cfg b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.cfg new file mode 100644 index 0000000000..3290ddefe7 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.cfg @@ -0,0 +1,48 @@ +# yocto-bsp-filename {{=machine}}.cfg +CONFIG_PRINTK=y + +# Basic hardware support for the box - network, USB, PCI, sound +CONFIG_NETDEVICES=y +CONFIG_ATA=y +CONFIG_ATA_GENERIC=y +CONFIG_ATA_SFF=y +CONFIG_PCI=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_USB_SUPPORT=y +CONFIG_USB=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_R8169=y +CONFIG_PATA_SCH=y +CONFIG_MMC_SDHCI_PCI=y +CONFIG_USB_EHCI_HCD=y +CONFIG_PCIEPORTBUS=y +CONFIG_NET=y +CONFIG_USB_UHCI_HCD=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_HDA_INTEL=y + +# Make sure these are on, otherwise the bootup won't be fun +CONFIG_EXT3_FS=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_MODULES=y +CONFIG_SHMEM=y +CONFIG_TMPFS=y +CONFIG_PACKET=y + +CONFIG_I2C=y +CONFIG_AGP=y +CONFIG_PM=y +CONFIG_ACPI=y +CONFIG_INPUT=y + +# Needed for booting (and using) USB memory sticks +CONFIG_BLK_DEV_LOOP=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y + +CONFIG_RD_GZIP=y diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.scc b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.scc new file mode 100644 index 0000000000..9b7c291a8f --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/files/machine.scc @@ -0,0 +1,14 @@ +# yocto-bsp-filename {{=machine}}.scc +kconf hardware {{=machine}}.cfg + +include features/serial/8250.scc +{{ if xserver == "y" and xserver_choice == "xserver_vesa": }} +include cfg/vesafb.scc +{{ if xserver == "y" and xserver_choice == "xserver_i915" or xserver_choice == "xserver_i965": }} +include features/i915/i915.scc + +include cfg/usb-mass-storage.scc +include features/power/intel.scc + +kconf hardware {{=machine}}-user-config.cfg +include {{=machine}}-user-patches.scc diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/kernel-list.noinstall b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/kernel-list.noinstall new file mode 100644 index 0000000000..a04e6c7852 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/kernel-list.noinstall @@ -0,0 +1,5 @@ +{{ if kernel_choice != "custom": }} +{{ input type:"boolean" name:"use_default_kernel" prio:"10" msg:"Would you like to use the default (3.14) kernel? (y/n)" default:"y"}} + +{{ if kernel_choice != "custom" and use_default_kernel == "n": }} +{{ input type:"choicelist" name:"kernel_choice" gen:"bsp.kernel.kernels" prio:"10" msg:"Please choose the kernel to use in this BSP:" default:"linux-yocto_3.14"}} diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-dev.bbappend b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-dev.bbappend new file mode 100644 index 0000000000..2fa6231cbf --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-dev.bbappend @@ -0,0 +1,26 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-dev": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" nameappend:"i386" gen:"bsp.kernel.all_branches" branches_base:"standard" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Would you like SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend new file mode 100644 index 0000000000..39bc72d9c4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-rt_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-rt_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/preempt-rt" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/preempt-rt/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-preempt-rt.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-rt_{{=machine}} ?= "f35992f80c81dc5fa1a97165dfd5cbb84661f7cb" +#SRCREV_meta_pn-linux-yocto-rt_{{=machine}} ?= "1b534b2f8bbe9b8a773268cfa30a4850346f6f5f" +#LINUX_VERSION = "3.10.9" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend new file mode 100644 index 0000000000..f04dd0cce4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.10.9" diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend new file mode 100644 index 0000000000..471ccbcc3e --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto-tiny_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto-tiny_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard/tiny" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/tiny/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-tiny.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto-tiny_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto-tiny_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.10.bbappend b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.10.bbappend new file mode 100644 index 0000000000..e21a333fa4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.10.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.10": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "b170394a475b96ecc92cbc9e4b002bed0a9f69c5" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "c2ed0f16fdec628242a682897d5d86df4547cf24" +#LINUX_VERSION = "3.10.9" \ No newline at end of file diff --git a/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.14.bbappend b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.14.bbappend new file mode 100644 index 0000000000..ca0b497ff4 --- /dev/null +++ b/scripts/lib/bsp/substrate/target/arch/x86_64/recipes-kernel/linux/linux-yocto_3.14.bbappend @@ -0,0 +1,33 @@ +# yocto-bsp-filename {{ if kernel_choice == "linux-yocto_3.14": }} this +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +PR := "${PR}.1" + +COMPATIBLE_MACHINE_{{=machine}} = "{{=machine}}" + +{{ input type:"boolean" name:"need_new_kbranch" prio:"20" msg:"Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n]" default:"y" }} + +{{ if need_new_kbranch == "y": }} +{{ input type:"choicelist" name:"new_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "n": }} +{{ input type:"choicelist" name:"existing_kbranch" gen:"bsp.kernel.all_branches" branches_base:"standard:standard/common-pc-64" prio:"20" msg:"Please choose a machine branch to base this BSP on:" default:"standard/common-pc-64/base" }} + +{{ if need_new_kbranch == "n": }} +KBRANCH_{{=machine}} = "{{=existing_kbranch}}" + +{{ input type:"boolean" name:"smp" prio:"30" msg:"Do you need SMP support? (y/n)" default:"y"}} +{{ if smp == "y": }} +KERNEL_FEATURES_append_{{=machine}} += " cfg/smp.scc" + +SRC_URI += "file://{{=machine}}-standard.scc \ + file://{{=machine}}-user-config.cfg \ + file://{{=machine}}-user-patches.scc \ + file://{{=machine}}-user-features.scc \ + " + +# uncomment and replace these SRCREVs with the real commit ids once you've had +# the appropriate changes committed to the upstream linux-yocto repo +#SRCREV_machine_pn-linux-yocto_{{=machine}} ?= "840bb8c059418c4753415df56c9aff1c0d5354c8" +#SRCREV_meta_pn-linux-yocto_{{=machine}} ?= "4fd76cc4f33e0afd8f906b1e8f231b6d13b6c993" +#LINUX_VERSION = "3.14" diff --git a/scripts/lib/bsp/tags.py b/scripts/lib/bsp/tags.py new file mode 100644 index 0000000000..3719427884 --- /dev/null +++ b/scripts/lib/bsp/tags.py @@ -0,0 +1,49 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2012, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module provides a place to define common constants for the +# Yocto BSP Tools. +# +# AUTHORS +# Tom Zanussi +# + +OPEN_TAG = "{{" +CLOSE_TAG = "}}" +ASSIGN_TAG = "{{=" +INPUT_TAG = "input" +IF_TAG = "if" +FILENAME_TAG = "yocto-bsp-filename" +DIRNAME_TAG = "yocto-bsp-dirname" + +INDENT_STR = " " + +BLANKLINE_STR = "of.write(\"\\n\")" +NORMAL_START = "of.write" +OPEN_START = "current_file =" + +INPUT_TYPE_PROPERTY = "type" + +SRC_URI_FILE = "file://" + +GIT_CHECK_URI = "git://git.yoctoproject.org/linux-yocto-dev.git" + + + diff --git a/scripts/lib/image/__init__.py b/scripts/lib/image/__init__.py new file mode 100644 index 0000000000..1ff814e761 --- /dev/null +++ b/scripts/lib/image/__init__.py @@ -0,0 +1,22 @@ +# +# OpenEmbedded Image tools library +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# AUTHORS +# Tom Zanussi +# diff --git a/scripts/lib/image/canned-wks/directdisk.wks b/scripts/lib/image/canned-wks/directdisk.wks new file mode 100644 index 0000000000..62dcab15ce --- /dev/null +++ b/scripts/lib/image/canned-wks/directdisk.wks @@ -0,0 +1,10 @@ +# short-description: Create a 'pcbios' direct disk image +# long-description: Creates a partitioned legacy BIOS disk image that the user +# can directly dd to boot media. + + +part /boot --source bootimg-pcbios --ondisk sda --label boot --active --align 1024 +part / --source rootfs --ondisk sda --fstype=ext3 --label platform --align 1024 + +bootloader --timeout=0 --append="rootwait rootfstype=ext3 video=vesafb vga=0x318 console=tty0" + diff --git a/scripts/lib/image/canned-wks/mkefidisk.wks b/scripts/lib/image/canned-wks/mkefidisk.wks new file mode 100644 index 0000000000..58d42e61eb --- /dev/null +++ b/scripts/lib/image/canned-wks/mkefidisk.wks @@ -0,0 +1,11 @@ +# short-description: Create an EFI disk image +# long-description: Creates a partitioned EFI disk image that the user +# can directly dd to boot media. + +part /boot --source bootimg-efi --sourceparams="loader=grub-efi" --ondisk sda --label msdos --active --align 1024 + +part / --source rootfs --ondisk sda --fstype=ext3 --label platform --align 1024 + +part swap --ondisk sda --size 44 --label swap1 --fstype=swap + +bootloader --timeout=10 --append="rootwait rootfstype=ext3 console=ttyPCH0,115200 console=tty0 vmalloc=256MB snd-hda-intel.enable_msi=0" diff --git a/scripts/lib/image/canned-wks/mkgummidisk.wks b/scripts/lib/image/canned-wks/mkgummidisk.wks new file mode 100644 index 0000000000..f81cbdfb84 --- /dev/null +++ b/scripts/lib/image/canned-wks/mkgummidisk.wks @@ -0,0 +1,11 @@ +# short-description: Create an EFI disk image +# long-description: Creates a partitioned EFI disk image that the user +# can directly dd to boot media. + +part /boot --source bootimg-efi --sourceparams="loader=gummiboot" --ondisk sda --label msdos --active --align 1024 + +part / --source rootfs --ondisk sda --fstype=ext3 --label platform --align 1024 + +part swap --ondisk sda --size 44 --label swap1 --fstype=swap + +bootloader --timeout=10 --append="rootwait rootfstype=ext3 console=ttyPCH0,115200 console=tty0 vmalloc=256MB snd-hda-intel.enable_msi=0" diff --git a/scripts/lib/image/canned-wks/sdimage-bootpart.wks b/scripts/lib/image/canned-wks/sdimage-bootpart.wks new file mode 100644 index 0000000000..7ffd632f4a --- /dev/null +++ b/scripts/lib/image/canned-wks/sdimage-bootpart.wks @@ -0,0 +1,6 @@ +# short-description: Create SD card image with a boot partition +# long-description: Creates a partitioned SD card image. Boot files +# are located in the first vfat partition. + +part /boot --source bootimg-partition --ondisk mmcblk --fstype=vfat --label boot --active --align 4 --size 16 +part / --source rootfs --ondisk mmcblk --fstype=ext4 --label root --align 4 diff --git a/scripts/lib/image/canned-wks/uboot.wks b/scripts/lib/image/canned-wks/uboot.wks new file mode 100644 index 0000000000..7de0572d0f --- /dev/null +++ b/scripts/lib/image/canned-wks/uboot.wks @@ -0,0 +1,17 @@ +# short-description: . Create a ramdisk image for U-Boot +# long-description: Creates a ramdisk image for U-Boot that user +# can directly load it into ram through tftp +# +# part - is a wic command that drive the process of generating a valid file system +# - --source=uboot : wic plugin that generates a ramdisk image for U-Boot +# - --fstype=ext2 : file system type( ext2 / ext3 / ext 4) +# +# %packages %end - option to provide a list of packages that will be installed +# into rootfs. All packages dependencies will be installed by +# package manager(default opkg). + + +part / --source=uboot --fstype=ext2 --label imageName --align 1024 + +%packages +%end diff --git a/scripts/lib/image/config/wic.conf b/scripts/lib/image/config/wic.conf new file mode 100644 index 0000000000..2de8fa91f7 --- /dev/null +++ b/scripts/lib/image/config/wic.conf @@ -0,0 +1,10 @@ +[common] +; general settings +distro_name = OpenEmbedded + +[create] +; settings for create subcommand +; repourl=http://linux.com/ipk/all http://linux.com/ipk/target http://linux.com/ipk/arch +arch=powerpc +pkgmgr=opkg +install_pkgs=source diff --git a/scripts/lib/image/engine.py b/scripts/lib/image/engine.py new file mode 100644 index 0000000000..e794545e94 --- /dev/null +++ b/scripts/lib/image/engine.py @@ -0,0 +1,279 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION + +# This module implements the image creation engine used by 'wic' to +# create images. The engine parses through the OpenEmbedded kickstart +# (wks) file specified and generates images that can then be directly +# written onto media. +# +# AUTHORS +# Tom Zanussi +# + +import os +import sys +from abc import ABCMeta, abstractmethod +import shlex +import json +import subprocess +import shutil + +import os, sys, errno +from wic import msger, creator +from wic.utils import cmdln, misc, errors +from wic.conf import configmgr +from wic.plugin import pluginmgr +from wic.__version__ import VERSION +from wic.utils.oe.misc import * + + +def verify_build_env(): + """ + Verify that the build environment is sane. + + Returns True if it is, false otherwise + """ + try: + builddir = os.environ["BUILDDIR"] + except KeyError: + print "BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)" + sys.exit(1) + + return True + + +def find_artifacts(image_name): + """ + Gather the build artifacts for the current image (the image_name + e.g. core-image-minimal) for the current MACHINE set in local.conf + """ + bitbake_env_lines = get_bitbake_env_lines() + + rootfs_dir = kernel_dir = bootimg_dir = native_sysroot = "" + + for line in bitbake_env_lines.split('\n'): + if (get_line_val(line, "IMAGE_ROOTFS")): + rootfs_dir = get_line_val(line, "IMAGE_ROOTFS") + continue + if (get_line_val(line, "STAGING_KERNEL_DIR")): + kernel_dir = get_line_val(line, "STAGING_KERNEL_DIR") + continue + if (get_line_val(line, "STAGING_DIR_NATIVE")): + native_sysroot = get_line_val(line, "STAGING_DIR_NATIVE") + continue + + return (rootfs_dir, kernel_dir, bootimg_dir, native_sysroot) + + +CANNED_IMAGE_DIR = "lib/image/canned-wks" # relative to scripts +SCRIPTS_CANNED_IMAGE_DIR = "scripts/" + CANNED_IMAGE_DIR + +def build_canned_image_list(dl): + layers_path = get_bitbake_var("BBLAYERS") + canned_wks_layer_dirs = [] + + if layers_path is not None: + for layer_path in layers_path.split(): + path = os.path.join(layer_path, SCRIPTS_CANNED_IMAGE_DIR) + canned_wks_layer_dirs.append(path) + + path = os.path.join(dl, CANNED_IMAGE_DIR) + canned_wks_layer_dirs.append(path) + + return canned_wks_layer_dirs + +def find_canned_image(scripts_path, wks_file): + """ + Find a .wks file with the given name in the canned files dir. + + Return False if not found + """ + layers_canned_wks_dir = build_canned_image_list(scripts_path) + + for canned_wks_dir in layers_canned_wks_dir: + for root, dirs, files in os.walk(canned_wks_dir): + for file in files: + if file.endswith("~") or file.endswith("#"): + continue + if file.endswith(".wks") and wks_file + ".wks" == file: + fullpath = os.path.join(canned_wks_dir, file) + return fullpath + return None + + +def list_canned_images(scripts_path): + """ + List the .wks files in the canned image dir, minus the extension. + """ + layers_canned_wks_dir = build_canned_image_list(scripts_path) + + for canned_wks_dir in layers_canned_wks_dir: + for root, dirs, files in os.walk(canned_wks_dir): + for file in files: + if file.endswith("~") or file.endswith("#"): + continue + if file.endswith(".wks"): + fullpath = os.path.join(canned_wks_dir, file) + f = open(fullpath, "r") + lines = f.readlines() + for line in lines: + desc = "" + idx = line.find("short-description:") + if idx != -1: + desc = line[idx + len("short-description:"):].strip() + break + basename = os.path.splitext(file)[0] + print " %s\t\t%s" % (basename.ljust(30), desc) + + +def list_canned_image_help(scripts_path, fullpath): + """ + List the help and params in the specified canned image. + """ + f = open(fullpath, "r") + lines = f.readlines() + found = False + for line in lines: + if not found: + idx = line.find("long-description:") + if idx != -1: + print + print line[idx + len("long-description:"):].strip() + found = True + continue + if not line.strip(): + break + idx = line.find("#") + if idx != -1: + print line[idx + len("#:"):].rstrip() + else: + break + + +def list_source_plugins(): + """ + List the available source plugins i.e. plugins available for --source. + """ + plugins = pluginmgr.get_source_plugins() + + for plugin in plugins: + print " %s" % plugin + + +def wic_create(args, wks_file, rootfs_dir, bootimg_dir, kernel_dir, + native_sysroot, scripts_path, image_output_dir, debug, + properties_file, properties=None): + """Create image + + wks_file - user-defined OE kickstart file + rootfs_dir - absolute path to the build's /rootfs dir + bootimg_dir - absolute path to the build's boot artifacts directory + kernel_dir - absolute path to the build's kernel directory + native_sysroot - absolute path to the build's native sysroots dir + scripts_path - absolute path to /scripts dir + image_output_dir - dirname to create for image + properties_file - use values from this file if nonempty i.e no prompting + properties - use values from this string if nonempty i.e no prompting + + Normally, the values for the build artifacts values are determined + by 'wic -e' from the output of the 'bitbake -e' command given an + image name e.g. 'core-image-minimal' and a given machine set in + local.conf. If that's the case, the variables get the following + values from the output of 'bitbake -e': + + rootfs_dir: IMAGE_ROOTFS + kernel_dir: STAGING_KERNEL_DIR + native_sysroot: STAGING_DIR_NATIVE + + In the above case, bootimg_dir remains unset and the + plugin-specific image creation code is responsible for finding the + bootimg artifacts. + + In the case where the values are passed in explicitly i.e 'wic -e' + is not used but rather the individual 'wic' options are used to + explicitly specify these values. + """ + try: + oe_builddir = os.environ["BUILDDIR"] + except KeyError: + print "BUILDDIR not found, exiting. (Did you forget to source oe-init-build-env?)" + sys.exit(1) + + direct_args = list() + direct_args.insert(0, oe_builddir) + direct_args.insert(0, image_output_dir) + direct_args.insert(0, wks_file) + direct_args.insert(0, rootfs_dir) + direct_args.insert(0, bootimg_dir) + direct_args.insert(0, kernel_dir) + direct_args.insert(0, native_sysroot) + direct_args.insert(0, "direct") + + if debug: + msger.set_loglevel('debug') + + cr = creator.Creator() + + cr.main(direct_args) + + print "\nThe image(s) were created using OE kickstart file:\n %s" % wks_file + + +def wic_list(args, scripts_path, properties_file): + """ + Print the complete list of properties defined by the image, or the + possible values for a particular image property. + """ + if len(args) < 1: + return False + + if len(args) == 1: + if args[0] == "images": + list_canned_images(scripts_path) + return True + elif args[0] == "source-plugins": + list_source_plugins() + return True + elif args[0] == "properties": + return True + else: + return False + + if len(args) == 2: + if args[0] == "properties": + wks_file = args[1] + print "print properties contained in wks file: %s" % wks_file + return True + elif args[0] == "property": + print "print property values for property: %s" % args[1] + return True + elif args[1] == "help": + wks_file = args[0] + fullpath = find_canned_image(scripts_path, wks_file) + if not fullpath: + print "No image named %s found, exiting. (Use 'wic list images' to list available images, or specify a fully-qualified OE kickstart (.wks) filename)\n" % wks_file + sys.exit(1) + list_canned_image_help(scripts_path, fullpath) + return True + else: + return False + + return False diff --git a/scripts/lib/image/help.py b/scripts/lib/image/help.py new file mode 100644 index 0000000000..6b74f57662 --- /dev/null +++ b/scripts/lib/image/help.py @@ -0,0 +1,756 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module implements some basic help invocation functions along +# with the bulk of the help topic text for the OE Core Image Tools. +# +# AUTHORS +# Tom Zanussi +# + +import subprocess +import logging + + +def subcommand_error(args): + logging.info("invalid subcommand %s" % args[0]) + + +def display_help(subcommand, subcommands): + """ + Display help for subcommand. + """ + if subcommand not in subcommands: + return False + + help = subcommands.get(subcommand, subcommand_error)[2] + pager = subprocess.Popen('less', stdin=subprocess.PIPE) + pager.communicate(help) + + return True + + +def wic_help(args, usage_str, subcommands): + """ + Subcommand help dispatcher. + """ + if len(args) == 1 or not display_help(args[1], subcommands): + print(usage_str) + + +def invoke_subcommand(args, parser, main_command_usage, subcommands): + """ + Dispatch to subcommand handler borrowed from combo-layer. + Should use argparse, but has to work in 2.6. + """ + if not args: + logging.error("No subcommand specified, exiting") + parser.print_help() + elif args[0] == "help": + wic_help(args, main_command_usage, subcommands) + elif args[0] not in subcommands: + logging.error("Unsupported subcommand %s, exiting\n" % (args[0])) + parser.print_help() + else: + usage = subcommands.get(args[0], subcommand_error)[1] + subcommands.get(args[0], subcommand_error)[0](args[1:], usage) + + +## +# wic help and usage strings +## + +wic_usage = """ + + Create a customized OpenEmbedded image + + usage: wic [--version] [--help] COMMAND [ARGS] + + Current 'wic' commands are: + create Create a new OpenEmbedded image + list List available values for options and image properties + + Help topics: + overview wic overview - General overview of wic + plugins wic plugins - Overview and API + kickstart wic kickstart - wic kickstart reference + + See 'wic help ' for more information on a specific + command or help topic. +""" + +wic_help_usage = """ + + usage: wic help + + This command displays detailed help for the specified subcommand. +""" + +wic_create_usage = """ + + Create a new OpenEmbedded image + + usage: wic create [-o | --outdir ] + [-i | --infile ] + [-e | --image-name] [-s, --skip-build-check] [-D, --debug] + [-r, --rootfs-dir] [-b, --bootimg-dir] + [-k, --kernel-dir] [-n, --native-sysroot] + + This command creates an OpenEmbedded image based on the 'OE kickstart + commands' found in the . + + The -o option can be used to place the image in a directory with a + different name and location. + + See 'wic help create' for more detailed instructions. +""" + +wic_create_help = """ + +NAME + wic create - Create a new OpenEmbedded image + +SYNOPSIS + wic create [-o | --outdir ] + [-i | --infile ] + [-e | --image-name] [-s, --skip-build-check] [-D, --debug] + [-r, --rootfs-dir] [-b, --bootimg-dir] + [-k, --kernel-dir] [-n, --native-sysroot] + +DESCRIPTION + This command creates an OpenEmbedded image based on the 'OE + kickstart commands' found in the . + + In order to do this, wic needs to know the locations of the + various build artifacts required to build the image. + + Users can explicitly specify the build artifact locations using + the -r, -b, -k, and -n options. See below for details on where + the corresponding artifacts are typically found in a normal + OpenEmbedded build. + + Alternatively, users can use the -e option to have 'wic' determine + those locations for a given image. If the -e option is used, the + user needs to have set the appropriate MACHINE variable in + local.conf, and have sourced the build environment. + + The -e option is used to specify the name of the image to use the + artifacts from e.g. core-image-sato. + + The -r option is used to specify the path to the /rootfs dir to + use as the .wks rootfs source. + + The -b option is used to specify the path to the dir containing + the boot artifacts (e.g. /EFI or /syslinux dirs) to use as the + .wks bootimg source. + + The -k option is used to specify the path to the dir containing + the kernel to use in the .wks bootimg. + + The -n option is used to specify the path to the native sysroot + containing the tools to use to build the image. + + The -s option is used to skip the build check. The build check is + a simple sanity check used to determine whether the user has + sourced the build environment so that the -e option can operate + correctly. If the user has specified the build artifact locations + explicitly, 'wic' assumes the user knows what he or she is doing + and skips the build check. + + The -D option is used to display debug information detailing + exactly what happens behind the scenes when a create request is + fulfilled (or not, as the case may be). It enumerates and + displays the command sequence used, and should be included in any + bug report describing unexpected results. + + When 'wic -e' is used, the locations for the build artifacts + values are determined by 'wic -e' from the output of the 'bitbake + -e' command given an image name e.g. 'core-image-minimal' and a + given machine set in local.conf. In that case, the image is + created as if the following 'bitbake -e' variables were used: + + -r: IMAGE_ROOTFS + -k: STAGING_KERNEL_DIR + -n: STAGING_DIR_NATIVE + -b: empty (plugin-specific handlers must determine this) + + If 'wic -e' is not used, the user needs to select the appropriate + value for -b (as well as -r, -k, and -n). + + The -o option can be used to place the image in a directory with a + different name and location. + + As an alternative to the wks file, the image-specific properties + that define the values that will be used to generate a particular + image can be specified on the command-line using the -i option and + supplying a JSON object consisting of the set of name:value pairs + needed by image creation. + + The set of properties available for a given image type can be + listed using the 'wic list' command. +""" + +wic_list_usage = """ + + List available OpenEmbedded image properties and values + + usage: wic list images + wic list help + wic list source-plugins + wic list properties + wic list properties + wic list property + [-o | --outfile ] + + This command enumerates the set of available canned images as well as + help for those images. It also can be used to enumerate the complete + set of possible values for a specified option or property needed by + the image creation process. + + The first form enumerates all the available 'canned' images. + + The second form lists the detailed help information for a specific + 'canned' image. + + The third form enumerates all the available --sources (source + plugins). + + The fourth form enumerates all the possible values that exist and can + be specified in an OE kickstart (wks) file. + + The fifth form enumerates all the possible options that exist for the + set of properties specified in a given OE kickstart (ks) file. + + The final form enumerates all the possible values that exist and can + be specified for any given OE kickstart (wks) property. + + See 'wic help list' for more details. +""" + +wic_list_help = """ + +NAME + wic list - List available OpenEmbedded image properties and values + +SYNOPSIS + wic list images + wic list help + wic list source-plugins + wic list properties + wic list properties + wic list property + [-o | --outfile ] + +DESCRIPTION + This command enumerates the complete set of possible values for a + specified option or property needed by the image creation process. + + This command enumerates the set of available canned images as well + as help for those images. It also can be used to enumerate the + complete set of possible values for a specified option or property + needed by the image creation process. + + The first form enumerates all the available 'canned' images. + These are actually just the set of .wks files that have been moved + into the /scripts/lib/image/canned-wks directory). + + The second form lists the detailed help information for a specific + 'canned' image. + + The third form enumerates all the available --sources (source + plugins). The contents of a given partition are driven by code + defined in 'source plugins'. Users specify a specific plugin via + the --source parameter of the partition .wks command. Normally + this is the 'rootfs' plugin but can be any of the more specialized + sources listed by the 'list source-plugins' command. Users can + also add their own source plugins - see 'wic help plugins' for + details. + + The third form enumerates all the possible values that exist and + can be specified in a OE kickstart (wks) file. The output of this + can be used by the third form to print the description and + possible values of a specific property. + + The fourth form enumerates all the possible options that exist for + the set of properties specified in a given OE kickstart (wks) + file. If the -o option is specified, the list of properties, in + addition to being displayed, will be written to the specified file + as a JSON object. In this case, the object will consist of the + set of name:value pairs corresponding to the (possibly nested) + dictionary of properties defined by the input statements used by + the image. Some example output for the 'list ' command: + + $ wic list test.ks + "part" : { + "mountpoint" : "/" + "fstype" : "ext3" + } + "part" : { + "mountpoint" : "/home" + "fstype" : "ext3" + "offset" : "10000" + } + "bootloader" : { + "type" : "efi" + } + . + . + . + + Each entry in the output consists of the name of the input element + e.g. "part", followed by the properties defined for that + element enclosed in braces. This information should provide + sufficient information to create a complete user interface with. + + The final form enumerates all the possible values that exist and + can be specified for any given OE kickstart (wks) property. If + the -o option is specified, the list of values for the given + property, in addition to being displayed, will be written to the + specified file as a JSON object. In this case, the object will + consist of the set of name:value pairs corresponding to the array + of property values associated with the property. + + $ wic list property part + ["mountpoint", "where the partition should be mounted"] + ["fstype", "filesytem type of the partition"] + ["ext3"] + ["ext4"] + ["btrfs"] + ["swap"] + ["offset", "offset of the partition within the image"] + +""" + +wic_plugins_help = """ + +NAME + wic plugins - Overview and API + +DESCRIPTION + plugins allow wic functionality to be extended and specialized by + users. This section documents the plugin interface, which is + currently restricted to 'source' plugins. + + 'Source' plugins provide a mechanism to customize various aspects + of the image generation process in wic, mainly the contents of + partitions. + + Source plugins provide a mechanism for mapping values specified in + .wks files using the --source keyword to a particular plugin + implementation that populates a corresponding partition. + + A source plugin is created as a subclass of SourcePlugin (see + scripts/lib/wic/pluginbase.py) and the plugin file containing it + is added to scripts/lib/wic/plugins/source/ to make the plugin + implementation available to the wic implementation. + + Source plugins can also be implemented and added by external + layers - any plugins found in a scripts/lib/wic/plugins/source/ + directory in an external layer will also be made available. + + When the wic implementation needs to invoke a partition-specific + implementation, it looks for the plugin that has the same name as + the --source param given to that partition. For example, if the + partition is set up like this: + + part /boot --source bootimg-pcbios ... + + then the methods defined as class members of the plugin having the + matching bootimg-pcbios .name class member would be used. + + To be more concrete, here's the plugin definition that would match + a '--source bootimg-pcbios' usage, along with an example method + that would be called by the wic implementation when it needed to + invoke an implementation-specific partition-preparation function: + + class BootimgPcbiosPlugin(SourcePlugin): + name = 'bootimg-pcbios' + + @classmethod + def do_prepare_partition(self, part, ...) + + If the subclass itself doesn't implement a function, a 'default' + version in a superclass will be located and used, which is why all + plugins must be derived from SourcePlugin. + + The SourcePlugin class defines the following methods, which is the + current set of methods that can be implemented/overridden by + --source plugins. Any methods not implemented by a SourcePlugin + subclass inherit the implementations present in the SourcePlugin + class (see the SourcePlugin source for details): + + do_prepare_partition() + Called to do the actual content population for a + partition. In other words, it 'prepares' the final partition + image which will be incorporated into the disk image. + + do_configure_partition() + Called before do_prepare_partition(), typically used to + create custom configuration files for a partition, for + example syslinux or grub config files. + + do_install_disk() + Called after all partitions have been prepared and assembled + into a disk image. This provides a hook to allow + finalization of a disk image, for example to write an MBR to + it. + + do_stage_partition() + Special content-staging hook called before + do_prepare_partition(), normally empty. + + Typically, a partition will just use the passed-in + parameters, for example the unmodified value of bootimg_dir. + In some cases however, things may need to be more tailored. + As an example, certain files may additionally need to be + take from bootimg_dir + /boot. This hook allows those files + to be staged in a customized fashion. Note that + get_bitbake_var() allows you to access non-standard + variables that you might want to use for these types of + situations. + + This scheme is extensible - adding more hooks is a simple matter + of adding more plugin methods to SourcePlugin and derived classes. + The code that then needs to call the plugin methods uses + plugin.get_source_plugin_methods() to find the method(s) needed by + the call; this is done by filling up a dict with keys containing + the method names of interest - on success, these will be filled in + with the actual methods. Please see the implementation for + examples and details. +""" + +wic_overview_help = """ + +NAME + wic overview - General overview of wic + +DESCRIPTION + The 'wic' command generates partitioned images from existing + OpenEmbedded build artifacts. Image generation is driven by + partitioning commands contained in an 'Openembedded kickstart' + (.wks) file (see 'wic help kickstart') specified either directly + on the command-line or as one of a selection of canned .wks files + (see 'wic list images'). When applied to a given set of build + artifacts, the result is an image or set of images that can be + directly written onto media and used on a particular system. + + The 'wic' command and the infrastructure it's based on is by + definition incomplete - its purpose is to allow the generation of + customized images, and as such was designed to be completely + extensible via a plugin interface (see 'wic help plugins'). + + Background and Motivation + + wic is meant to be a completely independent standalone utility + that initially provides easier-to-use and more flexible + replacements for a couple bits of existing functionality in + oe-core: directdisk.bbclass and mkefidisk.sh. The difference + between wic and those examples is that with wic the functionality + of those scripts is implemented by a general-purpose partitioning + 'language' based on Redhat kickstart syntax). + + The initial motivation and design considerations that lead to the + current tool are described exhaustively in Yocto Bug #3847 + (https://bugzilla.yoctoproject.org/show_bug.cgi?id=3847). + + Implementation and Examples + + wic can be used in two different modes, depending on how much + control the user needs in specifying the Openembedded build + artifacts that will be used in creating the image: 'raw' and + 'cooked'. + + If used in 'raw' mode, artifacts are explicitly specified via + command-line arguments (see example below). + + The more easily usable 'cooked' mode uses the current MACHINE + setting and a specified image name to automatically locate the + artifacts used to create the image. + + OE kickstart files (.wks) can of course be specified directly on + the command-line, but the user can also choose from a set of + 'canned' .wks files available via the 'wic list images' command + (example below). + + In any case, the prerequisite for generating any image is to have + the build artifacts already available. The below examples assume + the user has already build a 'core-image-minimal' for a specific + machine (future versions won't require this redundant step, but + for now that's typically how build artifacts get generated). + + The other prerequisite is to source the build environment: + + $ source oe-init-build-env + + To start out with, we'll generate an image from one of the canned + .wks files. The following generates a list of availailable + images: + + $ wic list images + mkefidisk Create an EFI disk image + directdisk Create a 'pcbios' direct disk image + + You can get more information about any of the available images by + typing 'wic list xxx help', where 'xxx' is one of the image names: + + $ wic list mkefidisk help + + Creates a partitioned EFI disk image that the user can directly dd + to boot media. + + At any time, you can get help on the 'wic' command or any + subcommand (currently 'list' and 'create'). For instance, to get + the description of 'wic create' command and its parameters: + + $ wic create + + Usage: + + Create a new OpenEmbedded image + + usage: wic create [-o | ...] + [-i | --infile ] + [-e | --image-name] [-s, --skip-build-check] [-D, --debug] + [-r, --rootfs-dir] [-b, --bootimg-dir] + [-k, --kernel-dir] [-n, --native-sysroot] + + This command creates an OpenEmbedded image based on the 'OE + kickstart commands' found in the . + + The -o option can be used to place the image in a directory + with a different name and location. + + See 'wic help create' for more detailed instructions. + ... + + As mentioned in the command, you can get even more detailed + information by adding 'help' to the above: + + $ wic help create + + So, the easiest way to create an image is to use the -e option + with a canned .wks file. To use the -e option, you need to + specify the image used to generate the artifacts and you actually + need to have the MACHINE used to build them specified in your + local.conf (these requirements aren't necessary if you aren't + using the -e options.) Below, we generate a directdisk image, + pointing the process at the core-image-minimal artifacts for the + current MACHINE: + + $ wic create directdisk -e core-image-minimal + + Checking basic build environment... + Done. + + Creating image(s)... + + Info: The new image(s) can be found here: + /var/tmp/wic/build/directdisk-201309252350-sda.direct + + The following build artifacts were used to create the image(s): + + ROOTFS_DIR: ... + BOOTIMG_DIR: ... + KERNEL_DIR: ... + NATIVE_SYSROOT: ... + + The image(s) were created using OE kickstart file: + .../scripts/lib/image/canned-wks/directdisk.wks + + The output shows the name and location of the image created, and + so that you know exactly what was used to generate the image, each + of the artifacts and the kickstart file used. + + Similarly, you can create a 'mkefidisk' image in the same way + (notice that this example uses a different machine - because it's + using the -e option, you need to change the MACHINE in your + local.conf): + + $ wic create mkefidisk -e core-image-minimal + Checking basic build environment... + Done. + + Creating image(s)... + + Info: The new image(s) can be found here: + /var/tmp/wic/build/mkefidisk-201309260027-sda.direct + + ... + + Here's an example that doesn't take the easy way out and manually + specifies each build artifact, along with a non-canned .wks file, + and also uses the -o option to have wic create the output + somewhere other than the default /var/tmp/wic: + + $ wic create ~/test.wks -o /home/trz/testwic --rootfs-dir + /home/trz/yocto/build/tmp/work/crownbay/core-image-minimal/1.0-r0/rootfs + --bootimg-dir /home/trz/yocto/build/tmp/sysroots/crownbay/usr/share + --kernel-dir /home/trz/yocto/build/tmp/sysroots/crownbay/usr/src/kernel + --native-sysroot /home/trz/yocto/build/tmp/sysroots/x86_64-linux + + Creating image(s)... + + Info: The new image(s) can be found here: + /home/trz/testwic/build/test-201309260032-sda.direct + + ... + + Finally, here's an example of the actual partition language + commands used to generate the mkefidisk image i.e. these are the + contents of the mkefidisk.wks OE kickstart file: + + # short-description: Create an EFI disk image + # long-description: Creates a partitioned EFI disk image that the user + # can directly dd to boot media. + + part /boot --source bootimg-efi --ondisk sda --fstype=efi --active + + part / --source rootfs --ondisk sda --fstype=ext3 --label platform + + part swap --ondisk sda --size 44 --label swap1 --fstype=swap + + bootloader --timeout=10 --append="rootwait console=ttyPCH0,115200" + + You can get a complete listing and description of all the + kickstart commands available for use in .wks files from 'wic help + kickstart'. +""" + +wic_kickstart_help = """ + +NAME + wic kickstart - wic kickstart reference + +DESCRIPTION + This section provides the definitive reference to the wic + kickstart language. It also provides documentation on the list of + --source plugins available for use from the 'part' command (see + the 'Platform-specific Plugins' section below). + + The current wic implementation supports only the basic kickstart + partitioning commands: partition (or part for short) and + bootloader. + + The following is a listing of the commands, their syntax, and + meanings. The commands are based on the Fedora kickstart + documentation but with modifications to reflect wic capabilities. + + http://fedoraproject.org/wiki/Anaconda/Kickstart#part_or_partition + http://fedoraproject.org/wiki/Anaconda/Kickstart#bootloader + + Commands + + * 'part' or 'partition' + + This command creates a partition on the system and uses the + following syntax: + + part + + The is where the partition will be mounted and + must take of one of the following forms: + + /: For example: /, /usr, or /home + + swap: The partition will be used as swap space. + + The following are supported 'part' options: + + --size: The minimum partition size in MBytes. Specify an + integer value such as 500. Do not append the number + with "MB". You do not need this option if you use + --source. + + --source: This option is a wic-specific option that names the + source of the data that will populate the + partition. The most common value for this option + is 'rootfs', but can be any value which maps to a + valid 'source plugin' (see 'wic help plugins'). + + If '--source rootfs' is used, it tells the wic + command to create a partition as large as needed + and to fill it with the contents of the root + filesystem pointed to by the '-r' wic command-line + option (or the equivalent rootfs derived from the + '-e' command-line option). The filesystem type + that will be used to create the partition is driven + by the value of the --fstype option specified for + the partition (see --fstype below). + + If --source ' is used, it tells the + wic command to create a partition as large as + needed and to fill with the contents of the + partition that will be generated by the specified + plugin name using the data pointed to by the '-r' + wic command-line option (or the equivalent rootfs + derived from the '-e' command-line option). + Exactly what those contents and filesystem type end + up being are dependent on the given plugin + implementation. + + --ondisk or --ondrive: Forces the partition to be created on + a particular disk. + + --fstype: Sets the file system type for the partition. These + apply to partitions created using '--source rootfs' (see + --source above). Valid values are: + + ext2 + ext3 + ext4 + btrfs + squashfs + swap + + --fsoptions: Specifies a free-form string of options to be + used when mounting the filesystem. This string + will be copied into the /etc/fstab file of the + installed system and should be enclosed in + quotes. If not specified, the default string is + "defaults". + + --label label: Specifies the label to give to the filesystem + to be made on the partition. If the given + label is already in use by another filesystem, + a new label is created for the partition. + + --active: Marks the partition as active. + + --align (in KBytes): This option is specific to wic and says + to start a partition on an x KBytes + boundary. + + * bootloader + + This command allows the user to specify various bootloader + options. The following are supported 'bootloader' options: + + --timeout: Specifies the number of seconds before the + bootloader times out and boots the default option. + + --append: Specifies kernel parameters. These will be added to + bootloader command-line - for example, the syslinux + APPEND or grub kernel command line. + + Note that bootloader functionality and boot partitions are + implemented by the various --source plugins that implement + bootloader functionality; the bootloader command essentially + provides a means of modifying bootloader configuration. +""" diff --git a/scripts/lib/scriptpath.py b/scripts/lib/scriptpath.py new file mode 100644 index 0000000000..d00317e18d --- /dev/null +++ b/scripts/lib/scriptpath.py @@ -0,0 +1,42 @@ +# Path utility functions for OE python scripts +# +# Copyright (C) 2012-2014 Intel Corporation +# Copyright (C) 2011 Mentor Graphics Corporation +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import os +import os.path + +def add_oe_lib_path(): + basepath = os.path.abspath(os.path.dirname(__file__) + '/../..') + newpath = basepath + '/meta/lib' + sys.path.insert(0, newpath) + +def add_bitbake_lib_path(): + basepath = os.path.abspath(os.path.dirname(__file__) + '/../..') + bitbakepath = None + if os.path.exists(basepath + '/bitbake/lib/bb'): + bitbakepath = basepath + '/bitbake' + else: + # look for bitbake/bin dir in PATH + for pth in os.environ['PATH'].split(':'): + if os.path.exists(os.path.join(pth, '../lib/bb')): + bitbakepath = os.path.abspath(os.path.join(pth, '..')) + break + + if bitbakepath: + sys.path.insert(0, bitbakepath + '/lib') + return bitbakepath diff --git a/scripts/lib/wic/3rdparty/pykickstart/__init__.py b/scripts/lib/wic/3rdparty/pykickstart/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/wic/3rdparty/pykickstart/base.py b/scripts/lib/wic/3rdparty/pykickstart/base.py new file mode 100644 index 0000000000..e6c8f56f9d --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/base.py @@ -0,0 +1,466 @@ +# +# Chris Lumens +# +# Copyright 2006, 2007, 2008 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +""" +Base classes for creating commands and syntax version object. + +This module exports several important base classes: + + BaseData - The base abstract class for all data objects. Data objects + are contained within a BaseHandler object. + + BaseHandler - The base abstract class from which versioned kickstart + handler are derived. Subclasses of BaseHandler hold + BaseData and KickstartCommand objects. + + DeprecatedCommand - An abstract subclass of KickstartCommand that should + be further subclassed by users of this module. When + a subclass is used, a warning message will be + printed. + + KickstartCommand - The base abstract class for all kickstart commands. + Command objects are contained within a BaseHandler + object. +""" +import gettext +gettext.textdomain("pykickstart") +_ = lambda x: gettext.ldgettext("pykickstart", x) + +import types +import warnings +from pykickstart.errors import * +from pykickstart.ko import * +from pykickstart.parser import Packages +from pykickstart.version import versionToString + +### +### COMMANDS +### +class KickstartCommand(KickstartObject): + """The base class for all kickstart commands. This is an abstract class.""" + removedKeywords = [] + removedAttrs = [] + + def __init__(self, writePriority=0, *args, **kwargs): + """Create a new KickstartCommand instance. This method must be + provided by all subclasses, but subclasses must call + KickstartCommand.__init__ first. Instance attributes: + + currentCmd -- The name of the command in the input file that + caused this handler to be run. + currentLine -- The current unprocessed line from the input file + that caused this handler to be run. + handler -- A reference to the BaseHandler subclass this + command is contained withing. This is needed to + allow referencing of Data objects. + lineno -- The current line number in the input file. + writePriority -- An integer specifying when this command should be + printed when iterating over all commands' __str__ + methods. The higher the number, the later this + command will be written. All commands with the + same priority will be written alphabetically. + """ + + # We don't want people using this class by itself. + if self.__class__ is KickstartCommand: + raise TypeError, "KickstartCommand is an abstract class." + + KickstartObject.__init__(self, *args, **kwargs) + + self.writePriority = writePriority + + # These will be set by the dispatcher. + self.currentCmd = "" + self.currentLine = "" + self.handler = None + self.lineno = 0 + + # If a subclass provides a removedKeywords list, remove all the + # members from the kwargs list before we start processing it. This + # ensures that subclasses don't continue to recognize arguments that + # were removed. + for arg in filter(kwargs.has_key, self.removedKeywords): + kwargs.pop(arg) + + def __call__(self, *args, **kwargs): + """Set multiple attributes on a subclass of KickstartCommand at once + via keyword arguments. Valid attributes are anything specified in + a subclass, but unknown attributes will be ignored. + """ + for (key, val) in kwargs.items(): + # Ignore setting attributes that were removed in a subclass, as + # if they were unknown attributes. + if key in self.removedAttrs: + continue + + if hasattr(self, key): + setattr(self, key, val) + + def __str__(self): + """Return a string formatted for output to a kickstart file. This + method must be provided by all subclasses. + """ + return KickstartObject.__str__(self) + + def parse(self, args): + """Parse the list of args and set data on the KickstartCommand object. + This method must be provided by all subclasses. + """ + raise TypeError, "parse() not implemented for KickstartCommand" + + def apply(self, instroot="/"): + """Write out the configuration related to the KickstartCommand object. + Subclasses which do not provide this method will not have their + configuration written out. + """ + return + + def dataList(self): + """For commands that can occur multiple times in a single kickstart + file (like network, part, etc.), return the list that we should + append more data objects to. + """ + return None + + def deleteRemovedAttrs(self): + """Remove all attributes from self that are given in the removedAttrs + list. This method should be called from __init__ in a subclass, + but only after the superclass's __init__ method has been called. + """ + for attr in filter(lambda k: hasattr(self, k), self.removedAttrs): + delattr(self, attr) + + # Set the contents of the opts object (an instance of optparse.Values + # returned by parse_args) as attributes on the KickstartCommand object. + # It's useful to call this from KickstartCommand subclasses after parsing + # the arguments. + def _setToSelf(self, optParser, opts): + self._setToObj(optParser, opts, self) + + # Sets the contents of the opts object (an instance of optparse.Values + # returned by parse_args) as attributes on the provided object obj. It's + # useful to call this from KickstartCommand subclasses that handle lists + # of objects (like partitions, network devices, etc.) and need to populate + # a Data object. + def _setToObj(self, optParser, opts, obj): + for key in filter (lambda k: getattr(opts, k) != None, optParser.keys()): + setattr(obj, key, getattr(opts, key)) + +class DeprecatedCommand(KickstartCommand): + """Specify that a command is deprecated and no longer has any function. + Any command that is deprecated should be subclassed from this class, + only specifying an __init__ method that calls the superclass's __init__. + This is an abstract class. + """ + def __init__(self, writePriority=None, *args, **kwargs): + # We don't want people using this class by itself. + if self.__class__ is KickstartCommand: + raise TypeError, "DeprecatedCommand is an abstract class." + + # Create a new DeprecatedCommand instance. + KickstartCommand.__init__(self, writePriority, *args, **kwargs) + + def __str__(self): + """Placeholder since DeprecatedCommands don't work anymore.""" + return "" + + def parse(self, args): + """Print a warning message if the command is seen in the input file.""" + mapping = {"lineno": self.lineno, "cmd": self.currentCmd} + warnings.warn(_("Ignoring deprecated command on line %(lineno)s: The %(cmd)s command has been deprecated and no longer has any effect. It may be removed from future releases, which will result in a fatal error from kickstart. Please modify your kickstart file to remove this command.") % mapping, DeprecationWarning) + + +### +### HANDLERS +### +class BaseHandler(KickstartObject): + """Each version of kickstart syntax is provided by a subclass of this + class. These subclasses are what users will interact with for parsing, + extracting data, and writing out kickstart files. This is an abstract + class. + + version -- The version this syntax handler supports. This is set by + a class attribute of a BaseHandler subclass and is used to + set up the command dict. It is for read-only use. + """ + version = None + + def __init__(self, mapping=None, dataMapping=None, commandUpdates=None, + dataUpdates=None, *args, **kwargs): + """Create a new BaseHandler instance. This method must be provided by + all subclasses, but subclasses must call BaseHandler.__init__ first. + + mapping -- A custom map from command strings to classes, + useful when creating your own handler with + special command objects. It is otherwise unused + and rarely needed. If you give this argument, + the mapping takes the place of the default one + and so must include all commands you want + recognized. + dataMapping -- This is the same as mapping, but for data + objects. All the same comments apply. + commandUpdates -- This is similar to mapping, but does not take + the place of the defaults entirely. Instead, + this mapping is applied after the defaults and + updates it with just the commands you want to + modify. + dataUpdates -- This is the same as commandUpdates, but for + data objects. + + + Instance attributes: + + commands -- A mapping from a string command to a KickstartCommand + subclass object that handles it. Multiple strings can + map to the same object, but only one instance of the + command object should ever exist. Most users should + never have to deal with this directly, as it is + manipulated internally and called through dispatcher. + currentLine -- The current unprocessed line from the input file + that caused this handler to be run. + packages -- An instance of pykickstart.parser.Packages which + describes the packages section of the input file. + platform -- A string describing the hardware platform, which is + needed only by system-config-kickstart. + scripts -- A list of pykickstart.parser.Script instances, which is + populated by KickstartParser.addScript and describes the + %pre/%post/%traceback script section of the input file. + """ + + # We don't want people using this class by itself. + if self.__class__ is BaseHandler: + raise TypeError, "BaseHandler is an abstract class." + + KickstartObject.__init__(self, *args, **kwargs) + + # This isn't really a good place for these, but it's better than + # everything else I can think of. + self.scripts = [] + self.packages = Packages() + self.platform = "" + + # These will be set by the dispatcher. + self.commands = {} + self.currentLine = 0 + + # A dict keyed by an integer priority number, with each value being a + # list of KickstartCommand subclasses. This dict is maintained by + # registerCommand and used in __str__. No one else should be touching + # it. + self._writeOrder = {} + + self._registerCommands(mapping, dataMapping, commandUpdates, dataUpdates) + + def __str__(self): + """Return a string formatted for output to a kickstart file.""" + retval = "" + + if self.platform != "": + retval += "#platform=%s\n" % self.platform + + retval += "#version=%s\n" % versionToString(self.version) + + lst = self._writeOrder.keys() + lst.sort() + + for prio in lst: + for obj in self._writeOrder[prio]: + retval += obj.__str__() + + for script in self.scripts: + retval += script.__str__() + + retval += self.packages.__str__() + + return retval + + def _insertSorted(self, lst, obj): + length = len(lst) + i = 0 + + while i < length: + # If the two classes have the same name, it's because we are + # overriding an existing class with one from a later kickstart + # version, so remove the old one in favor of the new one. + if obj.__class__.__name__ > lst[i].__class__.__name__: + i += 1 + elif obj.__class__.__name__ == lst[i].__class__.__name__: + lst[i] = obj + return + elif obj.__class__.__name__ < lst[i].__class__.__name__: + break + + if i >= length: + lst.append(obj) + else: + lst.insert(i, obj) + + def _setCommand(self, cmdObj): + # Add an attribute on this version object. We need this to provide a + # way for clients to access the command objects. We also need to strip + # off the version part from the front of the name. + if cmdObj.__class__.__name__.find("_") != -1: + name = unicode(cmdObj.__class__.__name__.split("_", 1)[1]) + else: + name = unicode(cmdObj.__class__.__name__).lower() + + setattr(self, name.lower(), cmdObj) + + # Also, add the object into the _writeOrder dict in the right place. + if cmdObj.writePriority is not None: + if self._writeOrder.has_key(cmdObj.writePriority): + self._insertSorted(self._writeOrder[cmdObj.writePriority], cmdObj) + else: + self._writeOrder[cmdObj.writePriority] = [cmdObj] + + def _registerCommands(self, mapping=None, dataMapping=None, commandUpdates=None, + dataUpdates=None): + if mapping == {} or mapping == None: + from pykickstart.handlers.control import commandMap + cMap = commandMap[self.version] + else: + cMap = mapping + + if dataMapping == {} or dataMapping == None: + from pykickstart.handlers.control import dataMap + dMap = dataMap[self.version] + else: + dMap = dataMapping + + if type(commandUpdates) == types.DictType: + cMap.update(commandUpdates) + + if type(dataUpdates) == types.DictType: + dMap.update(dataUpdates) + + for (cmdName, cmdClass) in cMap.iteritems(): + # First make sure we haven't instantiated this command handler + # already. If we have, we just need to make another mapping to + # it in self.commands. + cmdObj = None + + for (key, val) in self.commands.iteritems(): + if val.__class__.__name__ == cmdClass.__name__: + cmdObj = val + break + + # If we didn't find an instance in self.commands, create one now. + if cmdObj == None: + cmdObj = cmdClass() + self._setCommand(cmdObj) + + # Finally, add the mapping to the commands dict. + self.commands[cmdName] = cmdObj + self.commands[cmdName].handler = self + + # We also need to create attributes for the various data objects. + # No checks here because dMap is a bijection. At least, that's what + # the comment says. Hope no one screws that up. + for (dataName, dataClass) in dMap.iteritems(): + setattr(self, dataName, dataClass) + + def dispatcher(self, args, lineno): + """Call the appropriate KickstartCommand handler for the current line + in the kickstart file. A handler for the current command should + be registered, though a handler of None is not an error. Returns + the data object returned by KickstartCommand.parse. + + args -- A list of arguments to the current command + lineno -- The line number in the file, for error reporting + """ + cmd = args[0] + + if not self.commands.has_key(cmd): + raise KickstartParseError, formatErrorMsg(lineno, msg=_("Unknown command: %s" % cmd)) + elif self.commands[cmd] != None: + self.commands[cmd].currentCmd = cmd + self.commands[cmd].currentLine = self.currentLine + self.commands[cmd].lineno = lineno + + # The parser returns the data object that was modified. This could + # be a BaseData subclass that should be put into a list, or it + # could be the command handler object itself. + obj = self.commands[cmd].parse(args[1:]) + lst = self.commands[cmd].dataList() + if lst is not None: + lst.append(obj) + + return obj + + def maskAllExcept(self, lst): + """Set all entries in the commands dict to None, except the ones in + the lst. All other commands will not be processed. + """ + self._writeOrder = {} + + for (key, val) in self.commands.iteritems(): + if not key in lst: + self.commands[key] = None + + def hasCommand(self, cmd): + """Return true if there is a handler for the string cmd.""" + return hasattr(self, cmd) + + +### +### DATA +### +class BaseData(KickstartObject): + """The base class for all data objects. This is an abstract class.""" + removedKeywords = [] + removedAttrs = [] + + def __init__(self, *args, **kwargs): + """Create a new BaseData instance. + + lineno -- Line number in the ks-file where this object was defined + """ + + # We don't want people using this class by itself. + if self.__class__ is BaseData: + raise TypeError, "BaseData is an abstract class." + + KickstartObject.__init__(self, *args, **kwargs) + self.lineno = 0 + + def __str__(self): + """Return a string formatted for output to a kickstart file.""" + return "" + + def __call__(self, *args, **kwargs): + """Set multiple attributes on a subclass of BaseData at once via + keyword arguments. Valid attributes are anything specified in a + subclass, but unknown attributes will be ignored. + """ + for (key, val) in kwargs.items(): + # Ignore setting attributes that were removed in a subclass, as + # if they were unknown attributes. + if key in self.removedAttrs: + continue + + if hasattr(self, key): + setattr(self, key, val) + + def deleteRemovedAttrs(self): + """Remove all attributes from self that are given in the removedAttrs + list. This method should be called from __init__ in a subclass, + but only after the superclass's __init__ method has been called. + """ + for attr in filter(lambda k: hasattr(self, k), self.removedAttrs): + delattr(self, attr) diff --git a/scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py b/scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py new file mode 100644 index 0000000000..2d94550935 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py @@ -0,0 +1,20 @@ +# +# Chris Lumens +# +# Copyright 2009 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +import bootloader, partition diff --git a/scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py b/scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py new file mode 100644 index 0000000000..c2b552f689 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py @@ -0,0 +1,216 @@ +# +# Chris Lumens +# +# Copyright 2007 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +from pykickstart.base import * +from pykickstart.options import * + +class FC3_Bootloader(KickstartCommand): + removedKeywords = KickstartCommand.removedKeywords + removedAttrs = KickstartCommand.removedAttrs + + def __init__(self, writePriority=10, *args, **kwargs): + KickstartCommand.__init__(self, writePriority, *args, **kwargs) + self.op = self._getParser() + + self.driveorder = kwargs.get("driveorder", []) + self.appendLine = kwargs.get("appendLine", "") + self.forceLBA = kwargs.get("forceLBA", False) + self.linear = kwargs.get("linear", True) + self.location = kwargs.get("location", "") + self.md5pass = kwargs.get("md5pass", "") + self.password = kwargs.get("password", "") + self.upgrade = kwargs.get("upgrade", False) + self.useLilo = kwargs.get("useLilo", False) + + self.deleteRemovedAttrs() + + def _getArgsAsStr(self): + retval = "" + + if self.appendLine != "": + retval += " --append=\"%s\"" % self.appendLine + if self.linear: + retval += " --linear" + if self.location: + retval += " --location=%s" % self.location + if hasattr(self, "forceLBA") and self.forceLBA: + retval += " --lba32" + if self.password != "": + retval += " --password=\"%s\"" % self.password + if self.md5pass != "": + retval += " --md5pass=\"%s\"" % self.md5pass + if self.upgrade: + retval += " --upgrade" + if self.useLilo: + retval += " --useLilo" + if len(self.driveorder) > 0: + retval += " --driveorder=\"%s\"" % ",".join(self.driveorder) + + return retval + + def __str__(self): + retval = KickstartCommand.__str__(self) + + if self.location != "": + retval += "# System bootloader configuration\nbootloader" + retval += self._getArgsAsStr() + "\n" + + return retval + + def _getParser(self): + def driveorder_cb (option, opt_str, value, parser): + for d in value.split(','): + parser.values.ensure_value(option.dest, []).append(d) + + op = KSOptionParser() + op.add_option("--append", dest="appendLine") + op.add_option("--linear", dest="linear", action="store_true", + default=True) + op.add_option("--nolinear", dest="linear", action="store_false") + op.add_option("--location", dest="location", type="choice", + default="mbr", + choices=["mbr", "partition", "none", "boot"]) + op.add_option("--lba32", dest="forceLBA", action="store_true", + default=False) + op.add_option("--password", dest="password", default="") + op.add_option("--md5pass", dest="md5pass", default="") + op.add_option("--upgrade", dest="upgrade", action="store_true", + default=False) + op.add_option("--useLilo", dest="useLilo", action="store_true", + default=False) + op.add_option("--driveorder", dest="driveorder", action="callback", + callback=driveorder_cb, nargs=1, type="string") + return op + + def parse(self, args): + (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) + self._setToSelf(self.op, opts) + + if self.currentCmd == "lilo": + self.useLilo = True + + return self + +class FC4_Bootloader(FC3_Bootloader): + removedKeywords = FC3_Bootloader.removedKeywords + ["linear", "useLilo"] + removedAttrs = FC3_Bootloader.removedAttrs + ["linear", "useLilo"] + + def __init__(self, writePriority=10, *args, **kwargs): + FC3_Bootloader.__init__(self, writePriority, *args, **kwargs) + + def _getArgsAsStr(self): + retval = "" + if self.appendLine != "": + retval += " --append=\"%s\"" % self.appendLine + if self.location: + retval += " --location=%s" % self.location + if hasattr(self, "forceLBA") and self.forceLBA: + retval += " --lba32" + if self.password != "": + retval += " --password=\"%s\"" % self.password + if self.md5pass != "": + retval += " --md5pass=\"%s\"" % self.md5pass + if self.upgrade: + retval += " --upgrade" + if len(self.driveorder) > 0: + retval += " --driveorder=\"%s\"" % ",".join(self.driveorder) + return retval + + def _getParser(self): + op = FC3_Bootloader._getParser(self) + op.remove_option("--linear") + op.remove_option("--nolinear") + op.remove_option("--useLilo") + return op + + def parse(self, args): + (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) + self._setToSelf(self.op, opts) + return self + +class F8_Bootloader(FC4_Bootloader): + removedKeywords = FC4_Bootloader.removedKeywords + removedAttrs = FC4_Bootloader.removedAttrs + + def __init__(self, writePriority=10, *args, **kwargs): + FC4_Bootloader.__init__(self, writePriority, *args, **kwargs) + + self.timeout = kwargs.get("timeout", None) + self.default = kwargs.get("default", "") + + def _getArgsAsStr(self): + ret = FC4_Bootloader._getArgsAsStr(self) + + if self.timeout is not None: + ret += " --timeout=%d" %(self.timeout,) + if self.default: + ret += " --default=%s" %(self.default,) + + return ret + + def _getParser(self): + op = FC4_Bootloader._getParser(self) + op.add_option("--timeout", dest="timeout", type="int") + op.add_option("--default", dest="default") + return op + +class F12_Bootloader(F8_Bootloader): + removedKeywords = F8_Bootloader.removedKeywords + removedAttrs = F8_Bootloader.removedAttrs + + def _getParser(self): + op = F8_Bootloader._getParser(self) + op.add_option("--lba32", dest="forceLBA", deprecated=1, action="store_true") + return op + +class F14_Bootloader(F12_Bootloader): + removedKeywords = F12_Bootloader.removedKeywords + ["forceLBA"] + removedAttrs = F12_Bootloader.removedKeywords + ["forceLBA"] + + def _getParser(self): + op = F12_Bootloader._getParser(self) + op.remove_option("--lba32") + return op + +class F15_Bootloader(F14_Bootloader): + removedKeywords = F14_Bootloader.removedKeywords + removedAttrs = F14_Bootloader.removedAttrs + + def __init__(self, writePriority=10, *args, **kwargs): + F14_Bootloader.__init__(self, writePriority, *args, **kwargs) + + self.isCrypted = kwargs.get("isCrypted", False) + + def _getArgsAsStr(self): + ret = F14_Bootloader._getArgsAsStr(self) + + if self.isCrypted: + ret += " --iscrypted" + + return ret + + def _getParser(self): + def password_cb(option, opt_str, value, parser): + parser.values.isCrypted = True + parser.values.password = value + + op = F14_Bootloader._getParser(self) + op.add_option("--iscrypted", dest="isCrypted", action="store_true", default=False) + op.add_option("--md5pass", action="callback", callback=password_cb, nargs=1, type="string") + return op diff --git a/scripts/lib/wic/3rdparty/pykickstart/commands/partition.py b/scripts/lib/wic/3rdparty/pykickstart/commands/partition.py new file mode 100644 index 0000000000..56b91aa9d9 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/commands/partition.py @@ -0,0 +1,314 @@ +# +# Chris Lumens +# +# Copyright 2005, 2006, 2007, 2008 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +from pykickstart.base import * +from pykickstart.errors import * +from pykickstart.options import * + +import gettext +import warnings +_ = lambda x: gettext.ldgettext("pykickstart", x) + +class FC3_PartData(BaseData): + removedKeywords = BaseData.removedKeywords + removedAttrs = BaseData.removedAttrs + + def __init__(self, *args, **kwargs): + BaseData.__init__(self, *args, **kwargs) + self.active = kwargs.get("active", False) + self.primOnly = kwargs.get("primOnly", False) + self.end = kwargs.get("end", 0) + self.fstype = kwargs.get("fstype", "") + self.grow = kwargs.get("grow", False) + self.maxSizeMB = kwargs.get("maxSizeMB", 0) + self.format = kwargs.get("format", True) + self.onbiosdisk = kwargs.get("onbiosdisk", "") + self.disk = kwargs.get("disk", "") + self.onPart = kwargs.get("onPart", "") + self.recommended = kwargs.get("recommended", False) + self.size = kwargs.get("size", None) + self.start = kwargs.get("start", 0) + self.mountpoint = kwargs.get("mountpoint", "") + + def __eq__(self, y): + if self.mountpoint: + return self.mountpoint == y.mountpoint + else: + return False + + def _getArgsAsStr(self): + retval = "" + + if self.active: + retval += " --active" + if self.primOnly: + retval += " --asprimary" + if hasattr(self, "end") and self.end != 0: + retval += " --end=%s" % self.end + if self.fstype != "": + retval += " --fstype=\"%s\"" % self.fstype + if self.grow: + retval += " --grow" + if self.maxSizeMB > 0: + retval += " --maxsize=%d" % self.maxSizeMB + if not self.format: + retval += " --noformat" + if self.onbiosdisk != "": + retval += " --onbiosdisk=%s" % self.onbiosdisk + if self.disk != "": + retval += " --ondisk=%s" % self.disk + if self.onPart != "": + retval += " --onpart=%s" % self.onPart + if self.recommended: + retval += " --recommended" + if self.size and self.size != 0: + retval += " --size=%s" % self.size + if hasattr(self, "start") and self.start != 0: + retval += " --start=%s" % self.start + + return retval + + def __str__(self): + retval = BaseData.__str__(self) + if self.mountpoint: + mountpoint_str = "%s" % self.mountpoint + else: + mountpoint_str = "(No mount point)" + retval += "part %s%s\n" % (mountpoint_str, self._getArgsAsStr()) + return retval + +class FC4_PartData(FC3_PartData): + removedKeywords = FC3_PartData.removedKeywords + removedAttrs = FC3_PartData.removedAttrs + + def __init__(self, *args, **kwargs): + FC3_PartData.__init__(self, *args, **kwargs) + self.bytesPerInode = kwargs.get("bytesPerInode", 4096) + self.fsopts = kwargs.get("fsopts", "") + self.label = kwargs.get("label", "") + + def _getArgsAsStr(self): + retval = FC3_PartData._getArgsAsStr(self) + + if hasattr(self, "bytesPerInode") and self.bytesPerInode != 0: + retval += " --bytes-per-inode=%d" % self.bytesPerInode + if self.fsopts != "": + retval += " --fsoptions=\"%s\"" % self.fsopts + if self.label != "": + retval += " --label=%s" % self.label + + return retval + +class F9_PartData(FC4_PartData): + removedKeywords = FC4_PartData.removedKeywords + ["bytesPerInode"] + removedAttrs = FC4_PartData.removedAttrs + ["bytesPerInode"] + + def __init__(self, *args, **kwargs): + FC4_PartData.__init__(self, *args, **kwargs) + self.deleteRemovedAttrs() + + self.fsopts = kwargs.get("fsopts", "") + self.label = kwargs.get("label", "") + self.fsprofile = kwargs.get("fsprofile", "") + self.encrypted = kwargs.get("encrypted", False) + self.passphrase = kwargs.get("passphrase", "") + + def _getArgsAsStr(self): + retval = FC4_PartData._getArgsAsStr(self) + + if self.fsprofile != "": + retval += " --fsprofile=\"%s\"" % self.fsprofile + if self.encrypted: + retval += " --encrypted" + + if self.passphrase != "": + retval += " --passphrase=\"%s\"" % self.passphrase + + return retval + +class F11_PartData(F9_PartData): + removedKeywords = F9_PartData.removedKeywords + ["start", "end"] + removedAttrs = F9_PartData.removedAttrs + ["start", "end"] + +class F12_PartData(F11_PartData): + removedKeywords = F11_PartData.removedKeywords + removedAttrs = F11_PartData.removedAttrs + + def __init__(self, *args, **kwargs): + F11_PartData.__init__(self, *args, **kwargs) + + self.escrowcert = kwargs.get("escrowcert", "") + self.backuppassphrase = kwargs.get("backuppassphrase", False) + + def _getArgsAsStr(self): + retval = F11_PartData._getArgsAsStr(self) + + if self.encrypted and self.escrowcert != "": + retval += " --escrowcert=\"%s\"" % self.escrowcert + + if self.backuppassphrase: + retval += " --backuppassphrase" + + return retval + +F14_PartData = F12_PartData + +class FC3_Partition(KickstartCommand): + removedKeywords = KickstartCommand.removedKeywords + removedAttrs = KickstartCommand.removedAttrs + + def __init__(self, writePriority=130, *args, **kwargs): + KickstartCommand.__init__(self, writePriority, *args, **kwargs) + self.op = self._getParser() + + self.partitions = kwargs.get("partitions", []) + + def __str__(self): + retval = "" + + for part in self.partitions: + retval += part.__str__() + + if retval != "": + return "# Disk partitioning information\n" + retval + else: + return "" + + def _getParser(self): + def part_cb (option, opt_str, value, parser): + if value.startswith("/dev/"): + parser.values.ensure_value(option.dest, value[5:]) + else: + parser.values.ensure_value(option.dest, value) + + op = KSOptionParser() + op.add_option("--active", dest="active", action="store_true", + default=False) + op.add_option("--asprimary", dest="primOnly", action="store_true", + default=False) + op.add_option("--end", dest="end", action="store", type="int", + nargs=1) + op.add_option("--fstype", "--type", dest="fstype") + op.add_option("--grow", dest="grow", action="store_true", default=False) + op.add_option("--maxsize", dest="maxSizeMB", action="store", type="int", + nargs=1) + op.add_option("--noformat", dest="format", action="store_false", + default=True) + op.add_option("--onbiosdisk", dest="onbiosdisk") + op.add_option("--ondisk", "--ondrive", dest="disk") + op.add_option("--onpart", "--usepart", dest="onPart", action="callback", + callback=part_cb, nargs=1, type="string") + op.add_option("--recommended", dest="recommended", action="store_true", + default=False) + op.add_option("--size", dest="size", action="store", type="int", + nargs=1) + op.add_option("--start", dest="start", action="store", type="int", + nargs=1) + return op + + def parse(self, args): + (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) + + pd = self.handler.PartData() + self._setToObj(self.op, opts, pd) + pd.lineno = self.lineno + if extra: + pd.mountpoint = extra[0] + if pd in self.dataList(): + warnings.warn(_("A partition with the mountpoint %s has already been defined.") % pd.mountpoint) + else: + pd.mountpoint = None + + return pd + + def dataList(self): + return self.partitions + +class FC4_Partition(FC3_Partition): + removedKeywords = FC3_Partition.removedKeywords + removedAttrs = FC3_Partition.removedAttrs + + def __init__(self, writePriority=130, *args, **kwargs): + FC3_Partition.__init__(self, writePriority, *args, **kwargs) + + def part_cb (option, opt_str, value, parser): + if value.startswith("/dev/"): + parser.values.ensure_value(option.dest, value[5:]) + else: + parser.values.ensure_value(option.dest, value) + + def _getParser(self): + op = FC3_Partition._getParser(self) + op.add_option("--bytes-per-inode", dest="bytesPerInode", action="store", + type="int", nargs=1) + op.add_option("--fsoptions", dest="fsopts") + op.add_option("--label", dest="label") + return op + +class F9_Partition(FC4_Partition): + removedKeywords = FC4_Partition.removedKeywords + removedAttrs = FC4_Partition.removedAttrs + + def __init__(self, writePriority=130, *args, **kwargs): + FC4_Partition.__init__(self, writePriority, *args, **kwargs) + + def part_cb (option, opt_str, value, parser): + if value.startswith("/dev/"): + parser.values.ensure_value(option.dest, value[5:]) + else: + parser.values.ensure_value(option.dest, value) + + def _getParser(self): + op = FC4_Partition._getParser(self) + op.add_option("--bytes-per-inode", deprecated=1) + op.add_option("--fsprofile") + op.add_option("--encrypted", action="store_true", default=False) + op.add_option("--passphrase") + return op + +class F11_Partition(F9_Partition): + removedKeywords = F9_Partition.removedKeywords + removedAttrs = F9_Partition.removedAttrs + + def _getParser(self): + op = F9_Partition._getParser(self) + op.add_option("--start", deprecated=1) + op.add_option("--end", deprecated=1) + return op + +class F12_Partition(F11_Partition): + removedKeywords = F11_Partition.removedKeywords + removedAttrs = F11_Partition.removedAttrs + + def _getParser(self): + op = F11_Partition._getParser(self) + op.add_option("--escrowcert") + op.add_option("--backuppassphrase", action="store_true", default=False) + return op + +class F14_Partition(F12_Partition): + removedKeywords = F12_Partition.removedKeywords + removedAttrs = F12_Partition.removedAttrs + + def _getParser(self): + op = F12_Partition._getParser(self) + op.remove_option("--bytes-per-inode") + op.remove_option("--start") + op.remove_option("--end") + return op diff --git a/scripts/lib/wic/3rdparty/pykickstart/constants.py b/scripts/lib/wic/3rdparty/pykickstart/constants.py new file mode 100644 index 0000000000..5e12fc80ec --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/constants.py @@ -0,0 +1,57 @@ +# +# Chris Lumens +# +# Copyright 2005-2007 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +CLEARPART_TYPE_LINUX = 0 +CLEARPART_TYPE_ALL = 1 +CLEARPART_TYPE_NONE = 2 + +DISPLAY_MODE_CMDLINE = 0 +DISPLAY_MODE_GRAPHICAL = 1 +DISPLAY_MODE_TEXT = 2 + +FIRSTBOOT_DEFAULT = 0 +FIRSTBOOT_SKIP = 1 +FIRSTBOOT_RECONFIG = 2 + +KS_MISSING_PROMPT = 0 +KS_MISSING_IGNORE = 1 + +SELINUX_DISABLED = 0 +SELINUX_ENFORCING = 1 +SELINUX_PERMISSIVE = 2 + +KS_SCRIPT_PRE = 0 +KS_SCRIPT_POST = 1 +KS_SCRIPT_TRACEBACK = 2 + +KS_WAIT = 0 +KS_REBOOT = 1 +KS_SHUTDOWN = 2 + +KS_INSTKEY_SKIP = -99 + +BOOTPROTO_DHCP = "dhcp" +BOOTPROTO_BOOTP = "bootp" +BOOTPROTO_STATIC = "static" +BOOTPROTO_QUERY = "query" +BOOTPROTO_IBFT = "ibft" + +GROUP_REQUIRED = 0 +GROUP_DEFAULT = 1 +GROUP_ALL = 2 diff --git a/scripts/lib/wic/3rdparty/pykickstart/errors.py b/scripts/lib/wic/3rdparty/pykickstart/errors.py new file mode 100644 index 0000000000..a234d99d43 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/errors.py @@ -0,0 +1,103 @@ +# +# errors.py: Kickstart error handling. +# +# Chris Lumens +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +""" +Error handling classes and functions. + +This module exports a single function: + + formatErrorMsg - Properly formats an error message. + +It also exports several exception classes: + + KickstartError - A generic exception class. + + KickstartParseError - An exception for errors relating to parsing. + + KickstartValueError - An exception for errors relating to option + processing. + + KickstartVersionError - An exception for errors relating to unsupported + syntax versions. +""" +import gettext +_ = lambda x: gettext.ldgettext("pykickstart", x) + +def formatErrorMsg(lineno, msg=""): + """Properly format the error message msg for inclusion in an exception.""" + if msg != "": + mapping = {"lineno": lineno, "msg": msg} + return _("The following problem occurred on line %(lineno)s of the kickstart file:\n\n%(msg)s\n") % mapping + else: + return _("There was a problem reading from line %s of the kickstart file") % lineno + +class KickstartError(Exception): + """A generic exception class for unspecific error conditions.""" + def __init__(self, val = ""): + """Create a new KickstartError exception instance with the descriptive + message val. val should be the return value of formatErrorMsg. + """ + Exception.__init__(self) + self.value = val + + def __str__ (self): + return self.value + +class KickstartParseError(KickstartError): + """An exception class for errors when processing the input file, such as + unknown options, commands, or sections. + """ + def __init__(self, msg): + """Create a new KickstartParseError exception instance with the + descriptive message val. val should be the return value of + formatErrorMsg. + """ + KickstartError.__init__(self, msg) + + def __str__(self): + return self.value + +class KickstartValueError(KickstartError): + """An exception class for errors when processing arguments to commands, + such as too many arguments, too few arguments, or missing required + arguments. + """ + def __init__(self, msg): + """Create a new KickstartValueError exception instance with the + descriptive message val. val should be the return value of + formatErrorMsg. + """ + KickstartError.__init__(self, msg) + + def __str__ (self): + return self.value + +class KickstartVersionError(KickstartError): + """An exception class for errors related to using an incorrect version of + kickstart syntax. + """ + def __init__(self, msg): + """Create a new KickstartVersionError exception instance with the + descriptive message val. val should be the return value of + formatErrorMsg. + """ + KickstartError.__init__(self, msg) + + def __str__ (self): + return self.value diff --git a/scripts/lib/wic/3rdparty/pykickstart/handlers/__init__.py b/scripts/lib/wic/3rdparty/pykickstart/handlers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/wic/3rdparty/pykickstart/handlers/control.py b/scripts/lib/wic/3rdparty/pykickstart/handlers/control.py new file mode 100644 index 0000000000..8dc80d1ebe --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/handlers/control.py @@ -0,0 +1,46 @@ +# +# Chris Lumens +# +# Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +from pykickstart.version import * +from pykickstart.commands import * + +# This map is keyed on kickstart syntax version as provided by +# pykickstart.version. Within each sub-dict is a mapping from command name +# to the class that handles it. This is an onto mapping - that is, multiple +# command names can map to the same class. However, the Handler will ensure +# that only one instance of each class ever exists. +commandMap = { + # based on f15 + F16: { + "bootloader": bootloader.F15_Bootloader, + "part": partition.F14_Partition, + "partition": partition.F14_Partition, + }, +} + +# This map is keyed on kickstart syntax version as provided by +# pykickstart.version. Within each sub-dict is a mapping from a data object +# name to the class that provides it. This is a bijective mapping - that is, +# each name maps to exactly one data class and all data classes have a name. +# More than one instance of each class is allowed to exist, however. +dataMap = { + F16: { + "PartData": partition.F14_PartData, + }, +} diff --git a/scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py b/scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py new file mode 100644 index 0000000000..3c52f8d754 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py @@ -0,0 +1,24 @@ +# +# Chris Lumens +# +# Copyright 2011 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +from pykickstart.base import * +from pykickstart.version import * + +class F16Handler(BaseHandler): + version = F16 diff --git a/scripts/lib/wic/3rdparty/pykickstart/ko.py b/scripts/lib/wic/3rdparty/pykickstart/ko.py new file mode 100644 index 0000000000..1350d19c70 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/ko.py @@ -0,0 +1,37 @@ +# +# Chris Lumens +# +# Copyright 2009 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +""" +Base classes for internal pykickstart use. + +The module exports the following important classes: + + KickstartObject - The base class for all classes in pykickstart +""" + +class KickstartObject(object): + """The base class for all other classes in pykickstart.""" + def __init__(self, *args, **kwargs): + """Create a new KickstartObject instance. All other classes in + pykickstart should be derived from this one. Instance attributes: + """ + pass + + def __str__(self): + return "" diff --git a/scripts/lib/wic/3rdparty/pykickstart/options.py b/scripts/lib/wic/3rdparty/pykickstart/options.py new file mode 100644 index 0000000000..341c5d7298 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/options.py @@ -0,0 +1,204 @@ +# +# Chris Lumens +# +# Copyright 2005, 2006, 2007 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +""" +Specialized option handling. + +This module exports two classes: + + KSOptionParser - A specialized subclass of OptionParser to be used + in BaseHandler subclasses. + + KSOption - A specialized subclass of Option. +""" +import warnings +from copy import copy +from optparse import * + +from constants import * +from errors import * +from version import * + +import gettext +_ = lambda x: gettext.ldgettext("pykickstart", x) + +class KSOptionParser(OptionParser): + """A specialized subclass of optparse.OptionParser to handle extra option + attribute checking, work error reporting into the KickstartParseError + framework, and to turn off the default help. + """ + def exit(self, status=0, msg=None): + pass + + def error(self, msg): + if self.lineno != None: + raise KickstartParseError, formatErrorMsg(self.lineno, msg=msg) + else: + raise KickstartParseError, msg + + def keys(self): + retval = [] + + for opt in self.option_list: + if opt not in retval: + retval.append(opt.dest) + + return retval + + def _init_parsing_state (self): + OptionParser._init_parsing_state(self) + self.option_seen = {} + + def check_values (self, values, args): + def seen(self, option): + return self.option_seen.has_key(option) + + def usedTooNew(self, option): + return option.introduced and option.introduced > self.version + + def usedDeprecated(self, option): + return option.deprecated + + def usedRemoved(self, option): + return option.removed and option.removed <= self.version + + for option in filter(lambda o: isinstance(o, Option), self.option_list): + if option.required and not seen(self, option): + raise KickstartValueError, formatErrorMsg(self.lineno, _("Option %s is required") % option) + elif seen(self, option) and usedTooNew(self, option): + mapping = {"option": option, "intro": versionToString(option.introduced), + "version": versionToString(self.version)} + self.error(_("The %(option)s option was introduced in version %(intro)s, but you are using kickstart syntax version %(version)s.") % mapping) + elif seen(self, option) and usedRemoved(self, option): + mapping = {"option": option, "removed": versionToString(option.removed), + "version": versionToString(self.version)} + + if option.removed == self.version: + self.error(_("The %(option)s option is no longer supported.") % mapping) + else: + self.error(_("The %(option)s option was removed in version %(removed)s, but you are using kickstart syntax version %(version)s.") % mapping) + elif seen(self, option) and usedDeprecated(self, option): + mapping = {"lineno": self.lineno, "option": option} + warnings.warn(_("Ignoring deprecated option on line %(lineno)s: The %(option)s option has been deprecated and no longer has any effect. It may be removed from future releases, which will result in a fatal error from kickstart. Please modify your kickstart file to remove this option.") % mapping, DeprecationWarning) + + return (values, args) + + def parse_args(self, *args, **kwargs): + if kwargs.has_key("lineno"): + self.lineno = kwargs.pop("lineno") + + return OptionParser.parse_args(self, **kwargs) + + def __init__(self, mapping=None, version=None): + """Create a new KSOptionParser instance. Each KickstartCommand + subclass should create one instance of KSOptionParser, providing + at least the lineno attribute. mapping and version are not required. + Instance attributes: + + mapping -- A mapping from option strings to different values. + version -- The version of the kickstart syntax we are checking + against. + """ + OptionParser.__init__(self, option_class=KSOption, + add_help_option=False, + conflict_handler="resolve") + if mapping is None: + self.map = {} + else: + self.map = mapping + + self.lineno = None + self.option_seen = {} + self.version = version + +def _check_ksboolean(option, opt, value): + if value.lower() in ("on", "yes", "true", "1"): + return True + elif value.lower() in ("off", "no", "false", "0"): + return False + else: + mapping = {"opt": opt, "value": value} + raise OptionValueError(_("Option %(opt)s: invalid boolean value: %(value)r") % mapping) + +def _check_string(option, opt, value): + if len(value) > 2 and value.startswith("--"): + mapping = {"opt": opt, "value": value} + raise OptionValueError(_("Option %(opt)s: invalid string value: %(value)r") % mapping) + else: + return value + +# Creates a new Option class that supports several new attributes: +# - required: any option with this attribute must be supplied or an exception +# is thrown +# - introduced: the kickstart syntax version that this option first appeared +# in - an exception will be raised if the option is used and +# the specified syntax version is less than the value of this +# attribute +# - deprecated: the kickstart syntax version that this option was deprecated +# in - a DeprecationWarning will be thrown if the option is +# used and the specified syntax version is greater than the +# value of this attribute +# - removed: the kickstart syntax version that this option was removed in - an +# exception will be raised if the option is used and the specified +# syntax version is greated than the value of this attribute +# Also creates a new type: +# - ksboolean: support various kinds of boolean values on an option +# And two new actions: +# - map : allows you to define an opt -> val mapping such that dest gets val +# when opt is seen +# - map_extend: allows you to define an opt -> [val1, ... valn] mapping such +# that dest gets a list of vals built up when opt is seen +class KSOption (Option): + ATTRS = Option.ATTRS + ['introduced', 'deprecated', 'removed', 'required'] + ACTIONS = Option.ACTIONS + ("map", "map_extend",) + STORE_ACTIONS = Option.STORE_ACTIONS + ("map", "map_extend",) + + TYPES = Option.TYPES + ("ksboolean", "string") + TYPE_CHECKER = copy(Option.TYPE_CHECKER) + TYPE_CHECKER["ksboolean"] = _check_ksboolean + TYPE_CHECKER["string"] = _check_string + + def _check_required(self): + if self.required and not self.takes_value(): + raise OptionError(_("Required flag set for option that doesn't take a value"), self) + + # Make sure _check_required() is called from the constructor! + CHECK_METHODS = Option.CHECK_METHODS + [_check_required] + + def process (self, opt, value, values, parser): + Option.process(self, opt, value, values, parser) + parser.option_seen[self] = 1 + + # Override default take_action method to handle our custom actions. + def take_action(self, action, dest, opt, value, values, parser): + if action == "map": + values.ensure_value(dest, parser.map[opt.lstrip('-')]) + elif action == "map_extend": + values.ensure_value(dest, []).extend(parser.map[opt.lstrip('-')]) + else: + Option.take_action(self, action, dest, opt, value, values, parser) + + def takes_value(self): + # Deprecated options don't take a value. + return Option.takes_value(self) and not self.deprecated + + def __init__(self, *args, **kwargs): + self.deprecated = False + self.required = False + Option.__init__(self, *args, **kwargs) diff --git a/scripts/lib/wic/3rdparty/pykickstart/parser.py b/scripts/lib/wic/3rdparty/pykickstart/parser.py new file mode 100644 index 0000000000..9c9674bf73 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/parser.py @@ -0,0 +1,619 @@ +# +# parser.py: Kickstart file parser. +# +# Chris Lumens +# +# Copyright 2005, 2006, 2007, 2008, 2011 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +""" +Main kickstart file processing module. + +This module exports several important classes: + + Script - Representation of a single %pre, %post, or %traceback script. + + Packages - Representation of the %packages section. + + KickstartParser - The kickstart file parser state machine. +""" + +from collections import Iterator +import os +import shlex +import sys +import tempfile +from copy import copy +from optparse import * + +import constants +from errors import KickstartError, KickstartParseError, KickstartValueError, formatErrorMsg +from ko import KickstartObject +from sections import * +import version + +import gettext +_ = lambda x: gettext.ldgettext("pykickstart", x) + +STATE_END = "end" +STATE_COMMANDS = "commands" + +ver = version.DEVEL + + +class PutBackIterator(Iterator): + def __init__(self, iterable): + self._iterable = iter(iterable) + self._buf = None + + def __iter__(self): + return self + + def put(self, s): + self._buf = s + + def next(self): + if self._buf: + retval = self._buf + self._buf = None + return retval + else: + return self._iterable.next() + +### +### SCRIPT HANDLING +### +class Script(KickstartObject): + """A class representing a single kickstart script. If functionality beyond + just a data representation is needed (for example, a run method in + anaconda), Script may be subclassed. Although a run method is not + provided, most of the attributes of Script have to do with running the + script. Instances of Script are held in a list by the Version object. + """ + def __init__(self, script, *args , **kwargs): + """Create a new Script instance. Instance attributes: + + errorOnFail -- If execution of the script fails, should anaconda + stop, display an error, and then reboot without + running any other scripts? + inChroot -- Does the script execute in anaconda's chroot + environment or not? + interp -- The program that should be used to interpret this + script. + lineno -- The line number this script starts on. + logfile -- Where all messages from the script should be logged. + script -- A string containing all the lines of the script. + type -- The type of the script, which can be KS_SCRIPT_* from + pykickstart.constants. + """ + KickstartObject.__init__(self, *args, **kwargs) + self.script = "".join(script) + + self.interp = kwargs.get("interp", "/bin/sh") + self.inChroot = kwargs.get("inChroot", False) + self.lineno = kwargs.get("lineno", None) + self.logfile = kwargs.get("logfile", None) + self.errorOnFail = kwargs.get("errorOnFail", False) + self.type = kwargs.get("type", constants.KS_SCRIPT_PRE) + + def __str__(self): + """Return a string formatted for output to a kickstart file.""" + retval = "" + + if self.type == constants.KS_SCRIPT_PRE: + retval += '\n%pre' + elif self.type == constants.KS_SCRIPT_POST: + retval += '\n%post' + elif self.type == constants.KS_SCRIPT_TRACEBACK: + retval += '\n%traceback' + + if self.interp != "/bin/sh" and self.interp != "": + retval += " --interpreter=%s" % self.interp + if self.type == constants.KS_SCRIPT_POST and not self.inChroot: + retval += " --nochroot" + if self.logfile != None: + retval += " --logfile %s" % self.logfile + if self.errorOnFail: + retval += " --erroronfail" + + if self.script.endswith("\n"): + if ver >= version.F8: + return retval + "\n%s%%end\n" % self.script + else: + return retval + "\n%s\n" % self.script + else: + if ver >= version.F8: + return retval + "\n%s\n%%end\n" % self.script + else: + return retval + "\n%s\n" % self.script + + +## +## PACKAGE HANDLING +## +class Group: + """A class representing a single group in the %packages section.""" + def __init__(self, name="", include=constants.GROUP_DEFAULT): + """Create a new Group instance. Instance attributes: + + name -- The group's identifier + include -- The level of how much of the group should be included. + Values can be GROUP_* from pykickstart.constants. + """ + self.name = name + self.include = include + + def __str__(self): + """Return a string formatted for output to a kickstart file.""" + if self.include == constants.GROUP_REQUIRED: + return "@%s --nodefaults" % self.name + elif self.include == constants.GROUP_ALL: + return "@%s --optional" % self.name + else: + return "@%s" % self.name + + def __cmp__(self, other): + if self.name < other.name: + return -1 + elif self.name > other.name: + return 1 + return 0 + +class Packages(KickstartObject): + """A class representing the %packages section of the kickstart file.""" + def __init__(self, *args, **kwargs): + """Create a new Packages instance. Instance attributes: + + addBase -- Should the Base group be installed even if it is + not specified? + default -- Should the default package set be selected? + excludedList -- A list of all the packages marked for exclusion in + the %packages section, without the leading minus + symbol. + excludeDocs -- Should documentation in each package be excluded? + groupList -- A list of Group objects representing all the groups + specified in the %packages section. Names will be + stripped of the leading @ symbol. + excludedGroupList -- A list of Group objects representing all the + groups specified for removal in the %packages + section. Names will be stripped of the leading + -@ symbols. + handleMissing -- If unknown packages are specified in the %packages + section, should it be ignored or not? Values can + be KS_MISSING_* from pykickstart.constants. + packageList -- A list of all the packages specified in the + %packages section. + instLangs -- A list of languages to install. + """ + KickstartObject.__init__(self, *args, **kwargs) + + self.addBase = True + self.default = False + self.excludedList = [] + self.excludedGroupList = [] + self.excludeDocs = False + self.groupList = [] + self.handleMissing = constants.KS_MISSING_PROMPT + self.packageList = [] + self.instLangs = None + + def __str__(self): + """Return a string formatted for output to a kickstart file.""" + pkgs = "" + + if not self.default: + grps = self.groupList + grps.sort() + for grp in grps: + pkgs += "%s\n" % grp.__str__() + + p = self.packageList + p.sort() + for pkg in p: + pkgs += "%s\n" % pkg + + grps = self.excludedGroupList + grps.sort() + for grp in grps: + pkgs += "-%s\n" % grp.__str__() + + p = self.excludedList + p.sort() + for pkg in p: + pkgs += "-%s\n" % pkg + + if pkgs == "": + return "" + + retval = "\n%packages" + + if self.default: + retval += " --default" + if self.excludeDocs: + retval += " --excludedocs" + if not self.addBase: + retval += " --nobase" + if self.handleMissing == constants.KS_MISSING_IGNORE: + retval += " --ignoremissing" + if self.instLangs: + retval += " --instLangs=%s" % self.instLangs + + if ver >= version.F8: + return retval + "\n" + pkgs + "\n%end\n" + else: + return retval + "\n" + pkgs + "\n" + + def _processGroup (self, line): + op = OptionParser() + op.add_option("--nodefaults", action="store_true", default=False) + op.add_option("--optional", action="store_true", default=False) + + (opts, extra) = op.parse_args(args=line.split()) + + if opts.nodefaults and opts.optional: + raise KickstartValueError, _("Group cannot specify both --nodefaults and --optional") + + # If the group name has spaces in it, we have to put it back together + # now. + grp = " ".join(extra) + + if opts.nodefaults: + self.groupList.append(Group(name=grp, include=constants.GROUP_REQUIRED)) + elif opts.optional: + self.groupList.append(Group(name=grp, include=constants.GROUP_ALL)) + else: + self.groupList.append(Group(name=grp, include=constants.GROUP_DEFAULT)) + + def add (self, pkgList): + """Given a list of lines from the input file, strip off any leading + symbols and add the result to the appropriate list. + """ + existingExcludedSet = set(self.excludedList) + existingPackageSet = set(self.packageList) + newExcludedSet = set() + newPackageSet = set() + + excludedGroupList = [] + + for pkg in pkgList: + stripped = pkg.strip() + + if stripped[0] == "@": + self._processGroup(stripped[1:]) + elif stripped[0] == "-": + if stripped[1] == "@": + excludedGroupList.append(Group(name=stripped[2:])) + else: + newExcludedSet.add(stripped[1:]) + else: + newPackageSet.add(stripped) + + # Groups have to be excluded in two different ways (note: can't use + # sets here because we have to store objects): + excludedGroupNames = map(lambda g: g.name, excludedGroupList) + + # First, an excluded group may be cancelling out a previously given + # one. This is often the case when using %include. So there we should + # just remove the group from the list. + self.groupList = filter(lambda g: g.name not in excludedGroupNames, self.groupList) + + # Second, the package list could have included globs which are not + # processed by pykickstart. In that case we need to preserve a list of + # excluded groups so whatever tool doing package/group installation can + # take appropriate action. + self.excludedGroupList.extend(excludedGroupList) + + existingPackageSet = (existingPackageSet - newExcludedSet) | newPackageSet + existingExcludedSet = (existingExcludedSet - existingPackageSet) | newExcludedSet + + self.packageList = list(existingPackageSet) + self.excludedList = list(existingExcludedSet) + + +### +### PARSER +### +class KickstartParser: + """The kickstart file parser class as represented by a basic state + machine. To create a specialized parser, make a subclass and override + any of the methods you care about. Methods that don't need to do + anything may just pass. However, _stateMachine should never be + overridden. + """ + def __init__ (self, handler, followIncludes=True, errorsAreFatal=True, + missingIncludeIsFatal=True): + """Create a new KickstartParser instance. Instance attributes: + + errorsAreFatal -- Should errors cause processing to halt, or + just print a message to the screen? This + is most useful for writing syntax checkers + that may want to continue after an error is + encountered. + followIncludes -- If %include is seen, should the included + file be checked as well or skipped? + handler -- An instance of a BaseHandler subclass. If + None, the input file will still be parsed + but no data will be saved and no commands + will be executed. + missingIncludeIsFatal -- Should missing include files be fatal, even + if errorsAreFatal is False? + """ + self.errorsAreFatal = errorsAreFatal + self.followIncludes = followIncludes + self.handler = handler + self.currentdir = {} + self.missingIncludeIsFatal = missingIncludeIsFatal + + self._state = STATE_COMMANDS + self._includeDepth = 0 + self._line = "" + + self.version = self.handler.version + + global ver + ver = self.version + + self._sections = {} + self.setupSections() + + def _reset(self): + """Reset the internal variables of the state machine for a new kickstart file.""" + self._state = STATE_COMMANDS + self._includeDepth = 0 + + def getSection(self, s): + """Return a reference to the requested section (s must start with '%'s), + or raise KeyError if not found. + """ + return self._sections[s] + + def handleCommand (self, lineno, args): + """Given the list of command and arguments, call the Version's + dispatcher method to handle the command. Returns the command or + data object returned by the dispatcher. This method may be + overridden in a subclass if necessary. + """ + if self.handler: + self.handler.currentCmd = args[0] + self.handler.currentLine = self._line + retval = self.handler.dispatcher(args, lineno) + + return retval + + def registerSection(self, obj): + """Given an instance of a Section subclass, register the new section + with the parser. Calling this method means the parser will + recognize your new section and dispatch into the given object to + handle it. + """ + if not obj.sectionOpen: + raise TypeError, "no sectionOpen given for section %s" % obj + + if not obj.sectionOpen.startswith("%"): + raise TypeError, "section %s tag does not start with a %%" % obj.sectionOpen + + self._sections[obj.sectionOpen] = obj + + def _finalize(self, obj): + """Called at the close of a kickstart section to take any required + actions. Internally, this is used to add scripts once we have the + whole body read. + """ + obj.finalize() + self._state = STATE_COMMANDS + + def _handleSpecialComments(self, line): + """Kickstart recognizes a couple special comments.""" + if self._state != STATE_COMMANDS: + return + + # Save the platform for s-c-kickstart. + if line[:10] == "#platform=": + self.handler.platform = self._line[11:] + + def _readSection(self, lineIter, lineno): + obj = self._sections[self._state] + + while True: + try: + line = lineIter.next() + if line == "": + # This section ends at the end of the file. + if self.version >= version.F8: + raise KickstartParseError, formatErrorMsg(lineno, msg=_("Section does not end with %%end.")) + + self._finalize(obj) + except StopIteration: + break + + lineno += 1 + + # Throw away blank lines and comments, unless the section wants all + # lines. + if self._isBlankOrComment(line) and not obj.allLines: + continue + + if line.startswith("%"): + args = shlex.split(line) + + if args and args[0] == "%end": + # This is a properly terminated section. + self._finalize(obj) + break + elif args and args[0] == "%ksappend": + continue + elif args and (self._validState(args[0]) or args[0] in ["%include", "%ksappend"]): + # This is an unterminated section. + if self.version >= version.F8: + raise KickstartParseError, formatErrorMsg(lineno, msg=_("Section does not end with %%end.")) + + # Finish up. We do not process the header here because + # kicking back out to STATE_COMMANDS will ensure that happens. + lineIter.put(line) + lineno -= 1 + self._finalize(obj) + break + else: + # This is just a line within a section. Pass it off to whatever + # section handles it. + obj.handleLine(line) + + return lineno + + def _validState(self, st): + """Is the given section tag one that has been registered with the parser?""" + return st in self._sections.keys() + + def _tryFunc(self, fn): + """Call the provided function (which doesn't take any arguments) and + do the appropriate error handling. If errorsAreFatal is False, this + function will just print the exception and keep going. + """ + try: + fn() + except Exception, msg: + if self.errorsAreFatal: + raise + else: + print msg + + def _isBlankOrComment(self, line): + return line.isspace() or line == "" or line.lstrip()[0] == '#' + + def _stateMachine(self, lineIter): + # For error reporting. + lineno = 0 + + while True: + # Get the next line out of the file, quitting if this is the last line. + try: + self._line = lineIter.next() + if self._line == "": + break + except StopIteration: + break + + lineno += 1 + + # Eliminate blank lines, whitespace-only lines, and comments. + if self._isBlankOrComment(self._line): + self._handleSpecialComments(self._line) + continue + + # Remove any end-of-line comments. + sanitized = self._line.split("#")[0] + + # Then split the line. + args = shlex.split(sanitized.rstrip()) + + if args[0] == "%include": + # This case comes up primarily in ksvalidator. + if not self.followIncludes: + continue + + if len(args) == 1 or not args[1]: + raise KickstartParseError, formatErrorMsg(lineno) + + self._includeDepth += 1 + + try: + self.readKickstart(args[1], reset=False) + except KickstartError: + # Handle the include file being provided over the + # network in a %pre script. This case comes up in the + # early parsing in anaconda. + if self.missingIncludeIsFatal: + raise + + self._includeDepth -= 1 + continue + + # Now on to the main event. + if self._state == STATE_COMMANDS: + if args[0] == "%ksappend": + # This is handled by the preprocess* functions, so continue. + continue + elif args[0][0] == '%': + # This is the beginning of a new section. Handle its header + # here. + newSection = args[0] + if not self._validState(newSection): + raise KickstartParseError, formatErrorMsg(lineno, msg=_("Unknown kickstart section: %s" % newSection)) + + self._state = newSection + obj = self._sections[self._state] + self._tryFunc(lambda: obj.handleHeader(lineno, args)) + + # This will handle all section processing, kicking us back + # out to STATE_COMMANDS at the end with the current line + # being the next section header, etc. + lineno = self._readSection(lineIter, lineno) + else: + # This is a command in the command section. Dispatch to it. + self._tryFunc(lambda: self.handleCommand(lineno, args)) + elif self._state == STATE_END: + break + + def readKickstartFromString (self, s, reset=True): + """Process a kickstart file, provided as the string str.""" + if reset: + self._reset() + + # Add a "" to the end of the list so the string reader acts like the + # file reader and we only get StopIteration when we're after the final + # line of input. + i = PutBackIterator(s.splitlines(True) + [""]) + self._stateMachine (i) + + def readKickstart(self, f, reset=True): + """Process a kickstart file, given by the filename f.""" + if reset: + self._reset() + + # an %include might not specify a full path. if we don't try to figure + # out what the path should have been, then we're unable to find it + # requiring full path specification, though, sucks. so let's make + # the reading "smart" by keeping track of what the path is at each + # include depth. + if not os.path.exists(f): + if self.currentdir.has_key(self._includeDepth - 1): + if os.path.exists(os.path.join(self.currentdir[self._includeDepth - 1], f)): + f = os.path.join(self.currentdir[self._includeDepth - 1], f) + + cd = os.path.dirname(f) + if not cd.startswith("/"): + cd = os.path.abspath(cd) + self.currentdir[self._includeDepth] = cd + + try: + s = file(f).read() + except IOError, e: + raise KickstartError, formatErrorMsg(0, msg=_("Unable to open input kickstart file: %s") % e.strerror) + + self.readKickstartFromString(s, reset=False) + + def setupSections(self): + """Install the sections all kickstart files support. You may override + this method in a subclass, but should avoid doing so unless you know + what you're doing. + """ + self._sections = {} + + # Install the sections all kickstart files support. + self.registerSection(PreScriptSection(self.handler, dataObj=Script)) + self.registerSection(PostScriptSection(self.handler, dataObj=Script)) + self.registerSection(TracebackScriptSection(self.handler, dataObj=Script)) + self.registerSection(PackageSection(self.handler)) diff --git a/scripts/lib/wic/3rdparty/pykickstart/sections.py b/scripts/lib/wic/3rdparty/pykickstart/sections.py new file mode 100644 index 0000000000..44df856b8d --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/sections.py @@ -0,0 +1,244 @@ +# +# sections.py: Kickstart file sections. +# +# Chris Lumens +# +# Copyright 2011 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +""" +This module exports the classes that define a section of a kickstart file. A +section is a chunk of the file starting with a %tag and ending with a %end. +Examples of sections include %packages, %pre, and %post. + +You may use this module to define your own custom sections which will be +treated just the same as a predefined one by the kickstart parser. All that +is necessary is to create a new subclass of Section and call +parser.registerSection with an instance of your new class. +""" +from constants import * +from options import KSOptionParser +from version import * + +class Section(object): + """The base class for defining kickstart sections. You are free to + subclass this as appropriate. + + Class attributes: + + allLines -- Does this section require the parser to call handleLine + for every line in the section, even blanks and comments? + sectionOpen -- The string that denotes the start of this section. You + must start your tag with a percent sign. + timesSeen -- This attribute is for informational purposes only. It is + incremented every time handleHeader is called to keep + track of the number of times a section of this type is + seen. + """ + allLines = False + sectionOpen = "" + timesSeen = 0 + + def __init__(self, handler, **kwargs): + """Create a new Script instance. At the least, you must pass in an + instance of a baseHandler subclass. + + Valid kwargs: + + dataObj -- + """ + self.handler = handler + + self.version = self.handler.version + + self.dataObj = kwargs.get("dataObj", None) + + def finalize(self): + """This method is called when the %end tag for a section is seen. It + is not required to be provided. + """ + pass + + def handleLine(self, line): + """This method is called for every line of a section. Take whatever + action is appropriate. While this method is not required to be + provided, not providing it does not make a whole lot of sense. + + Arguments: + + line -- The complete line, with any trailing newline. + """ + pass + + def handleHeader(self, lineno, args): + """This method is called when the opening tag for a section is seen. + Not all sections will need this method, though all provided with + kickstart include one. + + Arguments: + + args -- A list of all strings passed as arguments to the section + opening tag. + """ + self.timesSeen += 1 + +class NullSection(Section): + """This defines a section that pykickstart will recognize but do nothing + with. If the parser runs across a %section that has no object registered, + it will raise an error. Sometimes, you may want to simply ignore those + sections instead. This class is useful for that purpose. + """ + def __init__(self, *args, **kwargs): + """Create a new NullSection instance. You must pass a sectionOpen + parameter (including a leading '%') for the section you wish to + ignore. + """ + Section.__init__(self, *args, **kwargs) + self.sectionOpen = kwargs.get("sectionOpen") + +class ScriptSection(Section): + allLines = True + + def __init__(self, *args, **kwargs): + Section.__init__(self, *args, **kwargs) + self._script = {} + self._resetScript() + + def _getParser(self): + op = KSOptionParser(self.version) + op.add_option("--erroronfail", dest="errorOnFail", action="store_true", + default=False) + op.add_option("--interpreter", dest="interpreter", default="/bin/sh") + op.add_option("--log", "--logfile", dest="log") + return op + + def _resetScript(self): + self._script = {"interp": "/bin/sh", "log": None, "errorOnFail": False, + "lineno": None, "chroot": False, "body": []} + + def handleLine(self, line): + self._script["body"].append(line) + + def finalize(self): + if " ".join(self._script["body"]).strip() == "": + return + + kwargs = {"interp": self._script["interp"], + "inChroot": self._script["chroot"], + "lineno": self._script["lineno"], + "logfile": self._script["log"], + "errorOnFail": self._script["errorOnFail"], + "type": self._script["type"]} + + s = self.dataObj (self._script["body"], **kwargs) + self._resetScript() + + if self.handler: + self.handler.scripts.append(s) + + def handleHeader(self, lineno, args): + """Process the arguments to a %pre/%post/%traceback header for later + setting on a Script instance once the end of the script is found. + This method may be overridden in a subclass if necessary. + """ + Section.handleHeader(self, lineno, args) + op = self._getParser() + + (opts, extra) = op.parse_args(args=args[1:], lineno=lineno) + + self._script["interp"] = opts.interpreter + self._script["lineno"] = lineno + self._script["log"] = opts.log + self._script["errorOnFail"] = opts.errorOnFail + if hasattr(opts, "nochroot"): + self._script["chroot"] = not opts.nochroot + +class PreScriptSection(ScriptSection): + sectionOpen = "%pre" + + def _resetScript(self): + ScriptSection._resetScript(self) + self._script["type"] = KS_SCRIPT_PRE + +class PostScriptSection(ScriptSection): + sectionOpen = "%post" + + def _getParser(self): + op = ScriptSection._getParser(self) + op.add_option("--nochroot", dest="nochroot", action="store_true", + default=False) + return op + + def _resetScript(self): + ScriptSection._resetScript(self) + self._script["chroot"] = True + self._script["type"] = KS_SCRIPT_POST + +class TracebackScriptSection(ScriptSection): + sectionOpen = "%traceback" + + def _resetScript(self): + ScriptSection._resetScript(self) + self._script["type"] = KS_SCRIPT_TRACEBACK + +class PackageSection(Section): + sectionOpen = "%packages" + + def handleLine(self, line): + if not self.handler: + return + + (h, s, t) = line.partition('#') + line = h.rstrip() + + self.handler.packages.add([line]) + + def handleHeader(self, lineno, args): + """Process the arguments to the %packages header and set attributes + on the Version's Packages instance appropriate. This method may be + overridden in a subclass if necessary. + """ + Section.handleHeader(self, lineno, args) + op = KSOptionParser(version=self.version) + op.add_option("--excludedocs", dest="excludedocs", action="store_true", + default=False) + op.add_option("--ignoremissing", dest="ignoremissing", + action="store_true", default=False) + op.add_option("--nobase", dest="nobase", action="store_true", + default=False) + op.add_option("--ignoredeps", dest="resolveDeps", action="store_false", + deprecated=FC4, removed=F9) + op.add_option("--resolvedeps", dest="resolveDeps", action="store_true", + deprecated=FC4, removed=F9) + op.add_option("--default", dest="defaultPackages", action="store_true", + default=False, introduced=F7) + op.add_option("--instLangs", dest="instLangs", type="string", + default="", introduced=F9) + + (opts, extra) = op.parse_args(args=args[1:], lineno=lineno) + + self.handler.packages.excludeDocs = opts.excludedocs + self.handler.packages.addBase = not opts.nobase + if opts.ignoremissing: + self.handler.packages.handleMissing = KS_MISSING_IGNORE + else: + self.handler.packages.handleMissing = KS_MISSING_PROMPT + + if opts.defaultPackages: + self.handler.packages.default = True + + if opts.instLangs: + self.handler.packages.instLangs = opts.instLangs diff --git a/scripts/lib/wic/3rdparty/pykickstart/version.py b/scripts/lib/wic/3rdparty/pykickstart/version.py new file mode 100644 index 0000000000..8a8e6aad22 --- /dev/null +++ b/scripts/lib/wic/3rdparty/pykickstart/version.py @@ -0,0 +1,168 @@ +# +# Chris Lumens +# +# Copyright 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat +# trademarks that are incorporated in the source code or documentation are not +# subject to the GNU General Public License and may only be used or replicated +# with the express permission of Red Hat, Inc. +# +""" +Methods for working with kickstart versions. + +This module defines several symbolic constants that specify kickstart syntax +versions. Each version corresponds roughly to one release of Red Hat Linux, +Red Hat Enterprise Linux, or Fedora Core as these are where most syntax +changes take place. + +This module also exports several functions: + + makeVersion - Given a version number, return an instance of the + matching handler class. + + returnClassForVersion - Given a version number, return the matching + handler class. This does not return an + instance of that class, however. + + stringToVersion - Convert a string representation of a version number + into the symbolic constant. + + versionToString - Perform the reverse mapping. + + versionFromFile - Read a kickstart file and determine the version of + syntax it uses. This requires the kickstart file to + have a version= comment in it. +""" +import imputil, re, sys + +import gettext +_ = lambda x: gettext.ldgettext("pykickstart", x) + +from pykickstart.errors import KickstartVersionError + +# Symbolic names for internal version numbers. +RHEL3 = 900 +FC3 = 1000 +RHEL4 = 1100 +FC4 = 2000 +FC5 = 3000 +FC6 = 4000 +RHEL5 = 4100 +F7 = 5000 +F8 = 6000 +F9 = 7000 +F10 = 8000 +F11 = 9000 +F12 = 10000 +F13 = 11000 +RHEL6 = 11100 +F14 = 12000 +F15 = 13000 +F16 = 14000 + +# This always points at the latest version and is the default. +DEVEL = F16 + +# A one-to-one mapping from string representations to version numbers. +versionMap = { + "DEVEL": DEVEL, + "FC3": FC3, "FC4": FC4, "FC5": FC5, "FC6": FC6, "F7": F7, "F8": F8, + "F9": F9, "F10": F10, "F11": F11, "F12": F12, "F13": F13, + "F14": F14, "F15": F15, "F16": F16, + "RHEL3": RHEL3, "RHEL4": RHEL4, "RHEL5": RHEL5, "RHEL6": RHEL6 +} + +def stringToVersion(s): + """Convert string into one of the provided version constants. Raises + KickstartVersionError if string does not match anything. + """ + # First try these short forms. + try: + return versionMap[s.upper()] + except KeyError: + pass + + # Now try the Fedora versions. + m = re.match("^fedora.* (\d+)$", s, re.I) + + if m and m.group(1): + if versionMap.has_key("FC" + m.group(1)): + return versionMap["FC" + m.group(1)] + elif versionMap.has_key("F" + m.group(1)): + return versionMap["F" + m.group(1)] + else: + raise KickstartVersionError(_("Unsupported version specified: %s") % s) + + # Now try the RHEL versions. + m = re.match("^red hat enterprise linux.* (\d+)([\.\d]*)$", s, re.I) + + if m and m.group(1): + if versionMap.has_key("RHEL" + m.group(1)): + return versionMap["RHEL" + m.group(1)] + else: + raise KickstartVersionError(_("Unsupported version specified: %s") % s) + + # If nothing else worked, we're out of options. + raise KickstartVersionError(_("Unsupported version specified: %s") % s) + +def versionToString(version, skipDevel=False): + """Convert version into a string representation of the version number. + This is the reverse operation of stringToVersion. Raises + KickstartVersionError if version does not match anything. + """ + if not skipDevel and version == versionMap["DEVEL"]: + return "DEVEL" + + for (key, val) in versionMap.iteritems(): + if key == "DEVEL": + continue + elif val == version: + return key + + raise KickstartVersionError(_("Unsupported version specified: %s") % version) + +def returnClassForVersion(version=DEVEL): + """Return the class of the syntax handler for version. version can be + either a string or the matching constant. Raises KickstartValueError + if version does not match anything. + """ + try: + version = int(version) + module = "%s" % versionToString(version, skipDevel=True) + except ValueError: + module = "%s" % version + version = stringToVersion(version) + + module = module.lower() + + try: + import pykickstart.handlers + sys.path.extend(pykickstart.handlers.__path__) + found = imputil.imp.find_module(module) + loaded = imputil.imp.load_module(module, found[0], found[1], found[2]) + + for (k, v) in loaded.__dict__.iteritems(): + if k.lower().endswith("%shandler" % module): + return v + except: + raise KickstartVersionError(_("Unsupported version specified: %s") % version) + +def makeVersion(version=DEVEL): + """Return a new instance of the syntax handler for version. version can be + either a string or the matching constant. This function is useful for + standalone programs which just need to handle a specific version of + kickstart syntax (as provided by a command line argument, for example) + and need to instantiate the correct object. + """ + cl = returnClassForVersion(version) + return cl() diff --git a/scripts/lib/wic/__init__.py b/scripts/lib/wic/__init__.py new file mode 100644 index 0000000000..63c1d9c846 --- /dev/null +++ b/scripts/lib/wic/__init__.py @@ -0,0 +1,4 @@ +import os, sys + +cur_path = os.path.dirname(__file__) or '.' +sys.path.insert(0, cur_path + '/3rdparty') diff --git a/scripts/lib/wic/__version__.py b/scripts/lib/wic/__version__.py new file mode 100644 index 0000000000..5452a46712 --- /dev/null +++ b/scripts/lib/wic/__version__.py @@ -0,0 +1 @@ +VERSION = "2.00" diff --git a/scripts/lib/wic/conf.py b/scripts/lib/wic/conf.py new file mode 100644 index 0000000000..be34355ce4 --- /dev/null +++ b/scripts/lib/wic/conf.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os, sys, re +import ConfigParser + +from wic import msger +from wic import kickstart +from wic.utils import misc, runner, errors + + +def get_siteconf(): + wic_path = os.path.dirname(__file__) + eos = wic_path.find('scripts') + len('scripts') + scripts_path = wic_path[:eos] + + return scripts_path + "/lib/image/config/wic.conf" + +class ConfigMgr(object): + DEFAULTS = {'common': { + "distro_name": "Default Distribution", + "plugin_dir": "/usr/lib/wic/plugins", # TODO use prefix also? + }, + 'create': { + "tmpdir": '/var/tmp/wic', + "outdir": './wic-output', + + "release": None, + "logfile": None, + "name_prefix": None, + "name_suffix": None, + }, + } + + # make the manager class as singleton + _instance = None + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(ConfigMgr, cls).__new__(cls, *args, **kwargs) + + return cls._instance + + def __init__(self, ksconf=None, siteconf=None): + # reset config options + self.reset() + + if not siteconf: + siteconf = get_siteconf() + + # initial options from siteconf + self._siteconf = siteconf + + if ksconf: + self._ksconf = ksconf + + def reset(self): + self.__ksconf = None + self.__siteconf = None + + # initialize the values with defaults + for sec, vals in self.DEFAULTS.iteritems(): + setattr(self, sec, vals) + + def __set_ksconf(self, ksconf): + if not os.path.isfile(ksconf): + msger.error('Cannot find ks file: %s' % ksconf) + + self.__ksconf = ksconf + self._parse_kickstart(ksconf) + def __get_ksconf(self): + return self.__ksconf + _ksconf = property(__get_ksconf, __set_ksconf) + + def _parse_kickstart(self, ksconf=None): + if not ksconf: + return + + ks = kickstart.read_kickstart(ksconf) + + self.create['ks'] = ks + self.create['name'] = os.path.splitext(os.path.basename(ksconf))[0] + + self.create['name'] = misc.build_name(ksconf, + self.create['release'], + self.create['name_prefix'], + self.create['name_suffix']) + +configmgr = ConfigMgr() diff --git a/scripts/lib/wic/creator.py b/scripts/lib/wic/creator.py new file mode 100644 index 0000000000..2219377b38 --- /dev/null +++ b/scripts/lib/wic/creator.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os, sys, re +from optparse import SUPPRESS_HELP + +from wic import msger +from wic.utils import cmdln, errors +from wic.conf import configmgr +from wic.plugin import pluginmgr + + +class Creator(cmdln.Cmdln): + """${name}: create an image + + Usage: + ${name} SUBCOMMAND [OPTS] + + ${command_list} + ${option_list} + """ + + name = 'wic create(cr)' + + def __init__(self, *args, **kwargs): + cmdln.Cmdln.__init__(self, *args, **kwargs) + self._subcmds = [] + + # get cmds from pluginmgr + # mix-in do_subcmd interface + for subcmd, klass in pluginmgr.get_plugins('imager').iteritems(): + if not hasattr(klass, 'do_create'): + msger.warning("Unsupported subcmd: %s" % subcmd) + continue + + func = getattr(klass, 'do_create') + setattr(self.__class__, "do_"+subcmd, func) + self._subcmds.append(subcmd) + + def get_optparser(self): + optparser = cmdln.CmdlnOptionParser(self) + optparser.add_option('-d', '--debug', action='store_true', + dest='debug', + help=SUPPRESS_HELP) + optparser.add_option('-v', '--verbose', action='store_true', + dest='verbose', + help=SUPPRESS_HELP) + optparser.add_option('', '--logfile', type='string', dest='logfile', + default=None, + help='Path of logfile') + optparser.add_option('-c', '--config', type='string', dest='config', + default=None, + help='Specify config file for wic') + optparser.add_option('-o', '--outdir', type='string', action='store', + dest='outdir', default=None, + help='Output directory') + optparser.add_option('', '--tmpfs', action='store_true', dest='enabletmpfs', + help='Setup tmpdir as tmpfs to accelerate, experimental' + ' feature, use it if you have more than 4G memory') + return optparser + + def preoptparse(self, argv): + optparser = self.get_optparser() + + largs = [] + rargs = [] + while argv: + arg = argv.pop(0) + + if arg in ('-h', '--help'): + rargs.append(arg) + + elif optparser.has_option(arg): + largs.append(arg) + + if optparser.get_option(arg).takes_value(): + try: + largs.append(argv.pop(0)) + except IndexError: + raise errors.Usage("option %s requires arguments" % arg) + + else: + if arg.startswith("--"): + if "=" in arg: + opt = arg.split("=")[0] + else: + opt = None + elif arg.startswith("-") and len(arg) > 2: + opt = arg[0:2] + else: + opt = None + + if opt and optparser.has_option(opt): + largs.append(arg) + else: + rargs.append(arg) + + return largs + rargs + + def postoptparse(self): + abspath = lambda pth: os.path.abspath(os.path.expanduser(pth)) + + if self.options.verbose: + msger.set_loglevel('verbose') + if self.options.debug: + msger.set_loglevel('debug') + + if self.options.logfile: + logfile_abs_path = abspath(self.options.logfile) + if os.path.isdir(logfile_abs_path): + raise errors.Usage("logfile's path %s should be file" + % self.options.logfile) + if not os.path.exists(os.path.dirname(logfile_abs_path)): + os.makedirs(os.path.dirname(logfile_abs_path)) + msger.set_interactive(False) + msger.set_logfile(logfile_abs_path) + configmgr.create['logfile'] = self.options.logfile + + if self.options.config: + configmgr.reset() + configmgr._siteconf = self.options.config + + if self.options.outdir is not None: + configmgr.create['outdir'] = abspath(self.options.outdir) + + cdir = 'outdir' + if os.path.exists(configmgr.create[cdir]) \ + and not os.path.isdir(configmgr.create[cdir]): + msger.error('Invalid directory specified: %s' \ + % configmgr.create[cdir]) + + if self.options.enabletmpfs: + configmgr.create['enabletmpfs'] = self.options.enabletmpfs + + def main(self, argv=None): + if argv is None: + argv = sys.argv + else: + argv = argv[:] # don't modify caller's list + + self.optparser = self.get_optparser() + if self.optparser: + try: + argv = self.preoptparse(argv) + self.options, args = self.optparser.parse_args(argv) + + except cmdln.CmdlnUserError, ex: + msg = "%s: %s\nTry '%s help' for info.\n"\ + % (self.name, ex, self.name) + msger.error(msg) + + except cmdln.StopOptionProcessing, ex: + return 0 + else: + # optparser=None means no process for opts + self.options, args = None, argv[1:] + + if not args: + return self.emptyline() + + self.postoptparse() + + return self.cmd(args) + + def precmd(self, argv): # check help before cmd + + if '-h' in argv or '?' in argv or '--help' in argv or 'help' in argv: + return argv + + if len(argv) == 1: + return ['help', argv[0]] + + return argv diff --git a/scripts/lib/wic/imager/__init__.py b/scripts/lib/wic/imager/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/wic/imager/baseimager.py b/scripts/lib/wic/imager/baseimager.py new file mode 100644 index 0000000000..e8305272a2 --- /dev/null +++ b/scripts/lib/wic/imager/baseimager.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2007 Red Hat Inc. +# Copyright (c) 2009, 2010, 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +from __future__ import with_statement +import os, sys +import tempfile +import shutil + +from wic import kickstart +from wic import msger +from wic.utils.errors import CreatorError +from wic.utils import misc, runner, fs_related as fs + +class BaseImageCreator(object): + """Base class for image creation. + + BaseImageCreator is the simplest creator class available; it will + create a system image according to the supplied kickstart file. + + e.g. + + import wic.imgcreate as imgcreate + ks = imgcreate.read_kickstart("foo.ks") + imgcreate.ImageCreator(ks, "foo").create() + """ + + def __del__(self): + self.cleanup() + + def __init__(self, createopts = None): + """Initialize an ImageCreator instance. + + ks -- a pykickstart.KickstartParser instance; this instance will be + used to drive the install by e.g. providing the list of packages + to be installed, the system configuration and %post scripts + + name -- a name for the image; used for e.g. image filenames or + filesystem labels + """ + + self.__builddir = None + + self.ks = None + self.name = "target" + self.tmpdir = "/var/tmp/wic" + self.workdir = "/var/tmp/wic/build" + + # setup tmpfs tmpdir when enabletmpfs is True + self.enabletmpfs = False + + if createopts: + # Mapping table for variables that have different names. + optmap = {"outdir" : "destdir", + } + + # update setting from createopts + for key in createopts.keys(): + if key in optmap: + option = optmap[key] + else: + option = key + setattr(self, option, createopts[key]) + + self.destdir = os.path.abspath(os.path.expanduser(self.destdir)) + + self._dep_checks = ["ls", "bash", "cp", "echo"] + + # Output image file names + self.outimage = [] + + # No ks provided when called by convertor, so skip the dependency check + if self.ks: + # If we have btrfs partition we need to check necessary tools + for part in self.ks.handler.partition.partitions: + if part.fstype and part.fstype == "btrfs": + self._dep_checks.append("mkfs.btrfs") + break + + # make sure the specified tmpdir and cachedir exist + if not os.path.exists(self.tmpdir): + os.makedirs(self.tmpdir) + + + # + # Hooks for subclasses + # + def _create(self): + """Create partitions for the disk image(s) + + This is the hook where subclasses may create the partitions + that will be assembled into disk image(s). + + There is no default implementation. + """ + pass + + def _cleanup(self): + """Undo anything performed in _create(). + + This is the hook where subclasses must undo anything which was + done in _create(). + + There is no default implementation. + + """ + pass + + # + # Actual implementation + # + def __ensure_builddir(self): + if not self.__builddir is None: + return + + try: + self.workdir = os.path.join(self.tmpdir, "build") + if not os.path.exists(self.workdir): + os.makedirs(self.workdir) + self.__builddir = tempfile.mkdtemp(dir = self.workdir, + prefix = "imgcreate-") + except OSError, (err, msg): + raise CreatorError("Failed create build directory in %s: %s" % + (self.tmpdir, msg)) + + def __setup_tmpdir(self): + if not self.enabletmpfs: + return + + runner.show('mount -t tmpfs -o size=4G tmpfs %s' % self.workdir) + + def __clean_tmpdir(self): + if not self.enabletmpfs: + return + + runner.show('umount -l %s' % self.workdir) + + def create(self): + """Create partitions for the disk image(s) + + Create the partitions that will be assembled into disk + image(s). + """ + self.__setup_tmpdir() + self.__ensure_builddir() + + self._create() + + def cleanup(self): + """Undo anything performed in create(). + + Note, make sure to call this method once finished with the creator + instance in order to ensure no stale files are left on the host e.g.: + + creator = ImageCreator(ks, name) + try: + creator.create() + finally: + creator.cleanup() + + """ + if not self.__builddir: + return + + self._cleanup() + + shutil.rmtree(self.__builddir, ignore_errors = True) + self.__builddir = None + + self.__clean_tmpdir() + + + def print_outimage_info(self): + msg = "The new image can be found here:\n" + self.outimage.sort() + for file in self.outimage: + msg += ' %s\n' % os.path.abspath(file) + + msger.info(msg) diff --git a/scripts/lib/wic/imager/direct.py b/scripts/lib/wic/imager/direct.py new file mode 100644 index 0000000000..d0ae504daf --- /dev/null +++ b/scripts/lib/wic/imager/direct.py @@ -0,0 +1,363 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'direct' image creator class for 'wic' +# +# AUTHORS +# Tom Zanussi +# + +import os +import stat +import shutil + +from wic import kickstart, msger +from wic.utils import fs_related, runner, misc +from wic.utils.partitionedfs import Image +from wic.utils.errors import CreatorError, ImageError +from wic.imager.baseimager import BaseImageCreator +from wic.utils.oe.misc import * +from wic.plugin import pluginmgr + +disk_methods = { + "do_install_disk":None, +} + +class DirectImageCreator(BaseImageCreator): + """ + Installs a system into a file containing a partitioned disk image. + + DirectImageCreator is an advanced ImageCreator subclass; an image + file is formatted with a partition table, each partition created + from a rootfs or other OpenEmbedded build artifact and dd'ed into + the virtual disk. The disk image can subsequently be dd'ed onto + media and used on actual hardware. + """ + + def __init__(self, oe_builddir, image_output_dir, rootfs_dir, bootimg_dir, + kernel_dir, native_sysroot, creatoropts=None): + """ + Initialize a DirectImageCreator instance. + + This method takes the same arguments as ImageCreator.__init__() + """ + BaseImageCreator.__init__(self, creatoropts) + + self.__image = None + self.__disks = {} + self.__disk_format = "direct" + self._disk_names = [] + self._ptable_format = self.ks.handler.bootloader.ptable + + self.oe_builddir = oe_builddir + if image_output_dir: + self.tmpdir = image_output_dir + self.rootfs_dir = rootfs_dir + self.bootimg_dir = bootimg_dir + self.kernel_dir = kernel_dir + self.native_sysroot = native_sysroot + + def __write_fstab(self, image_rootfs): + """overriden to generate fstab (temporarily) in rootfs. This is called + from _create, make sure it doesn't get called from + BaseImage.create() + """ + if image_rootfs is None: + return None + + fstab = image_rootfs + "/etc/fstab" + if not os.path.isfile(fstab): + return None + + parts = self._get_parts() + + self._save_fstab(fstab) + fstab_lines = self._get_fstab(fstab, parts) + self._update_fstab(fstab_lines, parts) + self._write_fstab(fstab, fstab_lines) + + return fstab + + def _update_fstab(self, fstab_lines, parts): + """Assume partition order same as in wks""" + for num, p in enumerate(parts, 1): + if not p.mountpoint or p.mountpoint == "/" or p.mountpoint == "/boot": + continue + if self._ptable_format == 'msdos' and num > 3: + device_name = "/dev/" + p.disk + str(num + 1) + else: + device_name = "/dev/" + p.disk + str(num) + + opts = "defaults" + if p.fsopts: + opts = p.fsopts + + fstab_entry = device_name + "\t" + \ + p.mountpoint + "\t" + \ + p.fstype + "\t" + \ + opts + "\t0\t0\n" + fstab_lines.append(fstab_entry) + + def _write_fstab(self, fstab, fstab_lines): + fstab = open(fstab, "w") + for line in fstab_lines: + fstab.write(line) + fstab.close() + + def _save_fstab(self, fstab): + """Save the current fstab in rootfs""" + shutil.copyfile(fstab, fstab + ".orig") + + def _restore_fstab(self, fstab): + """Restore the saved fstab in rootfs""" + if fstab is None: + return + shutil.move(fstab + ".orig", fstab) + + def _get_fstab(self, fstab, parts): + """Return the desired contents of /etc/fstab.""" + f = open(fstab, "r") + fstab_contents = f.readlines() + f.close() + + return fstab_contents + + def set_bootimg_dir(self, bootimg_dir): + """ + Accessor for bootimg_dir, the actual location used for the source + of the bootimg. Should be set by source plugins (only if they + change the default bootimg source) so the correct info gets + displayed for print_outimage_info(). + """ + self.bootimg_dir = bootimg_dir + + def _get_parts(self): + if not self.ks: + raise CreatorError("Failed to get partition info, " + "please check your kickstart setting.") + + # Set a default partition if no partition is given out + if not self.ks.handler.partition.partitions: + partstr = "part / --size 1900 --ondisk sda --fstype=ext3" + args = partstr.split() + pd = self.ks.handler.partition.parse(args[1:]) + if pd not in self.ks.handler.partition.partitions: + self.ks.handler.partition.partitions.append(pd) + + # partitions list from kickstart file + return kickstart.get_partitions(self.ks) + + def get_disk_names(self): + """ Returns a list of physical target disk names (e.g., 'sdb') which + will be created. """ + + if self._disk_names: + return self._disk_names + + #get partition info from ks handler + parts = self._get_parts() + + for i in range(len(parts)): + if parts[i].disk: + disk_name = parts[i].disk + else: + raise CreatorError("Failed to create disks, no --ondisk " + "specified in partition line of ks file") + + if parts[i].mountpoint and not parts[i].fstype: + raise CreatorError("Failed to create disks, no --fstype " + "specified for partition with mountpoint " + "'%s' in the ks file") + + self._disk_names.append(disk_name) + + return self._disk_names + + def _full_name(self, name, extention): + """ Construct full file name for a file we generate. """ + return "%s-%s.%s" % (self.name, name, extention) + + def _full_path(self, path, name, extention): + """ Construct full file path to a file we generate. """ + return os.path.join(path, self._full_name(name, extention)) + + def get_default_source_plugin(self): + """ + The default source plugin i.e. the plugin that's consulted for + overall image generation tasks outside of any particular + partition. For convenience, we just hang it off the + bootloader handler since it's the one non-partition object in + any setup. By default the default plugin is set to the same + plugin as the /boot partition; since we hang it off the + bootloader object, the default can be explicitly set using the + --source bootloader param. + """ + return self.ks.handler.bootloader.source + + # + # Actual implemention + # + def _create(self): + """ + For 'wic', we already have our build artifacts - we just create + filesystems from the artifacts directly and combine them into + a partitioned image. + """ + parts = self._get_parts() + + self.__image = Image() + + for p in parts: + # as a convenience, set source to the boot partition source + # instead of forcing it to be set via bootloader --source + if not self.ks.handler.bootloader.source and p.mountpoint == "/boot": + self.ks.handler.bootloader.source = p.source + + for p in parts: + # need to create the filesystems in order to get their + # sizes before we can add them and do the layout. + # Image.create() actually calls __format_disks() to create + # the disk images and carve out the partitions, then + # self.assemble() calls Image.assemble() which calls + # __write_partitition() for each partition to dd the fs + # into the partitions. + + p.install_pkgs(self, self.workdir, self.oe_builddir, self.rootfs_dir, + self.bootimg_dir, self.kernel_dir, self.native_sysroot) + + fstab = self.__write_fstab(self.rootfs_dir.get("ROOTFS_DIR")) + + p.prepare(self, self.workdir, self.oe_builddir, self.rootfs_dir, + self.bootimg_dir, self.kernel_dir, self.native_sysroot) + + self._restore_fstab(fstab) + + self.__image.add_partition(int(p.size), + p.disk, + p.mountpoint, + p.source_file, + p.fstype, + p.label, + fsopts = p.fsopts, + boot = p.active, + align = p.align, + part_type = p.part_type) + + self.__image.layout_partitions(self._ptable_format) + + self.__imgdir = self.workdir + for disk_name, disk in self.__image.disks.items(): + full_path = self._full_path(self.__imgdir, disk_name, "direct") + msger.debug("Adding disk %s as %s with size %s bytes" \ + % (disk_name, full_path, disk['min_size'])) + disk_obj = fs_related.DiskImage(full_path, disk['min_size']) + self.__disks[disk_name] = disk_obj + self.__image.add_disk(disk_name, disk_obj) + + self.__image.create() + + def assemble(self): + """ + Assemble partitions into disk image(s) + """ + for disk_name, disk in self.__image.disks.items(): + full_path = self._full_path(self.__imgdir, disk_name, "direct") + msger.debug("Assembling disk %s as %s with size %s bytes" \ + % (disk_name, full_path, disk['min_size'])) + self.__image.assemble(full_path) + + def finalize(self): + """ + Finalize the disk image. + + For example, prepare the image to be bootable by e.g. + creating and installing a bootloader configuration. + + """ + source_plugin = self.get_default_source_plugin() + if source_plugin: + self._source_methods = pluginmgr.get_source_plugin_methods(source_plugin, disk_methods) + for disk_name, disk in self.__image.disks.items(): + self._source_methods["do_install_disk"](disk, disk_name, self, + self.workdir, + self.oe_builddir, + self.bootimg_dir, + self.kernel_dir, + self.native_sysroot) + + def print_outimage_info(self): + """ + Print the image(s) and artifacts used, for the user. + """ + msg = "The new image(s) can be found here:\n" + + parts = self._get_parts() + + for disk_name, disk in self.__image.disks.items(): + full_path = self._full_path(self.__imgdir, disk_name, "direct") + msg += ' %s\n\n' % full_path + + msg += 'The following build artifacts were used to create the image(s):\n' + for p in parts: + if p.get_rootfs() is None: + continue + if p.mountpoint == '/': + str = ':' + else: + str = '["%s"]:' % p.label + msg += ' ROOTFS_DIR%s%s\n' % (str.ljust(20), p.get_rootfs()) + + msg += ' BOOTIMG_DIR: %s\n' % self.bootimg_dir + msg += ' KERNEL_DIR: %s\n' % self.kernel_dir + msg += ' NATIVE_SYSROOT: %s\n' % self.native_sysroot + + msger.info(msg) + + def _get_boot_config(self): + """ + Return the rootdev/root_part_uuid (if specified by + --part-type) + + Assume partition order same as in wks + """ + rootdev = None + root_part_uuid = None + parts = self._get_parts() + for num, p in enumerate(parts, 1): + if p.mountpoint == "/": + part = '' + if p.disk.startswith('mmcblk'): + part = 'p' + + if self._ptable_format == 'msdos' and num > 3: + rootdev = "/dev/%s%s%-d" % (p.disk, part, num + 1) + else: + rootdev = "/dev/%s%s%-d" % (p.disk, part, num) + root_part_uuid = p.part_type + + return (rootdev, root_part_uuid) + + def _cleanup(self): + if not self.__image is None: + try: + self.__image.cleanup() + except ImageError, err: + msger.warning("%s" % err) + diff --git a/scripts/lib/wic/kickstart/__init__.py b/scripts/lib/wic/kickstart/__init__.py new file mode 100644 index 0000000000..600098293a --- /dev/null +++ b/scripts/lib/wic/kickstart/__init__.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2007 Red Hat, Inc. +# Copyright (c) 2009, 2010, 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os, sys, re +import shutil +import subprocess +import string + +import pykickstart.sections as kssections +import pykickstart.commands as kscommands +import pykickstart.constants as ksconstants +import pykickstart.errors as kserrors +import pykickstart.parser as ksparser +import pykickstart.version as ksversion +from pykickstart.handlers.control import commandMap +from pykickstart.handlers.control import dataMap + +from wic import msger +from wic.utils import errors, misc, runner, fs_related as fs +from custom_commands import wicboot, partition + +def read_kickstart(path): + """Parse a kickstart file and return a KickstartParser instance. + + This is a simple utility function which takes a path to a kickstart file, + parses it and returns a pykickstart KickstartParser instance which can + be then passed to an ImageCreator constructor. + + If an error occurs, a CreatorError exception is thrown. + """ + + #version = ksversion.makeVersion() + #ks = ksparser.KickstartParser(version) + + using_version = ksversion.DEVEL + commandMap[using_version]["bootloader"] = wicboot.Wic_Bootloader + commandMap[using_version]["part"] = partition.Wic_Partition + commandMap[using_version]["partition"] = partition.Wic_Partition + dataMap[using_version]["PartData"] = partition.Wic_PartData + superclass = ksversion.returnClassForVersion(version=using_version) + + class KSHandlers(superclass): + def __init__(self): + superclass.__init__(self, mapping=commandMap[using_version]) + + ks = ksparser.KickstartParser(KSHandlers(), errorsAreFatal=False) + + try: + ks.readKickstart(path) + except (kserrors.KickstartParseError, kserrors.KickstartError), err: + if msger.ask("Errors occured on kickstart file, skip and continue?"): + msger.warning("%s" % err) + pass + else: + raise errors.KsError("%s" % err) + + return ks + +def get_image_size(ks, default = None): + __size = 0 + for p in ks.handler.partition.partitions: + if p.mountpoint == "/" and p.size: + __size = p.size + if __size > 0: + return int(__size) * 1024L * 1024L + else: + return default + +def get_image_fstype(ks, default = None): + for p in ks.handler.partition.partitions: + if p.mountpoint == "/" and p.fstype: + return p.fstype + return default + +def get_image_fsopts(ks, default = None): + for p in ks.handler.partition.partitions: + if p.mountpoint == "/" and p.fsopts: + return p.fsopts + return default + +def get_timeout(ks, default = None): + if not hasattr(ks.handler.bootloader, "timeout"): + return default + if ks.handler.bootloader.timeout is None: + return default + return int(ks.handler.bootloader.timeout) + +def get_kernel_args(ks, default = "ro rd.live.image"): + if not hasattr(ks.handler.bootloader, "appendLine"): + return default + if ks.handler.bootloader.appendLine is None: + return default + return "%s %s" %(default, ks.handler.bootloader.appendLine) + +def get_menu_args(ks, default = ""): + if not hasattr(ks.handler.bootloader, "menus"): + return default + if ks.handler.bootloader.menus in (None, ""): + return default + return "%s" % ks.handler.bootloader.menus + +def get_default_kernel(ks, default = None): + if not hasattr(ks.handler.bootloader, "default"): + return default + if not ks.handler.bootloader.default: + return default + return ks.handler.bootloader.default + +def get_partitions(ks): + return ks.handler.partition.partitions diff --git a/scripts/lib/wic/kickstart/custom_commands/__init__.py b/scripts/lib/wic/kickstart/custom_commands/__init__.py new file mode 100644 index 0000000000..f84c6d9e00 --- /dev/null +++ b/scripts/lib/wic/kickstart/custom_commands/__init__.py @@ -0,0 +1,10 @@ +from micpartition import Mic_Partition +from micpartition import Mic_PartData +from partition import Wic_Partition + +__all__ = ( + "Mic_Partition", + "Mic_PartData", + "Wic_Partition", + "Wic_PartData", +) diff --git a/scripts/lib/wic/kickstart/custom_commands/micboot.py b/scripts/lib/wic/kickstart/custom_commands/micboot.py new file mode 100644 index 0000000000..d162142506 --- /dev/null +++ b/scripts/lib/wic/kickstart/custom_commands/micboot.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2008, 2009, 2010 Intel, Inc. +# +# Anas Nashif +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +from pykickstart.base import * +from pykickstart.errors import * +from pykickstart.options import * +from pykickstart.commands.bootloader import * + +class Mic_Bootloader(F8_Bootloader): + def __init__(self, writePriority=10, appendLine="", driveorder=None, + forceLBA=False, location="", md5pass="", password="", + upgrade=False, menus=""): + F8_Bootloader.__init__(self, writePriority, appendLine, driveorder, + forceLBA, location, md5pass, password, upgrade) + + self.menus = "" + self.ptable = "msdos" + + def _getArgsAsStr(self): + ret = F8_Bootloader._getArgsAsStr(self) + + if self.menus == "": + ret += " --menus=%s" %(self.menus,) + if self.ptable: + ret += " --ptable=\"%s\"" %(self.ptable,) + return ret + + def _getParser(self): + op = F8_Bootloader._getParser(self) + op.add_option("--menus", dest="menus") + op.add_option("--ptable", dest="ptable", type="string") + return op + diff --git a/scripts/lib/wic/kickstart/custom_commands/micpartition.py b/scripts/lib/wic/kickstart/custom_commands/micpartition.py new file mode 100644 index 0000000000..43d04f1294 --- /dev/null +++ b/scripts/lib/wic/kickstart/custom_commands/micpartition.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python -tt +# +# Marko Saukko +# +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# +# This copyrighted material is made available to anyone wishing to use, modify, +# copy, or redistribute it subject to the terms and conditions of the GNU +# General Public License v.2. This program is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the +# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +from pykickstart.commands.partition import * + +class Mic_PartData(FC4_PartData): + removedKeywords = FC4_PartData.removedKeywords + removedAttrs = FC4_PartData.removedAttrs + + def __init__(self, *args, **kwargs): + FC4_PartData.__init__(self, *args, **kwargs) + self.deleteRemovedAttrs() + self.align = kwargs.get("align", None) + self.extopts = kwargs.get("extopts", None) + self.part_type = kwargs.get("part_type", None) + + def _getArgsAsStr(self): + retval = FC4_PartData._getArgsAsStr(self) + + if self.align: + retval += " --align" + if self.extopts: + retval += " --extoptions=%s" % self.extopts + if self.part_type: + retval += " --part-type=%s" % self.part_type + + return retval + +class Mic_Partition(FC4_Partition): + removedKeywords = FC4_Partition.removedKeywords + removedAttrs = FC4_Partition.removedAttrs + + def _getParser(self): + op = FC4_Partition._getParser(self) + # The alignment value is given in kBytes. e.g., value 8 means that + # the partition is aligned to start from 8096 byte boundary. + op.add_option("--align", type="int", action="store", dest="align", + default=None) + op.add_option("--extoptions", type="string", action="store", dest="extopts", + default=None) + op.add_option("--part-type", type="string", action="store", dest="part_type", + default=None) + return op diff --git a/scripts/lib/wic/kickstart/custom_commands/partition.py b/scripts/lib/wic/kickstart/custom_commands/partition.py new file mode 100644 index 0000000000..03332194df --- /dev/null +++ b/scripts/lib/wic/kickstart/custom_commands/partition.py @@ -0,0 +1,652 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module provides the OpenEmbedded partition object definitions. +# +# AUTHORS +# Tom Zanussi +# + +import shutil +import os +import tempfile + +from pykickstart.commands.partition import * +from wic.utils.oe.misc import * +from wic.kickstart.custom_commands import * +from wic.plugin import pluginmgr + +import os +from mic.utils.oe.package_manager import * + +partition_methods = { + "do_install_pkgs":None, + "do_stage_partition":None, + "do_prepare_partition":None, + "do_configure_partition":None, +} + +class Wic_PartData(Mic_PartData): + removedKeywords = Mic_PartData.removedKeywords + removedAttrs = Mic_PartData.removedAttrs + + def __init__(self, *args, **kwargs): + Mic_PartData.__init__(self, *args, **kwargs) + self.deleteRemovedAttrs() + self.source = kwargs.get("source", None) + self.sourceparams = kwargs.get("sourceparams", None) + self.rootfs = kwargs.get("rootfs-dir", None) + self.source_file = "" + self.size = 0 + + def _getArgsAsStr(self): + retval = Mic_PartData._getArgsAsStr(self) + + if self.source: + retval += " --source=%s" % self.source + if self.sourceparams: + retval += " --sourceparams=%s" % self.sourceparams + if self.rootfs: + retval += " --rootfs-dir=%s" % self.rootfs + + return retval + + def get_rootfs(self): + """ + Acessor for rootfs dir + """ + return self.rootfs + + def set_rootfs(self, rootfs): + """ + Acessor for actual rootfs dir, which must be set by source + plugins. + """ + self.rootfs = rootfs + + def get_size(self): + """ + Accessor for partition size, 0 or --size before set_size(). + """ + return self.size + + def set_size(self, size): + """ + Accessor for actual partition size, which must be set by source + plugins. + """ + self.size = size + + def set_source_file(self, source_file): + """ + Accessor for source_file, the location of the generated partition + image, which must be set by source plugins. + """ + self.source_file = source_file + + def get_extra_block_count(self, current_blocks): + """ + The --size param is reflected in self.size (in MB), and we already + have current_blocks (1k) blocks, calculate and return the + number of (1k) blocks we need to add to get to --size, 0 if + we're already there or beyond. + """ + msger.debug("Requested partition size for %s: %d" % \ + (self.mountpoint, self.size)) + + if not self.size: + return 0 + + requested_blocks = self.size * 1024 + + msger.debug("Requested blocks %d, current_blocks %d" % \ + (requested_blocks, current_blocks)) + + if requested_blocks > current_blocks: + return requested_blocks - current_blocks + else: + return 0 + + def install_pkgs(self, creator, cr_workdir, oe_builddir, rootfs_dir, + bootimg_dir, kernel_dir, native_sysroot): + """ + Prepare content for individual partitions, installing packages. + """ + + if not self.source: + return + + self._source_methods = pluginmgr.get_source_plugin_methods(self.source, partition_methods) + self._source_methods["do_install_pkgs"](self, creator, + cr_workdir, + oe_builddir, + rootfs_dir, + bootimg_dir, + kernel_dir, + native_sysroot) + + def install_pkgs_ipk(self, cr_workdir, oe_builddir, rootfs_dir, + native_sysroot, packages, repourl): + """ + Install packages specified into wks file using opkg package manager. + This method is dependend on bb module. + """ + + gVar = {} + gVar["DEPLOY_DIR_IPK"] = os.path.join(oe_builddir, "tmp/deploy/ipk") + + # Run postinstall scripts even in offline mode + # Use the arch priority package rather than higher version one if more than one candidate is found. + #d.setVar("OPKG_ARGS", "--force_postinstall --prefer-arch-to-version") + gVar["OPKG_ARGS"] = "--force_postinstall" + + # OPKG path relative to /output_path + gVar["OPKGLIBDIR"] = "var/lib" + + source_url = repourl.split() + + # Generate feed uri's names, it doesn't seem to matter what name they have + feed_uris = "" + cnt = 0 + archs = "" + for url in source_url: + feed_uris += "cl_def_feed%d##%s\n" % (cnt, url) + cnt += 1 + head, tail = os.path.split(url) + archs += " " + tail + + # IPK_FEED_URIS with special formating defines the URI's used as source for packages + gVar['IPK_FEED_URIS'] = feed_uris + + gVar['BUILD_IMAGES_FROM_FEEDS'] = "1" + + # We need to provide sysroot for utilities + gVar['STAGING_DIR_NATIVE'] = native_sysroot + + # Set WORKDIR for output + gVar['WORKDIR'] = cr_workdir + + # Set TMPDIR for output + gVar['TMPDIR'] = os.path.join(cr_workdir, "tmp") + + if 'ROOTFS_DIR' in rootfs_dir: + target_dir = rootfs_dir['ROOTFS_DIR'] + elif os.path.isdir(rootfs_dir): + target_dir = rootfs_dir + else: + msg = "Couldn't find --rootfs-dir=%s connection" + msg += " or it is not a valid path, exiting" + msger.error(msg % rootfs_dir) + + # Need native sysroot /usr/bin/ for opkg-cl + # chnage PATH var to avoid issues with host tools + defpath = os.environ['PATH'] + os.environ['PATH'] = native_sysroot + "/usr/bin/" + ":/bin:/usr/bin:" + + pseudo = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot + pseudo += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % target_dir + pseudo += "export PSEUDO_PASSWD=%s;" % target_dir + pseudo += "export PSEUDO_NOSYMLINKEXP=1;" + pseudo += "%s/usr/bin/pseudo " % native_sysroot + + pm = WicOpkgPM(gVar, + target_dir, + 'opkg.conf', + archs, + pseudo, + native_sysroot) + + pm.update() + + pm.install(packages) + + os.environ['PATH'] += defpath + ":" + native_sysroot + "/usr/bin/" + + + def prepare(self, cr, cr_workdir, oe_builddir, rootfs_dir, bootimg_dir, + kernel_dir, native_sysroot): + """ + Prepare content for individual partitions, depending on + partition command parameters. + """ + self.sourceparams_dict = {} + + if self.sourceparams: + self.sourceparams_dict = parse_sourceparams(self.sourceparams) + + if not self.source: + if not self.size: + msger.error("The %s partition has a size of zero. Please specify a non-zero --size for that partition." % self.mountpoint) + if self.fstype and self.fstype == "swap": + self.prepare_swap_partition(cr_workdir, oe_builddir, + native_sysroot) + elif self.fstype: + self.prepare_empty_partition(cr_workdir, oe_builddir, + native_sysroot) + return + + plugins = pluginmgr.get_source_plugins() + + if self.source not in plugins: + msger.error("The '%s' --source specified for %s doesn't exist.\n\tSee 'wic list source-plugins' for a list of available --sources.\n\tSee 'wic help source-plugins' for details on adding a new source plugin." % (self.source, self.mountpoint)) + + self._source_methods = pluginmgr.get_source_plugin_methods(self.source, partition_methods) + self._source_methods["do_configure_partition"](self, self.sourceparams_dict, + cr, cr_workdir, + oe_builddir, + bootimg_dir, + kernel_dir, + native_sysroot) + self._source_methods["do_stage_partition"](self, self.sourceparams_dict, + cr, cr_workdir, + oe_builddir, + bootimg_dir, kernel_dir, + native_sysroot) + self._source_methods["do_prepare_partition"](self, self.sourceparams_dict, + cr, cr_workdir, + oe_builddir, + bootimg_dir, kernel_dir, rootfs_dir, + native_sysroot) + + def prepare_rootfs_from_fs_image(self, cr_workdir, oe_builddir, + rootfs_dir): + """ + Handle an already-created partition e.g. xxx.ext3 + """ + rootfs = oe_builddir + du_cmd = "du -Lbms %s" % rootfs + out = exec_cmd(du_cmd) + rootfs_size = out.split()[0] + + self.size = rootfs_size + self.source_file = rootfs + + def prepare_rootfs(self, cr_workdir, oe_builddir, rootfs_dir, + native_sysroot): + """ + Prepare content for a rootfs partition i.e. create a partition + and fill it from a /rootfs dir. + + Currently handles ext2/3/4, btrfs and vfat. + """ + pseudo = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot + pseudo += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % rootfs_dir + pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir + pseudo += "export PSEUDO_NOSYMLINKEXP=1;" + pseudo += "%s/usr/bin/pseudo " % native_sysroot + + if self.fstype.startswith("ext"): + return self.prepare_rootfs_ext(cr_workdir, oe_builddir, + rootfs_dir, native_sysroot, + pseudo) + elif self.fstype.startswith("btrfs"): + return self.prepare_rootfs_btrfs(cr_workdir, oe_builddir, + rootfs_dir, native_sysroot, + pseudo) + + elif self.fstype.startswith("vfat"): + return self.prepare_rootfs_vfat(cr_workdir, oe_builddir, + rootfs_dir, native_sysroot, + pseudo) + elif self.fstype.startswith("squashfs"): + return self.prepare_rootfs_squashfs(cr_workdir, oe_builddir, + rootfs_dir, native_sysroot, + pseudo) + + def prepare_rootfs_ext(self, cr_workdir, oe_builddir, rootfs_dir, + native_sysroot, pseudo): + """ + Prepare content for an ext2/3/4 rootfs partition. + """ + + image_rootfs = rootfs_dir + rootfs = "%s/rootfs_%s.%s" % (cr_workdir, self.label ,self.fstype) + + du_cmd = "du -ks %s" % image_rootfs + out = exec_cmd(du_cmd) + actual_rootfs_size = int(out.split()[0]) + + extra_blocks = self.get_extra_block_count(actual_rootfs_size) + + if extra_blocks < IMAGE_EXTRA_SPACE: + extra_blocks = IMAGE_EXTRA_SPACE + + rootfs_size = actual_rootfs_size + extra_blocks + rootfs_size *= IMAGE_OVERHEAD_FACTOR + + msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \ + (extra_blocks, self.mountpoint, rootfs_size)) + + dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=0 bs=1k" % \ + (rootfs, rootfs_size) + exec_cmd(dd_cmd) + + extra_imagecmd = "-i 8192" + + mkfs_cmd = "mkfs.%s -F %s %s -d %s" % \ + (self.fstype, extra_imagecmd, rootfs, image_rootfs) + (rc, out) = exec_native_cmd(pseudo + mkfs_cmd, native_sysroot) + if rc: + print "rootfs_dir: %s" % rootfs_dir + msger.error("ERROR: mkfs.%s returned '%s' instead of 0 (which you probably don't want to ignore, use --debug for details) when creating filesystem from rootfs directory: %s" % (self.fstype, rc, rootfs_dir)) + + # get the rootfs size in the right units for kickstart (Mb) + du_cmd = "du -Lbms %s" % rootfs + out = exec_cmd(du_cmd) + rootfs_size = out.split()[0] + + self.size = rootfs_size + self.source_file = rootfs + + return 0 + + def prepare_for_uboot(self, arch, cr_workdir, oe_builddir, rootfs_dir, + native_sysroot): + """ + Generates u-boot image from source_file( ext2/3/4 ) + + """ + pseudo = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot + pseudo += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % rootfs_dir + pseudo += "export PSEUDO_PASSWD=%s;" % rootfs_dir + pseudo += "export PSEUDO_NOSYMLINKEXP=1;" + pseudo += "%s/usr/bin/pseudo " % native_sysroot + + # 1) compress image + rootfs = self.source_file + rootfs_gzip = "%s.gz" % rootfs + gzip_cmd = "gzip -f -9 -c %s > %s" % (rootfs, rootfs_gzip) + rc, out = exec_native_cmd(pseudo + gzip_cmd, native_sysroot) + + # 2) image for U-Boot + rootfs_uboot = "%s.u-boot" % rootfs_gzip + mkimage_cmd = "mkimage -A %s -O linux -T ramdisk -C gzip -n %s -d %s %s" % \ + (arch, self.label, rootfs_gzip, rootfs_uboot) + rc, out = exec_native_cmd(pseudo + mkimage_cmd, native_sysroot) + + msger.info("\n\n\tThe new U-Boot ramdisk image can be found here:\n\t\t%s\n\n" % rootfs_uboot) + + return 0 + + def prepare_rootfs_btrfs(self, cr_workdir, oe_builddir, rootfs_dir, + native_sysroot, pseudo): + """ + Prepare content for a btrfs rootfs partition. + + Currently handles ext2/3/4 and btrfs. + """ + image_rootfs = rootfs_dir + rootfs = "%s/rootfs_%s.%s" % (cr_workdir, self.label, self.fstype) + + du_cmd = "du -ks %s" % image_rootfs + out = exec_cmd(du_cmd) + actual_rootfs_size = int(out.split()[0]) + + extra_blocks = self.get_extra_block_count(actual_rootfs_size) + + if extra_blocks < IMAGE_EXTRA_SPACE: + extra_blocks = IMAGE_EXTRA_SPACE + + rootfs_size = actual_rootfs_size + extra_blocks + rootfs_size *= IMAGE_OVERHEAD_FACTOR + + msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \ + (extra_blocks, self.mountpoint, rootfs_size)) + + dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=0 bs=1k" % \ + (rootfs, rootfs_size) + exec_cmd(dd_cmd) + + mkfs_cmd = "mkfs.%s -b %d -r %s %s" % \ + (self.fstype, rootfs_size * 1024, image_rootfs, rootfs) + (rc, out) = exec_native_cmd(pseudo + mkfs_cmd, native_sysroot) + if rc: + msger.error("ERROR: mkfs.%s returned '%s' instead of 0 (which you probably don't want to ignore, use --debug for details) when creating filesystem from rootfs directory: %s" % (self.fstype, rc, rootfs_dir)) + + # get the rootfs size in the right units for kickstart (Mb) + du_cmd = "du -Lbms %s" % rootfs + out = exec_cmd(du_cmd) + rootfs_size = out.split()[0] + + self.size = rootfs_size + self.source_file = rootfs + + def prepare_rootfs_vfat(self, cr_workdir, oe_builddir, rootfs_dir, + native_sysroot, pseudo): + """ + Prepare content for a vfat rootfs partition. + """ + image_rootfs = rootfs_dir + rootfs = "%s/rootfs_%s.%s" % (cr_workdir, self.label, self.fstype) + + du_cmd = "du -bks %s" % image_rootfs + out = exec_cmd(du_cmd) + blocks = int(out.split()[0]) + + extra_blocks = self.get_extra_block_count(blocks) + + if extra_blocks < IMAGE_EXTRA_SPACE: + extra_blocks = IMAGE_EXTRA_SPACE + + blocks += extra_blocks + + msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \ + (extra_blocks, self.mountpoint, blocks)) + + # Ensure total sectors is an integral number of sectors per + # track or mcopy will complain. Sectors are 512 bytes, and we + # generate images with 32 sectors per track. This calculation + # is done in blocks, thus the mod by 16 instead of 32. Apply + # sector count fix only when needed. + if blocks % 16 != 0: + blocks += (16 - (blocks % 16)) + + dosfs_cmd = "mkdosfs -n boot -S 512 -C %s %d" % (rootfs, blocks) + exec_native_cmd(dosfs_cmd, native_sysroot) + + mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (rootfs, image_rootfs) + rc, out = exec_native_cmd(mcopy_cmd, native_sysroot) + if rc: + msger.error("ERROR: mcopy returned '%s' instead of 0 (which you probably don't want to ignore, use --debug for details)" % rc) + + chmod_cmd = "chmod 644 %s" % rootfs + exec_cmd(chmod_cmd) + + # get the rootfs size in the right units for kickstart (Mb) + du_cmd = "du -Lbms %s" % rootfs + out = exec_cmd(du_cmd) + rootfs_size = out.split()[0] + + self.set_size(rootfs_size) + self.set_source_file(rootfs) + + def prepare_rootfs_squashfs(self, cr_workdir, oe_builddir, rootfs_dir, + native_sysroot, pseudo): + """ + Prepare content for a squashfs rootfs partition. + """ + image_rootfs = rootfs_dir + rootfs = "%s/rootfs_%s.%s" % (cr_workdir, self.label ,self.fstype) + + squashfs_cmd = "mksquashfs %s %s -noappend" % \ + (image_rootfs, rootfs) + exec_native_cmd(pseudo + squashfs_cmd, native_sysroot) + + # get the rootfs size in the right units for kickstart (Mb) + du_cmd = "du -Lbms %s" % rootfs + out = exec_cmd(du_cmd) + rootfs_size = out.split()[0] + + self.size = rootfs_size + self.source_file = rootfs + + return 0 + + def prepare_empty_partition(self, cr_workdir, oe_builddir, native_sysroot): + """ + Prepare an empty partition. + """ + if self.fstype.startswith("ext"): + return self.prepare_empty_partition_ext(cr_workdir, oe_builddir, + native_sysroot) + elif self.fstype.startswith("btrfs"): + return self.prepare_empty_partition_btrfs(cr_workdir, oe_builddir, + native_sysroot) + elif self.fstype.startswith("vfat"): + return self.prepare_empty_partition_vfat(cr_workdir, oe_builddir, + native_sysroot) + elif self.fstype.startswith("squashfs"): + return self.prepare_empty_partition_squashfs(cr_workdir, oe_builddir, + native_sysroot) + + def prepare_empty_partition_ext(self, cr_workdir, oe_builddir, + native_sysroot): + """ + Prepare an empty ext2/3/4 partition. + """ + fs = "%s/fs_%s.%s" % (cr_workdir, self.label, self.fstype) + + dd_cmd = "dd if=/dev/zero of=%s bs=1M seek=%d count=0" % \ + (fs, self.size) + exec_cmd(dd_cmd) + + extra_imagecmd = "-i 8192" + + mkfs_cmd = "mkfs.%s -F %s %s" % (self.fstype, extra_imagecmd, fs) + (rc, out) = exec_native_cmd(mkfs_cmd, native_sysroot) + if rc: + msger.error("ERROR: mkfs.%s returned '%s' instead of 0 (which you probably don't want to ignore, use --debug for details)" % (self.fstype, rc)) + + self.source_file = fs + + return 0 + + def prepare_empty_partition_btrfs(self, cr_workdir, oe_builddir, + native_sysroot): + """ + Prepare an empty btrfs partition. + """ + fs = "%s/fs_%s.%s" % (cr_workdir, self.label, self.fstype) + + dd_cmd = "dd if=/dev/zero of=%s bs=1M seek=%d count=0" % \ + (fs, self.size) + exec_cmd(dd_cmd) + + mkfs_cmd = "mkfs.%s -b %d %s" % (self.fstype, self.size * 1024, rootfs) + (rc, out) = exec_native_cmd(mkfs_cmd, native_sysroot) + if rc: + msger.error("ERROR: mkfs.%s returned '%s' instead of 0 (which you probably don't want to ignore, use --debug for details)" % (self.fstype, rc)) + + mkfs_cmd = "mkfs.%s -F %s %s" % (self.fstype, extra_imagecmd, fs) + (rc, out) = exec_native_cmd(mkfs_cmd, native_sysroot) + if rc: + msger.error("ERROR: mkfs.%s returned '%s' instead of 0 (which you probably don't want to ignore, use --debug for details)" % (self.fstype, rc)) + + self.source_file = fs + + return 0 + + def prepare_empty_partition_vfat(self, cr_workdir, oe_builddir, + native_sysroot): + """ + Prepare an empty vfat partition. + """ + fs = "%s/fs_%s.%s" % (cr_workdir, self.label, self.fstype) + + blocks = self.size * 1024 + + dosfs_cmd = "mkdosfs -n boot -S 512 -C %s %d" % (fs, blocks) + exec_native_cmd(dosfs_cmd, native_sysroot) + + chmod_cmd = "chmod 644 %s" % fs + exec_cmd(chmod_cmd) + + self.source_file = fs + + return 0 + + def prepare_empty_partition_squashfs(self, cr_workdir, oe_builddir, + native_sysroot): + """ + Prepare an empty squashfs partition. + """ + msger.warning("Creating of an empty squashfs %s partition was attempted. " \ + "Proceeding as requested." % self.mountpoint) + + fs = "%s/fs_%s.%s" % (cr_workdir, self.label, self.fstype) + + # it is not possible to create a squashfs without source data, + # thus prepare an empty temp dir that is used as source + tmpdir = tempfile.mkdtemp() + + squashfs_cmd = "mksquashfs %s %s -noappend" % \ + (tmpdir, fs) + exec_native_cmd(squashfs_cmd, native_sysroot) + + os.rmdir(tmpdir) + + # get the rootfs size in the right units for kickstart (Mb) + du_cmd = "du -Lbms %s" % fs + out = exec_cmd(du_cmd) + fs_size = out.split()[0] + + self.size = fs_size + self.source_file = fs + + return 0 + + def prepare_swap_partition(self, cr_workdir, oe_builddir, native_sysroot): + """ + Prepare a swap partition. + """ + fs = "%s/fs.%s" % (cr_workdir, self.fstype) + + dd_cmd = "dd if=/dev/zero of=%s bs=1M seek=%d count=0" % \ + (fs, self.size) + exec_cmd(dd_cmd) + + import uuid + label_str = "" + if self.label: + label_str = "-L %s" % self.label + mkswap_cmd = "mkswap %s -U %s %s" % (label_str, str(uuid.uuid1()), fs) + exec_native_cmd(mkswap_cmd, native_sysroot) + + self.source_file = fs + + return 0 + +class Wic_Partition(Mic_Partition): + removedKeywords = Mic_Partition.removedKeywords + removedAttrs = Mic_Partition.removedAttrs + + def _getParser(self): + op = Mic_Partition._getParser(self) + # use specified source file to fill the partition + # and calculate partition size + op.add_option("--source", type="string", action="store", + dest="source", default=None) + # comma-separated list of param=value pairs + op.add_option("--sourceparams", type="string", action="store", + dest="sourceparams", default=None) + # use specified rootfs path to fill the partition + op.add_option("--rootfs-dir", type="string", action="store", + dest="rootfs", default=None) + return op diff --git a/scripts/lib/wic/kickstart/custom_commands/wicboot.py b/scripts/lib/wic/kickstart/custom_commands/wicboot.py new file mode 100644 index 0000000000..f1914169d8 --- /dev/null +++ b/scripts/lib/wic/kickstart/custom_commands/wicboot.py @@ -0,0 +1,57 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2014, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module provides the OpenEmbedded bootloader object definitions. +# +# AUTHORS +# Tom Zanussi +# + +from pykickstart.base import * +from pykickstart.errors import * +from pykickstart.options import * +from pykickstart.commands.bootloader import * + +from wic.kickstart.custom_commands.micboot import * + +class Wic_Bootloader(Mic_Bootloader): + def __init__(self, writePriority=10, appendLine="", driveorder=None, + forceLBA=False, location="", md5pass="", password="", + upgrade=False, menus=""): + Mic_Bootloader.__init__(self, writePriority, appendLine, driveorder, + forceLBA, location, md5pass, password, upgrade) + + self.source = "" + + def _getArgsAsStr(self): + retval = Mic_Bootloader._getArgsAsStr(self) + + if self.source: + retval += " --source=%s" % self.source + + return retval + + def _getParser(self): + op = Mic_Bootloader._getParser(self) + # use specified source plugin to implement bootloader-specific methods + op.add_option("--source", type="string", action="store", + dest="source", default=None) + return op + diff --git a/scripts/lib/wic/msger.py b/scripts/lib/wic/msger.py new file mode 100644 index 0000000000..9f557e7b9a --- /dev/null +++ b/scripts/lib/wic/msger.py @@ -0,0 +1,309 @@ +#!/usr/bin/env python -tt +# vim: ai ts=4 sts=4 et sw=4 +# +# Copyright (c) 2009, 2010, 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os,sys +import re +import time + +__ALL__ = ['set_mode', + 'get_loglevel', + 'set_loglevel', + 'set_logfile', + 'raw', + 'debug', + 'verbose', + 'info', + 'warning', + 'error', + 'ask', + 'pause', + ] + +# COLORs in ANSI +INFO_COLOR = 32 # green +WARN_COLOR = 33 # yellow +ERR_COLOR = 31 # red +ASK_COLOR = 34 # blue +NO_COLOR = 0 + +PREFIX_RE = re.compile('^<(.*?)>\s*(.*)', re.S) + +INTERACTIVE = True + +LOG_LEVEL = 1 +LOG_LEVELS = { + 'quiet': 0, + 'normal': 1, + 'verbose': 2, + 'debug': 3, + 'never': 4, + } + +LOG_FILE_FP = None +LOG_CONTENT = '' +CATCHERR_BUFFILE_FD = -1 +CATCHERR_BUFFILE_PATH = None +CATCHERR_SAVED_2 = -1 + +def _general_print(head, color, msg = None, stream = None, level = 'normal'): + global LOG_CONTENT + if not stream: + stream = sys.stdout + + if LOG_LEVELS[level] > LOG_LEVEL: + # skip + return + + # encode raw 'unicode' str to utf8 encoded str + if msg and isinstance(msg, unicode): + msg = msg.encode('utf-8', 'ignore') + + errormsg = '' + if CATCHERR_BUFFILE_FD > 0: + size = os.lseek(CATCHERR_BUFFILE_FD , 0, os.SEEK_END) + os.lseek(CATCHERR_BUFFILE_FD, 0, os.SEEK_SET) + errormsg = os.read(CATCHERR_BUFFILE_FD, size) + os.ftruncate(CATCHERR_BUFFILE_FD, 0) + + # append error msg to LOG + if errormsg: + LOG_CONTENT += errormsg + + # append normal msg to LOG + save_msg = msg.strip() if msg else None + if save_msg: + timestr = time.strftime("[%m/%d %H:%M:%S %Z] ", time.localtime()) + LOG_CONTENT += timestr + save_msg + '\n' + + if errormsg: + _color_print('', NO_COLOR, errormsg, stream, level) + + _color_print(head, color, msg, stream, level) + +def _color_print(head, color, msg, stream, level): + colored = True + if color == NO_COLOR or \ + not stream.isatty() or \ + os.getenv('ANSI_COLORS_DISABLED') is not None: + colored = False + + if head.startswith('\r'): + # need not \n at last + newline = False + else: + newline = True + + if colored: + head = '\033[%dm%s:\033[0m ' %(color, head) + if not newline: + # ESC cmd to clear line + head = '\033[2K' + head + else: + if head: + head += ': ' + if head.startswith('\r'): + head = head.lstrip() + newline = True + + if msg is not None: + if isinstance(msg, unicode): + msg = msg.encode('utf8', 'ignore') + + stream.write('%s%s' % (head, msg)) + if newline: + stream.write('\n') + + stream.flush() + +def _color_perror(head, color, msg, level = 'normal'): + if CATCHERR_BUFFILE_FD > 0: + _general_print(head, color, msg, sys.stdout, level) + else: + _general_print(head, color, msg, sys.stderr, level) + +def _split_msg(head, msg): + if isinstance(msg, list): + msg = '\n'.join(map(str, msg)) + + if msg.startswith('\n'): + # means print \n at first + msg = msg.lstrip() + head = '\n' + head + + elif msg.startswith('\r'): + # means print \r at first + msg = msg.lstrip() + head = '\r' + head + + m = PREFIX_RE.match(msg) + if m: + head += ' <%s>' % m.group(1) + msg = m.group(2) + + return head, msg + +def get_loglevel(): + return (k for k,v in LOG_LEVELS.items() if v==LOG_LEVEL).next() + +def set_loglevel(level): + global LOG_LEVEL + if level not in LOG_LEVELS: + # no effect + return + + LOG_LEVEL = LOG_LEVELS[level] + +def set_interactive(mode=True): + global INTERACTIVE + if mode: + INTERACTIVE = True + else: + INTERACTIVE = False + +def log(msg=''): + # log msg to LOG_CONTENT then save to logfile + global LOG_CONTENT + if msg: + LOG_CONTENT += msg + +def raw(msg=''): + _general_print('', NO_COLOR, msg) + +def info(msg): + head, msg = _split_msg('Info', msg) + _general_print(head, INFO_COLOR, msg) + +def verbose(msg): + head, msg = _split_msg('Verbose', msg) + _general_print(head, INFO_COLOR, msg, level = 'verbose') + +def warning(msg): + head, msg = _split_msg('Warning', msg) + _color_perror(head, WARN_COLOR, msg) + +def debug(msg): + head, msg = _split_msg('Debug', msg) + _color_perror(head, ERR_COLOR, msg, level = 'debug') + +def error(msg): + head, msg = _split_msg('Error', msg) + _color_perror(head, ERR_COLOR, msg) + sys.exit(1) + +def ask(msg, default=True): + _general_print('\rQ', ASK_COLOR, '') + try: + if default: + msg += '(Y/n) ' + else: + msg += '(y/N) ' + if INTERACTIVE: + while True: + repl = raw_input(msg) + if repl.lower() == 'y': + return True + elif repl.lower() == 'n': + return False + elif not repl.strip(): + # + return default + + # else loop + else: + if default: + msg += ' Y' + else: + msg += ' N' + _general_print('', NO_COLOR, msg) + + return default + except KeyboardInterrupt: + sys.stdout.write('\n') + sys.exit(2) + +def choice(msg, choices, default=0): + if default >= len(choices): + return None + _general_print('\rQ', ASK_COLOR, '') + try: + msg += " [%s] " % '/'.join(choices) + if INTERACTIVE: + while True: + repl = raw_input(msg) + if repl in choices: + return repl + elif not repl.strip(): + return choices[default] + else: + msg += choices[default] + _general_print('', NO_COLOR, msg) + + return choices[default] + except KeyboardInterrupt: + sys.stdout.write('\n') + sys.exit(2) + +def pause(msg=None): + if INTERACTIVE: + _general_print('\rQ', ASK_COLOR, '') + if msg is None: + msg = 'press to continue ...' + raw_input(msg) + +def set_logfile(fpath): + global LOG_FILE_FP + + def _savelogf(): + if LOG_FILE_FP: + fp = open(LOG_FILE_FP, 'w') + fp.write(LOG_CONTENT) + fp.close() + + if LOG_FILE_FP is not None: + warning('duplicate log file configuration') + + LOG_FILE_FP = fpath + + import atexit + atexit.register(_savelogf) + +def enable_logstderr(fpath): + global CATCHERR_BUFFILE_FD + global CATCHERR_BUFFILE_PATH + global CATCHERR_SAVED_2 + + if os.path.exists(fpath): + os.remove(fpath) + CATCHERR_BUFFILE_PATH = fpath + CATCHERR_BUFFILE_FD = os.open(CATCHERR_BUFFILE_PATH, os.O_RDWR|os.O_CREAT) + CATCHERR_SAVED_2 = os.dup(2) + os.dup2(CATCHERR_BUFFILE_FD, 2) + +def disable_logstderr(): + global CATCHERR_BUFFILE_FD + global CATCHERR_BUFFILE_PATH + global CATCHERR_SAVED_2 + + raw(msg = None) # flush message buffer and print it. + os.dup2(CATCHERR_SAVED_2, 2) + os.close(CATCHERR_SAVED_2) + os.close(CATCHERR_BUFFILE_FD) + os.unlink(CATCHERR_BUFFILE_PATH) + CATCHERR_BUFFILE_FD = -1 + CATCHERR_BUFFILE_PATH = None + CATCHERR_SAVED_2 = -1 diff --git a/scripts/lib/wic/plugin.py b/scripts/lib/wic/plugin.py new file mode 100644 index 0000000000..41a80175ca --- /dev/null +++ b/scripts/lib/wic/plugin.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os, sys + +from wic import msger +from wic import pluginbase +from wic.utils import errors +from wic.utils.oe.misc import * + +__ALL__ = ['PluginMgr', 'pluginmgr'] + +PLUGIN_TYPES = ["imager", "source"] + +PLUGIN_DIR = "/lib/wic/plugins" # relative to scripts +SCRIPTS_PLUGIN_DIR = "scripts" + PLUGIN_DIR + +class PluginMgr(object): + plugin_dirs = {} + + # make the manager class as singleton + _instance = None + def __new__(cls, *args, **kwargs): + if not cls._instance: + cls._instance = super(PluginMgr, cls).__new__(cls, *args, **kwargs) + + return cls._instance + + def __init__(self): + wic_path = os.path.dirname(__file__) + eos = wic_path.find('scripts') + len('scripts') + scripts_path = wic_path[:eos] + self.scripts_path = scripts_path + self.plugin_dir = scripts_path + PLUGIN_DIR + self.layers_path = None + + def _build_plugin_dir_list(self, dl, ptype): + if self.layers_path is None: + self.layers_path = get_bitbake_var("BBLAYERS") + layer_dirs = [] + + if self.layers_path is not None: + for layer_path in self.layers_path.split(): + path = os.path.join(layer_path, SCRIPTS_PLUGIN_DIR, ptype) + layer_dirs.append(path) + + path = os.path.join(dl, ptype) + layer_dirs.append(path) + + return layer_dirs + + def append_dirs(self, dirs): + for path in dirs: + self._add_plugindir(path) + + # load all the plugins AGAIN + self._load_all() + + def _add_plugindir(self, path): + path = os.path.abspath(os.path.expanduser(path)) + + if not os.path.isdir(path): + msger.debug("Plugin dir is not a directory or does not exist: %s"\ + % path) + return + + if path not in self.plugin_dirs: + self.plugin_dirs[path] = False + # the value True/False means "loaded" + + def _load_all(self): + for (pdir, loaded) in self.plugin_dirs.iteritems(): + if loaded: continue + + sys.path.insert(0, pdir) + for mod in [x[:-3] for x in os.listdir(pdir) if x.endswith(".py")]: + if mod and mod != '__init__': + if mod in sys.modules: + #self.plugin_dirs[pdir] = True + msger.warning("Module %s already exists, skip" % mod) + else: + try: + pymod = __import__(mod) + self.plugin_dirs[pdir] = True + msger.debug("Plugin module %s:%s imported"\ + % (mod, pymod.__file__)) + except ImportError, err: + msg = 'Failed to load plugin %s/%s: %s' \ + % (os.path.basename(pdir), mod, err) + msger.warning(msg) + + del(sys.path[0]) + + def get_plugins(self, ptype): + """ the return value is dict of name:class pairs """ + + if ptype not in PLUGIN_TYPES: + raise errors.CreatorError('%s is not valid plugin type' % ptype) + + plugins_dir = self._build_plugin_dir_list(self.plugin_dir, ptype) + + self.append_dirs(plugins_dir) + + return pluginbase.get_plugins(ptype) + + def get_source_plugins(self): + """ + Return list of available source plugins. + """ + plugins_dir = self._build_plugin_dir_list(self.plugin_dir, 'source') + + self.append_dirs(plugins_dir) + + plugins = [] + + for _source_name, klass in self.get_plugins('source').iteritems(): + plugins.append(_source_name) + + return plugins + + + def get_source_plugin_methods(self, source_name, methods): + """ + The methods param is a dict with the method names to find. On + return, the dict values will be filled in with pointers to the + corresponding methods. If one or more methods are not found, + None is returned. + """ + return_methods = None + for _source_name, klass in self.get_plugins('source').iteritems(): + if _source_name == source_name: + for _method_name in methods.keys(): + if not hasattr(klass, _method_name): + msger.warning("Unimplemented %s source interface for: %s"\ + % (_method_name, _source_name)) + return None + func = getattr(klass, _method_name) + methods[_method_name] = func + return_methods = methods + return return_methods + +pluginmgr = PluginMgr() diff --git a/scripts/lib/wic/pluginbase.py b/scripts/lib/wic/pluginbase.py new file mode 100644 index 0000000000..d63e34e089 --- /dev/null +++ b/scripts/lib/wic/pluginbase.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os +import shutil +from wic import msger +from wic.utils import errors + +class _Plugin(object): + class __metaclass__(type): + def __init__(cls, name, bases, attrs): + if not hasattr(cls, 'plugins'): + cls.plugins = {} + + elif 'wic_plugin_type' in attrs: + if attrs['wic_plugin_type'] not in cls.plugins: + cls.plugins[attrs['wic_plugin_type']] = {} + + elif hasattr(cls, 'wic_plugin_type') and 'name' in attrs: + cls.plugins[cls.wic_plugin_type][attrs['name']] = cls + + def show_plugins(cls): + for cls in cls.plugins[cls.wic_plugin_type]: + print cls + + def get_plugins(cls): + return cls.plugins + + +class ImagerPlugin(_Plugin): + wic_plugin_type = "imager" + + +class SourcePlugin(_Plugin): + wic_plugin_type = "source" + """ + The methods that can be implemented by --source plugins. + + Any methods not implemented in a subclass inherit these. + """ + + @classmethod + def do_install_pkgs(self, part, creator, cr_workdir, oe_builddir, rootfs_dir, + bootimg_dir, kernel_dir, native_sysroot): + """ + Called before partitions have been prepared and assembled into a + disk image. Install packages into rootfs + """ + msger.debug("SourcePlugin: do_install_pkgs: part %s" % part) + + @classmethod + def do_install_disk(self, disk, disk_name, cr, workdir, oe_builddir, + bootimg_dir, kernel_dir, native_sysroot): + """ + Called after all partitions have been prepared and assembled into a + disk image. This provides a hook to allow finalization of a + disk image e.g. to write an MBR to it. + """ + msger.debug("SourcePlugin: do_install_disk: disk: %s" % disk_name) + + @classmethod + def do_stage_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + native_sysroot): + """ + Special content staging hook called before do_prepare_partition(), + normally empty. + + Typically, a partition will just use the passed-in parame e.g + straight bootimg_dir, etc, but in some cases, things need to + be more tailored e.g. to use a deploy dir + /boot, etc. This + hook allows those files to be staged in a customized fashion. + Not that get_bitbake_var() allows you to acces non-standard + variables that you might want to use for this. + """ + msger.debug("SourcePlugin: do_stage_partition: part: %s" % part) + + @classmethod + def do_configure_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + native_sysroot): + """ + Called before do_prepare_partition(), typically used to create + custom configuration files for a partition, for example + syslinux or grub config files. + """ + msger.debug("SourcePlugin: do_configure_partition: part: %s" % part) + + @classmethod + def do_prepare_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, rootfs_dir, + native_sysroot): + """ + Called to do the actual content population for a partition i.e. it + 'prepares' the partition to be incorporated into the image. + """ + msger.debug("SourcePlugin: do_prepare_partition: part: %s" % part) + +def get_plugins(typen): + ps = ImagerPlugin.get_plugins() + if typen in ps: + return ps[typen] + else: + return None + +__all__ = ['ImagerPlugin', 'SourcePlugin', 'get_plugins'] diff --git a/scripts/lib/wic/plugins/imager/direct_plugin.py b/scripts/lib/wic/plugins/imager/direct_plugin.py new file mode 100644 index 0000000000..5601c3f1c9 --- /dev/null +++ b/scripts/lib/wic/plugins/imager/direct_plugin.py @@ -0,0 +1,98 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'direct' imager plugin class for 'wic' +# +# AUTHORS +# Tom Zanussi +# + +import os +import shutil +import re +import tempfile + +from wic import msger +from wic.utils import misc, fs_related, errors, runner, cmdln +from wic.conf import configmgr +from wic.plugin import pluginmgr + +import wic.imager.direct as direct +from wic.pluginbase import ImagerPlugin + +class DirectPlugin(ImagerPlugin): + name = 'direct' + + @classmethod + def __rootfs_dir_to_dict(self, rootfs_dirs): + """ + Gets a string that contain 'connection=dir' splitted by + space and return a dict + """ + krootfs_dir = {} + for rootfs_dir in rootfs_dirs.split(' '): + k, v = rootfs_dir.split('=') + krootfs_dir[k] = v + + return krootfs_dir + + @classmethod + def do_create(self, subcmd, opts, *args): + """ + Create direct image, called from creator as 'direct' cmd + """ + if len(args) != 7: + raise errors.Usage("Extra arguments given") + + native_sysroot = args[0] + kernel_dir = args[1] + bootimg_dir = args[2] + rootfs_dir = args[3] + + creatoropts = configmgr.create + ksconf = args[4] + + image_output_dir = args[5] + oe_builddir = args[6] + + krootfs_dir = self.__rootfs_dir_to_dict(rootfs_dir) + + configmgr._ksconf = ksconf + + creator = direct.DirectImageCreator(oe_builddir, + image_output_dir, + krootfs_dir, + bootimg_dir, + kernel_dir, + native_sysroot, + creatoropts) + + try: + creator.create() + creator.assemble() + creator.finalize() + creator.print_outimage_info() + + except errors.CreatorError: + raise + finally: + creator.cleanup() + + return 0 diff --git a/scripts/lib/wic/plugins/source/bootimg-efi.py b/scripts/lib/wic/plugins/source/bootimg-efi.py new file mode 100644 index 0000000000..e4067b6dbf --- /dev/null +++ b/scripts/lib/wic/plugins/source/bootimg-efi.py @@ -0,0 +1,236 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2014, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'bootimg-efi' source plugin class for 'wic' +# +# AUTHORS +# Tom Zanussi +# + +import os +import shutil +import re +import tempfile + +from wic import kickstart, msger +from wic.utils import misc, fs_related, errors, runner, cmdln +from wic.conf import configmgr +from wic.plugin import pluginmgr +import wic.imager.direct as direct +from wic.pluginbase import SourcePlugin +from wic.utils.oe.misc import * +from wic.imager.direct import DirectImageCreator + +class BootimgEFIPlugin(SourcePlugin): + name = 'bootimg-efi' + + @classmethod + def do_configure_grubefi(self, hdddir, cr, cr_workdir): + """ + Create loader-specific (grub-efi) config + """ + splash = os.path.join(cr_workdir, "/EFI/boot/splash.jpg") + if os.path.exists(splash): + splashline = "menu background splash.jpg" + else: + splashline = "" + + (rootdev, root_part_uuid) = cr._get_boot_config() + options = cr.ks.handler.bootloader.appendLine + + grubefi_conf = "" + grubefi_conf += "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n" + grubefi_conf += "default=boot\n" + timeout = kickstart.get_timeout(cr.ks) + if not timeout: + timeout = 0 + grubefi_conf += "timeout=%s\n" % timeout + grubefi_conf += "menuentry 'boot'{\n" + + kernel = "/bzImage" + + if cr._ptable_format == 'msdos': + rootstr = rootdev + else: + raise ImageError("Unsupported partition table format found") + + grubefi_conf += "linux %s root=%s rootwait %s\n" \ + % (kernel, rootstr, options) + grubefi_conf += "}\n" + if splashline: + syslinux_conf += "%s\n" % splashline + + msger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg" \ + % cr_workdir) + cfg = open("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, "w") + cfg.write(grubefi_conf) + cfg.close() + + @classmethod + def do_configure_gummiboot(self, hdddir, cr, cr_workdir): + """ + Create loader-specific (gummiboot) config + """ + install_cmd = "install -d %s/loader" % hdddir + exec_cmd(install_cmd) + + install_cmd = "install -d %s/loader/entries" % hdddir + exec_cmd(install_cmd) + + (rootdev, root_part_uuid) = cr._get_boot_config() + options = cr.ks.handler.bootloader.appendLine + + timeout = kickstart.get_timeout(cr.ks) + if not timeout: + timeout = 0 + + loader_conf = "" + loader_conf += "default boot\n" + loader_conf += "timeout %d\n" % timeout + + msger.debug("Writing gummiboot config %s/hdd/boot/loader/loader.conf" \ + % cr_workdir) + cfg = open("%s/hdd/boot/loader/loader.conf" % cr_workdir, "w") + cfg.write(loader_conf) + cfg.close() + + kernel = "/bzImage" + + if cr._ptable_format == 'msdos': + rootstr = rootdev + else: + raise ImageError("Unsupported partition table format found") + + boot_conf = "" + boot_conf += "title boot\n" + boot_conf += "linux %s\n" % kernel + boot_conf += "options LABEL=Boot root=%s %s\n" \ + % (rootstr, options) + + msger.debug("Writing gummiboot config %s/hdd/boot/loader/entries/boot.conf" \ + % cr_workdir) + cfg = open("%s/hdd/boot/loader/entries/boot.conf" % cr_workdir, "w") + cfg.write(boot_conf) + cfg.close() + + + @classmethod + def do_configure_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + native_sysroot): + """ + Called before do_prepare_partition(), creates loader-specific config + """ + hdddir = "%s/hdd/boot" % cr_workdir + rm_cmd = "rm -rf %s" % cr_workdir + exec_cmd(rm_cmd) + + install_cmd = "install -d %s/EFI/BOOT" % hdddir + exec_cmd(install_cmd) + + try: + if source_params['loader'] == 'grub-efi': + self.do_configure_grubefi(hdddir, cr, cr_workdir) + elif source_params['loader'] == 'gummiboot': + self.do_configure_gummiboot(hdddir, cr, cr_workdir) + else: + msger.error("unrecognized bootimg-efi loader: %s" % source_params['loader']) + except KeyError: + msger.error("bootimg-efi requires a loader, none specified") + + + @classmethod + def do_prepare_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + rootfs_dir, native_sysroot): + """ + Called to do the actual content population for a partition i.e. it + 'prepares' the partition to be incorporated into the image. + In this case, prepare content for an EFI (grub) boot partition. + """ + if not bootimg_dir: + bootimg_dir = get_bitbake_var("HDDDIR") + if not bootimg_dir: + msger.error("Couldn't find HDDDIR, exiting\n") + # just so the result notes display it + cr.set_bootimg_dir(bootimg_dir) + + staging_kernel_dir = kernel_dir + + hdddir = "%s/hdd/boot" % cr_workdir + + install_cmd = "install -m 0644 %s/bzImage %s/bzImage" % \ + (staging_kernel_dir, hdddir) + exec_cmd(install_cmd) + + try: + if source_params['loader'] == 'grub-efi': + shutil.copyfile("%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir, + "%s/grub.cfg" % cr_workdir) + cp_cmd = "cp %s/EFI/BOOT/* %s/EFI/BOOT" % (bootimg_dir, hdddir) + exec_cmd(cp_cmd, True) + shutil.move("%s/grub.cfg" % cr_workdir, + "%s/hdd/boot/EFI/BOOT/grub.cfg" % cr_workdir) + elif source_params['loader'] == 'gummiboot': + cp_cmd = "cp %s/EFI/BOOT/* %s/EFI/BOOT" % (bootimg_dir, hdddir) + exec_cmd(cp_cmd, True) + else: + msger.error("unrecognized bootimg-efi loader: %s" % source_params['loader']) + except KeyError: + msger.error("bootimg-efi requires a loader, none specified") + + du_cmd = "du -bks %s" % hdddir + out = exec_cmd(du_cmd) + blocks = int(out.split()[0]) + + extra_blocks = part.get_extra_block_count(blocks) + + if extra_blocks < BOOTDD_EXTRA_SPACE: + extra_blocks = BOOTDD_EXTRA_SPACE + + blocks += extra_blocks + + msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \ + (extra_blocks, part.mountpoint, blocks)) + + # Ensure total sectors is an integral number of sectors per + # track or mcopy will complain. Sectors are 512 bytes, and we + # generate images with 32 sectors per track. This calculation is + # done in blocks, thus the mod by 16 instead of 32. + blocks += (16 - (blocks % 16)) + + # dosfs image, created by mkdosfs + bootimg = "%s/boot.img" % cr_workdir + + dosfs_cmd = "mkdosfs -n efi -C %s %d" % (bootimg, blocks) + exec_native_cmd(dosfs_cmd, native_sysroot) + + mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) + exec_native_cmd(mcopy_cmd, native_sysroot) + + chmod_cmd = "chmod 644 %s" % bootimg + exec_cmd(chmod_cmd) + + du_cmd = "du -Lbms %s" % bootimg + out = exec_cmd(du_cmd) + bootimg_size = out.split()[0] + + part.set_size(bootimg_size) + part.set_source_file(bootimg) diff --git a/scripts/lib/wic/plugins/source/bootimg-partition.py b/scripts/lib/wic/plugins/source/bootimg-partition.py new file mode 100644 index 0000000000..564118ad8b --- /dev/null +++ b/scripts/lib/wic/plugins/source/bootimg-partition.py @@ -0,0 +1,115 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'bootimg-partition' source plugin class for +# 'wic'. The plugin creates an image of boot partition, copying over +# files listed in IMAGE_BOOT_FILES bitbake variable. +# +# AUTHORS +# Maciej Borzecki +# + +import os +import re + +from wic import msger +from wic.pluginbase import SourcePlugin +from wic.utils.oe.misc import * + +class BootimgPartitionPlugin(SourcePlugin): + name = 'bootimg-partition' + + @classmethod + def do_install_disk(self, disk, disk_name, cr, workdir, oe_builddir, + bootimg_dir, kernel_dir, native_sysroot): + """ + Called after all partitions have been prepared and assembled into a + disk image. Do nothing. + """ + pass + + @classmethod + def do_configure_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + native_sysroot): + """ + Called before do_prepare_partition(). Possibly prepare + configuration files of some sort. + + """ + pass + + @classmethod + def do_prepare_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + rootfs_dir, native_sysroot): + """ + Called to do the actual content population for a partition i.e. it + 'prepares' the partition to be incorporated into the image. + In this case, does the following: + - sets up a vfat partition + - copies all files listed in IMAGE_BOOT_FILES variable + """ + hdddir = "%s/boot" % cr_workdir + rm_cmd = "rm -rf %s" % cr_workdir + exec_cmd(rm_cmd) + + install_cmd = "install -d %s" % hdddir + exec_cmd(install_cmd) + + if not bootimg_dir: + bootimg_dir = get_bitbake_var("DEPLOY_DIR_IMAGE") + if not bootimg_dir: + msger.error("Couldn't find DEPLOY_DIR_IMAGE, exiting\n") + + msger.debug('Bootimg dir: %s' % bootimg_dir) + + boot_files = get_bitbake_var("IMAGE_BOOT_FILES") + + if not boot_files: + msger.error('No boot files defined, IMAGE_BOOT_FILES unset') + + msger.debug('Boot files: %s' % boot_files) + + # list of tuples (src_name, dst_name) + deploy_files = [] + for src_entry in re.findall(r'[\w;\-\./]+', boot_files): + if ';' in src_entry: + dst_entry = tuple(src_entry.split(';')) + if not dst_entry[0] or not dst_entry[1]: + msger.error('Malformed boot file entry: %s' % (src_entry)) + else: + dst_entry = (src_entry, src_entry) + + msger.debug('Destination entry: %r' % (dst_entry,)) + deploy_files.append(dst_entry) + + for deploy_entry in deploy_files: + src, dst = deploy_entry + src_path = os.path.join(bootimg_dir, src) + dst_path = os.path.join(hdddir, dst) + + msger.debug('Install %s as %s' % (os.path.basename(src_path), + dst_path)) + install_cmd = "install -m 0644 -D %s %s" \ + % (src_path, dst_path) + exec_cmd(install_cmd) + + msger.debug('Prepare boot partition using rootfs in %s' % (hdddir)) + part.prepare_rootfs(cr_workdir, oe_builddir, hdddir, + native_sysroot) + diff --git a/scripts/lib/wic/plugins/source/bootimg-pcbios.py b/scripts/lib/wic/plugins/source/bootimg-pcbios.py new file mode 100644 index 0000000000..8a1aca1ad1 --- /dev/null +++ b/scripts/lib/wic/plugins/source/bootimg-pcbios.py @@ -0,0 +1,200 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2014, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'bootimg-pcbios' source plugin class for 'wic' +# +# AUTHORS +# Tom Zanussi +# + +import os +import shutil +import re +import tempfile + +from wic import kickstart, msger +from wic.utils import misc, fs_related, errors, runner, cmdln +from wic.conf import configmgr +from wic.plugin import pluginmgr +import wic.imager.direct as direct +from wic.pluginbase import SourcePlugin +from wic.utils.oe.misc import * +from wic.imager.direct import DirectImageCreator + +class BootimgPcbiosPlugin(SourcePlugin): + name = 'bootimg-pcbios' + + @classmethod + def do_install_disk(self, disk, disk_name, cr, workdir, oe_builddir, + bootimg_dir, kernel_dir, native_sysroot): + """ + Called after all partitions have been prepared and assembled into a + disk image. In this case, we install the MBR. + """ + mbrfile = "%s/syslinux/" % bootimg_dir + if cr._ptable_format == 'msdos': + mbrfile += "mbr.bin" + + if not os.path.exists(mbrfile): + msger.error("Couldn't find %s. If using the -e option, do you have the right MACHINE set in local.conf? If not, is the bootimg_dir path correct?" % mbrfile) + + full_path = cr._full_path(workdir, disk_name, "direct") + msger.debug("Installing MBR on disk %s as %s with size %s bytes" \ + % (disk_name, full_path, disk['min_size'])) + + rc = runner.show(['dd', 'if=%s' % mbrfile, + 'of=%s' % full_path, 'conv=notrunc']) + if rc != 0: + raise ImageError("Unable to set MBR to %s" % full_path) + + @classmethod + def do_configure_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + native_sysroot): + """ + Called before do_prepare_partition(), creates syslinux config + """ + hdddir = "%s/hdd/boot" % cr_workdir + rm_cmd = "rm -rf " + cr_workdir + exec_cmd(rm_cmd) + + install_cmd = "install -d %s" % hdddir + exec_cmd(install_cmd) + + splash = os.path.join(cr_workdir, "/hdd/boot/splash.jpg") + if os.path.exists(splash): + splashline = "menu background splash.jpg" + else: + splashline = "" + + (rootdev, root_part_uuid) = cr._get_boot_config() + options = cr.ks.handler.bootloader.appendLine + + syslinux_conf = "" + syslinux_conf += "PROMPT 0\n" + timeout = kickstart.get_timeout(cr.ks) + if not timeout: + timeout = 0 + syslinux_conf += "TIMEOUT " + str(timeout) + "\n" + syslinux_conf += "\n" + syslinux_conf += "ALLOWOPTIONS 1\n" + syslinux_conf += "SERIAL 0 115200\n" + syslinux_conf += "\n" + if splashline: + syslinux_conf += "%s\n" % splashline + syslinux_conf += "DEFAULT boot\n" + syslinux_conf += "LABEL boot\n" + + kernel = "/vmlinuz" + syslinux_conf += "KERNEL " + kernel + "\n" + + if cr._ptable_format == 'msdos': + rootstr = rootdev + else: + raise ImageError("Unsupported partition table format found") + + syslinux_conf += "APPEND label=boot root=%s %s\n" % (rootstr, options) + + msger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg" \ + % cr_workdir) + cfg = open("%s/hdd/boot/syslinux.cfg" % cr_workdir, "w") + cfg.write(syslinux_conf) + cfg.close() + + @classmethod + def do_prepare_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + rootfs_dir, native_sysroot): + """ + Called to do the actual content population for a partition i.e. it + 'prepares' the partition to be incorporated into the image. + In this case, prepare content for legacy bios boot partition. + """ + def _has_syslinux(dir): + if dir: + syslinux = "%s/syslinux" % dir + if os.path.exists(syslinux): + return True + return False + + if not _has_syslinux(bootimg_dir): + bootimg_dir = get_bitbake_var("STAGING_DATADIR") + if not bootimg_dir: + msger.error("Couldn't find STAGING_DATADIR, exiting\n") + if not _has_syslinux(bootimg_dir): + msger.error("Please build syslinux first\n") + # just so the result notes display it + cr.set_bootimg_dir(bootimg_dir) + + staging_kernel_dir = kernel_dir + + hdddir = "%s/hdd/boot" % cr_workdir + + install_cmd = "install -m 0644 %s/bzImage %s/vmlinuz" \ + % (staging_kernel_dir, hdddir) + exec_cmd(install_cmd) + + install_cmd = "install -m 444 %s/syslinux/ldlinux.sys %s/ldlinux.sys" \ + % (bootimg_dir, hdddir) + exec_cmd(install_cmd) + + du_cmd = "du -bks %s" % hdddir + out = exec_cmd(du_cmd) + blocks = int(out.split()[0]) + + extra_blocks = part.get_extra_block_count(blocks) + + if extra_blocks < BOOTDD_EXTRA_SPACE: + extra_blocks = BOOTDD_EXTRA_SPACE + + blocks += extra_blocks + + msger.debug("Added %d extra blocks to %s to get to %d total blocks" % \ + (extra_blocks, part.mountpoint, blocks)) + + # Ensure total sectors is an integral number of sectors per + # track or mcopy will complain. Sectors are 512 bytes, and we + # generate images with 32 sectors per track. This calculation is + # done in blocks, thus the mod by 16 instead of 32. + blocks += (16 - (blocks % 16)) + + # dosfs image, created by mkdosfs + bootimg = "%s/boot.img" % cr_workdir + + dosfs_cmd = "mkdosfs -n boot -S 512 -C %s %d" % (bootimg, blocks) + exec_native_cmd(dosfs_cmd, native_sysroot) + + mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (bootimg, hdddir) + exec_native_cmd(mcopy_cmd, native_sysroot) + + syslinux_cmd = "syslinux %s" % bootimg + exec_native_cmd(syslinux_cmd, native_sysroot) + + chmod_cmd = "chmod 644 %s" % bootimg + exec_cmd(chmod_cmd) + + du_cmd = "du -Lbms %s" % bootimg + out = exec_cmd(du_cmd) + bootimg_size = out.split()[0] + + part.set_size(bootimg_size) + part.set_source_file(bootimg) + + diff --git a/scripts/lib/wic/plugins/source/rootfs.py b/scripts/lib/wic/plugins/source/rootfs.py new file mode 100644 index 0000000000..a432a18705 --- /dev/null +++ b/scripts/lib/wic/plugins/source/rootfs.py @@ -0,0 +1,92 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2014, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'rootfs' source plugin class for 'wic' +# +# AUTHORS +# Tom Zanussi +# Joao Henrique Ferreira de Freitas +# + +import os +import shutil +import re +import tempfile + +from wic import kickstart, msger +from wic.utils import misc, fs_related, errors, runner, cmdln +from wic.conf import configmgr +from wic.plugin import pluginmgr +import wic.imager.direct as direct +from wic.pluginbase import SourcePlugin +from wic.utils.oe.misc import * +from wic.imager.direct import DirectImageCreator + +class RootfsPlugin(SourcePlugin): + name = 'rootfs' + + @staticmethod + def __get_rootfs_dir(rootfs_dir): + if os.path.isdir(rootfs_dir): + return rootfs_dir + + bitbake_env_lines = find_bitbake_env_lines(rootfs_dir) + if not bitbake_env_lines: + msg = "Couldn't get bitbake environment, exiting." + msger.error(msg) + + image_rootfs_dir = find_artifact(bitbake_env_lines, "IMAGE_ROOTFS") + if not os.path.isdir(image_rootfs_dir): + msg = "No valid artifact IMAGE_ROOTFS from image named" + msg += " %s has been found at %s, exiting.\n" % \ + (rootfs_dir, image_rootfs_dir) + msger.error(msg) + + return image_rootfs_dir + + @classmethod + def do_prepare_partition(self, part, source_params, cr, cr_workdir, + oe_builddir, bootimg_dir, kernel_dir, + krootfs_dir, native_sysroot): + """ + Called to do the actual content population for a partition i.e. it + 'prepares' the partition to be incorporated into the image. + In this case, prepare content for legacy bios boot partition. + """ + if part.rootfs is None: + if not 'ROOTFS_DIR' in krootfs_dir: + msg = "Couldn't find --rootfs-dir, exiting" + msger.error(msg) + rootfs_dir = krootfs_dir['ROOTFS_DIR'] + else: + if part.rootfs in krootfs_dir: + rootfs_dir = krootfs_dir[part.rootfs] + elif part.rootfs: + rootfs_dir = part.rootfs + else: + msg = "Couldn't find --rootfs-dir=%s connection" + msg += " or it is not a valid path, exiting" + msger.error(msg % part.rootfs) + + real_rootfs_dir = self.__get_rootfs_dir(rootfs_dir) + + part.set_rootfs(real_rootfs_dir) + part.prepare_rootfs(cr_workdir, oe_builddir, real_rootfs_dir, native_sysroot) + diff --git a/scripts/lib/wic/plugins/source/uboot.py b/scripts/lib/wic/plugins/source/uboot.py new file mode 100644 index 0000000000..57cb3cf8fe --- /dev/null +++ b/scripts/lib/wic/plugins/source/uboot.py @@ -0,0 +1,173 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2014, Enea AB. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the 'uboot' source plugin class for 'wic' +# +# AUTHORS +# Adrian Calianu +# + +import os +import shutil +import re +import tempfile + +from mic import kickstart, chroot, msger +from mic.utils import misc, fs_related, errors, runner, cmdln +from mic.conf import configmgr +from mic.plugin import pluginmgr +from mic.utils.partitionedfs import PartitionedMount +import mic.imager.direct as direct +from mic.pluginbase import SourcePlugin +from mic.utils.oe.misc import * +from mic.imager.direct import DirectImageCreator + +def create_local_rootfs(part, creator, cr_workdir, krootfs_dir, native_sysroot): + # In order to have a full control over rootfs we will make a local copy under workdir + # and change rootfs_dir to new location. + # In this way we can install more than one ROOTFS_DIRs and/or use + # an empty rootfs to install packages, so a rootfs could be generated only from pkgs + # TBD: create workdir/rootfs ; copy rootfs-> workdir/rootfs; set rootfs=workdir/rootfs + + cr_workdir = os.path.abspath(cr_workdir) + new_rootfs_dir = "%s/rootfs_%s" % (cr_workdir, creator.name) + + rootfs_exists = 1 + if part.rootfs is None: + if not 'ROOTFS_DIR' in krootfs_dir: + msg = "Couldn't find --rootfs-dir, exiting, " + msger.info(msg) + rootfs_exists = 0 + rootfs_dir = krootfs_dir['ROOTFS_DIR'] + creator.rootfs_dir['ROOTFS_DIR'] = new_rootfs_dir + else: + if part.rootfs in krootfs_dir: + rootfs_dir = krootfs_dir[part.rootfs] + creator.rootfs_dir[part.rootfs] = new_rootfs_dir + elif os.path.isdir(part.rootfs): + rootfs_dir = part.rootfs + part.rootfs = new_rootfs_dir + else: + msg = "Couldn't find --rootfs-dir=%s connection" + msg += " or it is not a valid path, exiting" + msger.info(msg % part.rootfs) + rootfs_exists = 0 + creator.rootfs_dir['ROOTFS_DIR'] = new_rootfs_dir + + pseudox = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot + pseudox += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % new_rootfs_dir + pseudox += "export PSEUDO_PASSWD=%s;" % new_rootfs_dir + pseudox += "export PSEUDO_NOSYMLINKEXP=1;" + pseudox += "%s/usr/bin/pseudo " % native_sysroot + + mkdir_cmd = "mkdir %s" % (new_rootfs_dir) + # rc, out = exec_native_cmd(pseudox + mkdir_cmd, native_sysroot) + rc, out = exec_cmd(mkdir_cmd, True) + + if rootfs_exists == 1 and os.path.isdir(rootfs_dir): + defpath = os.environ['PATH'] + os.environ['PATH'] = native_sysroot + "/usr/bin/" + ":/bin:/usr/bin:" + + rootfs_dir = os.path.abspath(rootfs_dir) + + pseudoc = "export PSEUDO_PREFIX=%s/usr;" % native_sysroot + pseudoc += "export PSEUDO_LOCALSTATEDIR=%s/../pseudo;" % rootfs_dir + pseudoc += "export PSEUDO_PASSWD=%s;" % rootfs_dir + pseudoc += "export PSEUDO_NOSYMLINKEXP=1;" + pseudoc += "%s/usr/bin/pseudo " % native_sysroot + + tarc_cmd = "tar cvpf %s/rootfs.tar -C %s ." % (cr_workdir, rootfs_dir) + rc, out = exec_native_cmd(pseudoc + tarc_cmd, native_sysroot) + + tarx_cmd = "tar xpvf %s/rootfs.tar -C %s" % (cr_workdir, new_rootfs_dir) + rc, out = exec_native_cmd(pseudox + tarx_cmd, native_sysroot) + + rm_cmd = "rm %s/rootfs.tar" % cr_workdir + rc, out = exec_cmd(rm_cmd, True) + + os.environ['PATH'] += defpath + ":" + native_sysroot + "/usr/bin/" + + return new_rootfs_dir + +class UBootPlugin(SourcePlugin): + name = 'uboot' + + @classmethod + def do_install_pkgs(self, part, creator, cr_workdir, oe_builddir, krootfs_dir, + bootimg_dir, kernel_dir, native_sysroot): + """ + Called before all partitions have been prepared and assembled into a + disk image. Intall packages based on wic configuration. + """ + + # set new rootfs_dir + rootfs_dir = create_local_rootfs(part, creator, cr_workdir, krootfs_dir, native_sysroot) + + # wks file parsing + packages = kickstart.get_packages(creator.ks) + + # wic.conf file parsing = found under 'creator' + local_pkgs_path = creator._local_pkgs_path + repourl = creator.repourl + pkgmgr = creator.pkgmgr_name + + # install packages + if packages and pkgmgr in ["opkg"]: + if len(repourl) > 0 : + part.install_pkgs_ipk(cr_workdir, oe_builddir, rootfs_dir, native_sysroot, + packages, repourl) + else: + msger.error("No packages repository provided in wic.conf") + + @classmethod + def do_prepare_partition(self, part, cr, cr_workdir, oe_builddir, bootimg_dir, + kernel_dir, krootfs_dir, native_sysroot): + """ + Called to do the actual content population for a partition i.e. it + 'prepares' the partition to be incorporated into the image. + In this case, prepare content for legacy bios boot partition. + """ + if part.rootfs is None: + if not 'ROOTFS_DIR' in krootfs_dir: + msg = "Couldn't find --rootfs-dir, exiting" + msger.error(msg) + rootfs_dir = krootfs_dir['ROOTFS_DIR'] + else: + if part.rootfs in krootfs_dir: + rootfs_dir = krootfs_dir[part.rootfs] + elif os.path.isdir(part.rootfs): + rootfs_dir = part.rootfs + else: + msg = "Couldn't find --rootfs-dir=%s connection" + msg += " or it is not a valid path, exiting" + msger.error(msg % part.rootfs) + + part.set_rootfs(rootfs_dir) + + # change partition label wich will reflect into the final rootfs image name + part.label = "%s_%s" % (part.label, cr.name) + + defpath = os.environ['PATH'] + os.environ['PATH'] = native_sysroot + "/usr/bin/" + ":/bin:/usr/bin:" + + part.prepare_rootfs(cr_workdir, oe_builddir, rootfs_dir, native_sysroot) + part.prepare_for_uboot(cr.target_arch,cr_workdir, oe_builddir, rootfs_dir, native_sysroot) + + os.environ['PATH'] += defpath + ":" + native_sysroot + "/usr/bin/" diff --git a/scripts/lib/wic/test b/scripts/lib/wic/test new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/scripts/lib/wic/test @@ -0,0 +1 @@ +test diff --git a/scripts/lib/wic/utils/__init__.py b/scripts/lib/wic/utils/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/lib/wic/utils/cmdln.py b/scripts/lib/wic/utils/cmdln.py new file mode 100644 index 0000000000..b099473ee4 --- /dev/null +++ b/scripts/lib/wic/utils/cmdln.py @@ -0,0 +1,1586 @@ +#!/usr/bin/env python +# Copyright (c) 2002-2007 ActiveState Software Inc. +# License: MIT (see LICENSE.txt for license details) +# Author: Trent Mick +# Home: http://trentm.com/projects/cmdln/ + +"""An improvement on Python's standard cmd.py module. + +As with cmd.py, this module provides "a simple framework for writing +line-oriented command intepreters." This module provides a 'RawCmdln' +class that fixes some design flaws in cmd.Cmd, making it more scalable +and nicer to use for good 'cvs'- or 'svn'-style command line interfaces +or simple shells. And it provides a 'Cmdln' class that add +optparse-based option processing. Basically you use it like this: + + import cmdln + + class MySVN(cmdln.Cmdln): + name = "svn" + + @cmdln.alias('stat', 'st') + @cmdln.option('-v', '--verbose', action='store_true' + help='print verbose information') + def do_status(self, subcmd, opts, *paths): + print "handle 'svn status' command" + + #... + + if __name__ == "__main__": + shell = MySVN() + retval = shell.main() + sys.exit(retval) + +See the README.txt or for more +details. +""" + +__version_info__ = (1, 1, 2) +__version__ = '.'.join(map(str, __version_info__)) + +import os +import sys +import re +import cmd +import optparse +from pprint import pprint +import sys + + + + +#---- globals + +LOOP_ALWAYS, LOOP_NEVER, LOOP_IF_EMPTY = range(3) + +# An unspecified optional argument when None is a meaningful value. +_NOT_SPECIFIED = ("Not", "Specified") + +# Pattern to match a TypeError message from a call that +# failed because of incorrect number of arguments (see +# Python/getargs.c). +_INCORRECT_NUM_ARGS_RE = re.compile( + r"(takes [\w ]+ )(\d+)( arguments? \()(\d+)( given\))") + + + +#---- exceptions + +class CmdlnError(Exception): + """A cmdln.py usage error.""" + def __init__(self, msg): + self.msg = msg + def __str__(self): + return self.msg + +class CmdlnUserError(Exception): + """An error by a user of a cmdln-based tool/shell.""" + pass + + + +#---- public methods and classes + +def alias(*aliases): + """Decorator to add aliases for Cmdln.do_* command handlers. + + Example: + class MyShell(cmdln.Cmdln): + @cmdln.alias("!", "sh") + def do_shell(self, argv): + #...implement 'shell' command + """ + def decorate(f): + if not hasattr(f, "aliases"): + f.aliases = [] + f.aliases += aliases + return f + return decorate + + +class RawCmdln(cmd.Cmd): + """An improved (on cmd.Cmd) framework for building multi-subcommand + scripts (think "svn" & "cvs") and simple shells (think "pdb" and + "gdb"). + + A simple example: + + import cmdln + + class MySVN(cmdln.RawCmdln): + name = "svn" + + @cmdln.aliases('stat', 'st') + def do_status(self, argv): + print "handle 'svn status' command" + + if __name__ == "__main__": + shell = MySVN() + retval = shell.main() + sys.exit(retval) + + See for more information. + """ + name = None # if unset, defaults basename(sys.argv[0]) + prompt = None # if unset, defaults to self.name+"> " + version = None # if set, default top-level options include --version + + # Default messages for some 'help' command error cases. + # They are interpolated with one arg: the command. + nohelp = "no help on '%s'" + unknowncmd = "unknown command: '%s'" + + helpindent = '' # string with which to indent help output + + def __init__(self, completekey='tab', + stdin=None, stdout=None, stderr=None): + """Cmdln(completekey='tab', stdin=None, stdout=None, stderr=None) + + The optional argument 'completekey' is the readline name of a + completion key; it defaults to the Tab key. If completekey is + not None and the readline module is available, command completion + is done automatically. + + The optional arguments 'stdin', 'stdout' and 'stderr' specify + alternate input, output and error output file objects; if not + specified, sys.* are used. + + If 'stdout' but not 'stderr' is specified, stdout is used for + error output. This is to provide least surprise for users used + to only the 'stdin' and 'stdout' options with cmd.Cmd. + """ + import sys + if self.name is None: + self.name = os.path.basename(sys.argv[0]) + if self.prompt is None: + self.prompt = self.name+"> " + self._name_str = self._str(self.name) + self._prompt_str = self._str(self.prompt) + if stdin is not None: + self.stdin = stdin + else: + self.stdin = sys.stdin + if stdout is not None: + self.stdout = stdout + else: + self.stdout = sys.stdout + if stderr is not None: + self.stderr = stderr + elif stdout is not None: + self.stderr = stdout + else: + self.stderr = sys.stderr + self.cmdqueue = [] + self.completekey = completekey + self.cmdlooping = False + + def get_optparser(self): + """Hook for subclasses to set the option parser for the + top-level command/shell. + + This option parser is used retrieved and used by `.main()' to + handle top-level options. + + The default implements a single '-h|--help' option. Sub-classes + can return None to have no options at the top-level. Typically + an instance of CmdlnOptionParser should be returned. + """ + version = (self.version is not None + and "%s %s" % (self._name_str, self.version) + or None) + return CmdlnOptionParser(self, version=version) + + def postoptparse(self): + """Hook method executed just after `.main()' parses top-level + options. + + When called `self.options' holds the results of the option parse. + """ + pass + + def main(self, argv=None, loop=LOOP_NEVER): + """A possible mainline handler for a script, like so: + + import cmdln + class MyCmd(cmdln.Cmdln): + name = "mycmd" + ... + + if __name__ == "__main__": + MyCmd().main() + + By default this will use sys.argv to issue a single command to + 'MyCmd', then exit. The 'loop' argument can be use to control + interactive shell behaviour. + + Arguments: + "argv" (optional, default sys.argv) is the command to run. + It must be a sequence, where the first element is the + command name and subsequent elements the args for that + command. + "loop" (optional, default LOOP_NEVER) is a constant + indicating if a command loop should be started (i.e. an + interactive shell). Valid values (constants on this module): + LOOP_ALWAYS start loop and run "argv", if any + LOOP_NEVER run "argv" (or .emptyline()) and exit + LOOP_IF_EMPTY run "argv", if given, and exit; + otherwise, start loop + """ + if argv is None: + import sys + argv = sys.argv + else: + argv = argv[:] # don't modify caller's list + + self.optparser = self.get_optparser() + if self.optparser: # i.e. optparser=None means don't process for opts + try: + self.options, args = self.optparser.parse_args(argv[1:]) + except CmdlnUserError, ex: + msg = "%s: %s\nTry '%s help' for info.\n"\ + % (self.name, ex, self.name) + self.stderr.write(self._str(msg)) + self.stderr.flush() + return 1 + except StopOptionProcessing, ex: + return 0 + else: + self.options, args = None, argv[1:] + self.postoptparse() + + if loop == LOOP_ALWAYS: + if args: + self.cmdqueue.append(args) + return self.cmdloop() + elif loop == LOOP_NEVER: + if args: + return self.cmd(args) + else: + return self.emptyline() + elif loop == LOOP_IF_EMPTY: + if args: + return self.cmd(args) + else: + return self.cmdloop() + + def cmd(self, argv): + """Run one command and exit. + + "argv" is the arglist for the command to run. argv[0] is the + command to run. If argv is an empty list then the + 'emptyline' handler is run. + + Returns the return value from the command handler. + """ + assert isinstance(argv, (list, tuple)), \ + "'argv' is not a sequence: %r" % argv + retval = None + try: + argv = self.precmd(argv) + retval = self.onecmd(argv) + self.postcmd(argv) + except: + if not self.cmdexc(argv): + raise + retval = 1 + return retval + + def _str(self, s): + """Safely convert the given str/unicode to a string for printing.""" + try: + return str(s) + except UnicodeError: + #XXX What is the proper encoding to use here? 'utf-8' seems + # to work better than "getdefaultencoding" (usually + # 'ascii'), on OS X at least. + #import sys + #return s.encode(sys.getdefaultencoding(), "replace") + return s.encode("utf-8", "replace") + + def cmdloop(self, intro=None): + """Repeatedly issue a prompt, accept input, parse into an argv, and + dispatch (via .precmd(), .onecmd() and .postcmd()), passing them + the argv. In other words, start a shell. + + "intro" (optional) is a introductory message to print when + starting the command loop. This overrides the class + "intro" attribute, if any. + """ + self.cmdlooping = True + self.preloop() + if self.use_rawinput and self.completekey: + try: + import readline + self.old_completer = readline.get_completer() + readline.set_completer(self.complete) + readline.parse_and_bind(self.completekey+": complete") + except ImportError: + pass + try: + if intro is None: + intro = self.intro + if intro: + intro_str = self._str(intro) + self.stdout.write(intro_str+'\n') + self.stop = False + retval = None + while not self.stop: + if self.cmdqueue: + argv = self.cmdqueue.pop(0) + assert isinstance(argv, (list, tuple)), \ + "item on 'cmdqueue' is not a sequence: %r" % argv + else: + if self.use_rawinput: + try: + line = raw_input(self._prompt_str) + except EOFError: + line = 'EOF' + else: + self.stdout.write(self._prompt_str) + self.stdout.flush() + line = self.stdin.readline() + if not len(line): + line = 'EOF' + else: + line = line[:-1] # chop '\n' + argv = line2argv(line) + try: + argv = self.precmd(argv) + retval = self.onecmd(argv) + self.postcmd(argv) + except: + if not self.cmdexc(argv): + raise + retval = 1 + self.lastretval = retval + self.postloop() + finally: + if self.use_rawinput and self.completekey: + try: + import readline + readline.set_completer(self.old_completer) + except ImportError: + pass + self.cmdlooping = False + return retval + + def precmd(self, argv): + """Hook method executed just before the command argv is + interpreted, but after the input prompt is generated and issued. + + "argv" is the cmd to run. + + Returns an argv to run (i.e. this method can modify the command + to run). + """ + return argv + + def postcmd(self, argv): + """Hook method executed just after a command dispatch is finished. + + "argv" is the command that was run. + """ + pass + + def cmdexc(self, argv): + """Called if an exception is raised in any of precmd(), onecmd(), + or postcmd(). If True is returned, the exception is deemed to have + been dealt with. Otherwise, the exception is re-raised. + + The default implementation handles CmdlnUserError's, which + typically correspond to user error in calling commands (as + opposed to programmer error in the design of the script using + cmdln.py). + """ + import sys + type, exc, traceback = sys.exc_info() + if isinstance(exc, CmdlnUserError): + msg = "%s %s: %s\nTry '%s help %s' for info.\n"\ + % (self.name, argv[0], exc, self.name, argv[0]) + self.stderr.write(self._str(msg)) + self.stderr.flush() + return True + + def onecmd(self, argv): + if not argv: + return self.emptyline() + self.lastcmd = argv + cmdname = self._get_canonical_cmd_name(argv[0]) + if cmdname: + handler = self._get_cmd_handler(cmdname) + if handler: + return self._dispatch_cmd(handler, argv) + return self.default(argv) + + def _dispatch_cmd(self, handler, argv): + return handler(argv) + + def default(self, argv): + """Hook called to handle a command for which there is no handler. + + "argv" is the command and arguments to run. + + The default implementation writes and error message to stderr + and returns an error exit status. + + Returns a numeric command exit status. + """ + errmsg = self._str(self.unknowncmd % (argv[0],)) + if self.cmdlooping: + self.stderr.write(errmsg+"\n") + else: + self.stderr.write("%s: %s\nTry '%s help' for info.\n" + % (self._name_str, errmsg, self._name_str)) + self.stderr.flush() + return 1 + + def parseline(self, line): + # This is used by Cmd.complete (readline completer function) to + # massage the current line buffer before completion processing. + # We override to drop special '!' handling. + line = line.strip() + if not line: + return None, None, line + elif line[0] == '?': + line = 'help ' + line[1:] + i, n = 0, len(line) + while i < n and line[i] in self.identchars: i = i+1 + cmd, arg = line[:i], line[i:].strip() + return cmd, arg, line + + def helpdefault(self, cmd, known): + """Hook called to handle help on a command for which there is no + help handler. + + "cmd" is the command name on which help was requested. + "known" is a boolean indicating if this command is known + (i.e. if there is a handler for it). + + Returns a return code. + """ + if known: + msg = self._str(self.nohelp % (cmd,)) + if self.cmdlooping: + self.stderr.write(msg + '\n') + else: + self.stderr.write("%s: %s\n" % (self.name, msg)) + else: + msg = self.unknowncmd % (cmd,) + if self.cmdlooping: + self.stderr.write(msg + '\n') + else: + self.stderr.write("%s: %s\n" + "Try '%s help' for info.\n" + % (self.name, msg, self.name)) + self.stderr.flush() + return 1 + + def do_help(self, argv): + """${cmd_name}: give detailed help on a specific sub-command + + Usage: + ${name} help [COMMAND] + """ + if len(argv) > 1: # asking for help on a particular command + doc = None + cmdname = self._get_canonical_cmd_name(argv[1]) or argv[1] + if not cmdname: + return self.helpdefault(argv[1], False) + else: + helpfunc = getattr(self, "help_"+cmdname, None) + if helpfunc: + doc = helpfunc() + else: + handler = self._get_cmd_handler(cmdname) + if handler: + doc = handler.__doc__ + if doc is None: + return self.helpdefault(argv[1], handler != None) + else: # bare "help" command + doc = self.__class__.__doc__ # try class docstring + if doc is None: + # Try to provide some reasonable useful default help. + if self.cmdlooping: prefix = "" + else: prefix = self.name+' ' + doc = """Usage: + %sCOMMAND [ARGS...] + %shelp [COMMAND] + + ${option_list} + ${command_list} + ${help_list} + """ % (prefix, prefix) + cmdname = None + + if doc: # *do* have help content, massage and print that + doc = self._help_reindent(doc) + doc = self._help_preprocess(doc, cmdname) + doc = doc.rstrip() + '\n' # trim down trailing space + self.stdout.write(self._str(doc)) + self.stdout.flush() + do_help.aliases = ["?"] + + def _help_reindent(self, help, indent=None): + """Hook to re-indent help strings before writing to stdout. + + "help" is the help content to re-indent + "indent" is a string with which to indent each line of the + help content after normalizing. If unspecified or None + then the default is use: the 'self.helpindent' class + attribute. By default this is the empty string, i.e. + no indentation. + + By default, all common leading whitespace is removed and then + the lot is indented by 'self.helpindent'. When calculating the + common leading whitespace the first line is ignored -- hence + help content for Conan can be written as follows and have the + expected indentation: + + def do_crush(self, ...): + '''${cmd_name}: crush your enemies, see them driven before you... + + c.f. Conan the Barbarian''' + """ + if indent is None: + indent = self.helpindent + lines = help.splitlines(0) + _dedentlines(lines, skip_first_line=True) + lines = [(indent+line).rstrip() for line in lines] + return '\n'.join(lines) + + def _help_preprocess(self, help, cmdname): + """Hook to preprocess a help string before writing to stdout. + + "help" is the help string to process. + "cmdname" is the canonical sub-command name for which help + is being given, or None if the help is not specific to a + command. + + By default the following template variables are interpolated in + help content. (Note: these are similar to Python 2.4's + string.Template interpolation but not quite.) + + ${name} + The tool's/shell's name, i.e. 'self.name'. + ${option_list} + A formatted table of options for this shell/tool. + ${command_list} + A formatted table of available sub-commands. + ${help_list} + A formatted table of additional help topics (i.e. 'help_*' + methods with no matching 'do_*' method). + ${cmd_name} + The name (and aliases) for this sub-command formatted as: + "NAME (ALIAS1, ALIAS2, ...)". + ${cmd_usage} + A formatted usage block inferred from the command function + signature. + ${cmd_option_list} + A formatted table of options for this sub-command. (This is + only available for commands using the optparse integration, + i.e. using @cmdln.option decorators or manually setting the + 'optparser' attribute on the 'do_*' method.) + + Returns the processed help. + """ + preprocessors = { + "${name}": self._help_preprocess_name, + "${option_list}": self._help_preprocess_option_list, + "${command_list}": self._help_preprocess_command_list, + "${help_list}": self._help_preprocess_help_list, + "${cmd_name}": self._help_preprocess_cmd_name, + "${cmd_usage}": self._help_preprocess_cmd_usage, + "${cmd_option_list}": self._help_preprocess_cmd_option_list, + } + + for marker, preprocessor in preprocessors.items(): + if marker in help: + help = preprocessor(help, cmdname) + return help + + def _help_preprocess_name(self, help, cmdname=None): + return help.replace("${name}", self.name) + + def _help_preprocess_option_list(self, help, cmdname=None): + marker = "${option_list}" + indent, indent_width = _get_indent(marker, help) + suffix = _get_trailing_whitespace(marker, help) + + if self.optparser: + # Setup formatting options and format. + # - Indentation of 4 is better than optparse default of 2. + # C.f. Damian Conway's discussion of this in Perl Best + # Practices. + self.optparser.formatter.indent_increment = 4 + self.optparser.formatter.current_indent = indent_width + block = self.optparser.format_option_help() + '\n' + else: + block = "" + + help = help.replace(indent+marker+suffix, block, 1) + return help + + + def _help_preprocess_command_list(self, help, cmdname=None): + marker = "${command_list}" + indent, indent_width = _get_indent(marker, help) + suffix = _get_trailing_whitespace(marker, help) + + # Find any aliases for commands. + token2canonical = self._get_canonical_map() + aliases = {} + for token, cmdname in token2canonical.items(): + if token == cmdname: continue + aliases.setdefault(cmdname, []).append(token) + + # Get the list of (non-hidden) commands and their + # documentation, if any. + cmdnames = {} # use a dict to strip duplicates + for attr in self.get_names(): + if attr.startswith("do_"): + cmdnames[attr[3:]] = True + cmdnames = cmdnames.keys() + cmdnames.sort() + linedata = [] + for cmdname in cmdnames: + if aliases.get(cmdname): + a = aliases[cmdname] + a.sort() + cmdstr = "%s (%s)" % (cmdname, ", ".join(a)) + else: + cmdstr = cmdname + doc = None + try: + helpfunc = getattr(self, 'help_'+cmdname) + except AttributeError: + handler = self._get_cmd_handler(cmdname) + if handler: + doc = handler.__doc__ + else: + doc = helpfunc() + + # Strip "${cmd_name}: " from the start of a command's doc. Best + # practice dictates that command help strings begin with this, but + # it isn't at all wanted for the command list. + to_strip = "${cmd_name}:" + if doc and doc.startswith(to_strip): + #log.debug("stripping %r from start of %s's help string", + # to_strip, cmdname) + doc = doc[len(to_strip):].lstrip() + linedata.append( (cmdstr, doc) ) + + if linedata: + subindent = indent + ' '*4 + lines = _format_linedata(linedata, subindent, indent_width+4) + block = indent + "Commands:\n" \ + + '\n'.join(lines) + "\n\n" + help = help.replace(indent+marker+suffix, block, 1) + return help + + def _gen_names_and_attrs(self): + # Inheritance says we have to look in class and + # base classes; order is not important. + names = [] + classes = [self.__class__] + while classes: + aclass = classes.pop(0) + if aclass.__bases__: + classes = classes + list(aclass.__bases__) + for name in dir(aclass): + yield (name, getattr(aclass, name)) + + def _help_preprocess_help_list(self, help, cmdname=None): + marker = "${help_list}" + indent, indent_width = _get_indent(marker, help) + suffix = _get_trailing_whitespace(marker, help) + + # Determine the additional help topics, if any. + helpnames = {} + token2cmdname = self._get_canonical_map() + for attrname, attr in self._gen_names_and_attrs(): + if not attrname.startswith("help_"): continue + helpname = attrname[5:] + if helpname not in token2cmdname: + helpnames[helpname] = attr + + if helpnames: + linedata = [(n, a.__doc__ or "") for n, a in helpnames.items()] + linedata.sort() + + subindent = indent + ' '*4 + lines = _format_linedata(linedata, subindent, indent_width+4) + block = (indent + + "Additional help topics (run `%s help TOPIC'):\n" % self.name + + '\n'.join(lines) + + "\n\n") + else: + block = '' + help = help.replace(indent+marker+suffix, block, 1) + return help + + def _help_preprocess_cmd_name(self, help, cmdname=None): + marker = "${cmd_name}" + handler = self._get_cmd_handler(cmdname) + if not handler: + raise CmdlnError("cannot preprocess '%s' into help string: " + "could not find command handler for %r" + % (marker, cmdname)) + s = cmdname + if hasattr(handler, "aliases"): + s += " (%s)" % (", ".join(handler.aliases)) + help = help.replace(marker, s) + return help + + #TODO: this only makes sense as part of the Cmdln class. + # Add hooks to add help preprocessing template vars and put + # this one on that class. + def _help_preprocess_cmd_usage(self, help, cmdname=None): + marker = "${cmd_usage}" + handler = self._get_cmd_handler(cmdname) + if not handler: + raise CmdlnError("cannot preprocess '%s' into help string: " + "could not find command handler for %r" + % (marker, cmdname)) + indent, indent_width = _get_indent(marker, help) + suffix = _get_trailing_whitespace(marker, help) + + # Extract the introspection bits we need. + func = handler.im_func + if func.func_defaults: + func_defaults = list(func.func_defaults) + else: + func_defaults = [] + co_argcount = func.func_code.co_argcount + co_varnames = func.func_code.co_varnames + co_flags = func.func_code.co_flags + CO_FLAGS_ARGS = 4 + CO_FLAGS_KWARGS = 8 + + # Adjust argcount for possible *args and **kwargs arguments. + argcount = co_argcount + if co_flags & CO_FLAGS_ARGS: argcount += 1 + if co_flags & CO_FLAGS_KWARGS: argcount += 1 + + # Determine the usage string. + usage = "%s %s" % (self.name, cmdname) + if argcount <= 2: # handler ::= do_FOO(self, argv) + usage += " [ARGS...]" + elif argcount >= 3: # handler ::= do_FOO(self, subcmd, opts, ...) + argnames = list(co_varnames[3:argcount]) + tail = "" + if co_flags & CO_FLAGS_KWARGS: + name = argnames.pop(-1) + import warnings + # There is no generally accepted mechanism for passing + # keyword arguments from the command line. Could + # *perhaps* consider: arg=value arg2=value2 ... + warnings.warn("argument '**%s' on '%s.%s' command " + "handler will never get values" + % (name, self.__class__.__name__, + func.func_name)) + if co_flags & CO_FLAGS_ARGS: + name = argnames.pop(-1) + tail = "[%s...]" % name.upper() + while func_defaults: + func_defaults.pop(-1) + name = argnames.pop(-1) + tail = "[%s%s%s]" % (name.upper(), (tail and ' ' or ''), tail) + while argnames: + name = argnames.pop(-1) + tail = "%s %s" % (name.upper(), tail) + usage += ' ' + tail + + block_lines = [ + self.helpindent + "Usage:", + self.helpindent + ' '*4 + usage + ] + block = '\n'.join(block_lines) + '\n\n' + + help = help.replace(indent+marker+suffix, block, 1) + return help + + #TODO: this only makes sense as part of the Cmdln class. + # Add hooks to add help preprocessing template vars and put + # this one on that class. + def _help_preprocess_cmd_option_list(self, help, cmdname=None): + marker = "${cmd_option_list}" + handler = self._get_cmd_handler(cmdname) + if not handler: + raise CmdlnError("cannot preprocess '%s' into help string: " + "could not find command handler for %r" + % (marker, cmdname)) + indent, indent_width = _get_indent(marker, help) + suffix = _get_trailing_whitespace(marker, help) + if hasattr(handler, "optparser"): + # Setup formatting options and format. + # - Indentation of 4 is better than optparse default of 2. + # C.f. Damian Conway's discussion of this in Perl Best + # Practices. + handler.optparser.formatter.indent_increment = 4 + handler.optparser.formatter.current_indent = indent_width + block = handler.optparser.format_option_help() + '\n' + else: + block = "" + + help = help.replace(indent+marker+suffix, block, 1) + return help + + def _get_canonical_cmd_name(self, token): + map = self._get_canonical_map() + return map.get(token, None) + + def _get_canonical_map(self): + """Return a mapping of available command names and aliases to + their canonical command name. + """ + cacheattr = "_token2canonical" + if not hasattr(self, cacheattr): + # Get the list of commands and their aliases, if any. + token2canonical = {} + cmd2funcname = {} # use a dict to strip duplicates + for attr in self.get_names(): + if attr.startswith("do_"): cmdname = attr[3:] + elif attr.startswith("_do_"): cmdname = attr[4:] + else: + continue + cmd2funcname[cmdname] = attr + token2canonical[cmdname] = cmdname + for cmdname, funcname in cmd2funcname.items(): # add aliases + func = getattr(self, funcname) + aliases = getattr(func, "aliases", []) + for alias in aliases: + if alias in cmd2funcname: + import warnings + warnings.warn("'%s' alias for '%s' command conflicts " + "with '%s' handler" + % (alias, cmdname, cmd2funcname[alias])) + continue + token2canonical[alias] = cmdname + setattr(self, cacheattr, token2canonical) + return getattr(self, cacheattr) + + def _get_cmd_handler(self, cmdname): + handler = None + try: + handler = getattr(self, 'do_' + cmdname) + except AttributeError: + try: + # Private command handlers begin with "_do_". + handler = getattr(self, '_do_' + cmdname) + except AttributeError: + pass + return handler + + def _do_EOF(self, argv): + # Default EOF handler + # Note: an actual EOF is redirected to this command. + #TODO: separate name for this. Currently it is available from + # command-line. Is that okay? + self.stdout.write('\n') + self.stdout.flush() + self.stop = True + + def emptyline(self): + # Different from cmd.Cmd: don't repeat the last command for an + # emptyline. + if self.cmdlooping: + pass + else: + return self.do_help(["help"]) + + +#---- optparse.py extension to fix (IMO) some deficiencies +# +# See the class _OptionParserEx docstring for details. +# + +class StopOptionProcessing(Exception): + """Indicate that option *and argument* processing should stop + cleanly. This is not an error condition. It is similar in spirit to + StopIteration. This is raised by _OptionParserEx's default "help" + and "version" option actions and can be raised by custom option + callbacks too. + + Hence the typical CmdlnOptionParser (a subclass of _OptionParserEx) + usage is: + + parser = CmdlnOptionParser(mycmd) + parser.add_option("-f", "--force", dest="force") + ... + try: + opts, args = parser.parse_args() + except StopOptionProcessing: + # normal termination, "--help" was probably given + sys.exit(0) + """ + +class _OptionParserEx(optparse.OptionParser): + """An optparse.OptionParser that uses exceptions instead of sys.exit. + + This class is an extension of optparse.OptionParser that differs + as follows: + - Correct (IMO) the default OptionParser error handling to never + sys.exit(). Instead OptParseError exceptions are passed through. + - Add the StopOptionProcessing exception (a la StopIteration) to + indicate normal termination of option processing. + See StopOptionProcessing's docstring for details. + + I'd also like to see the following in the core optparse.py, perhaps + as a RawOptionParser which would serve as a base class for the more + generally used OptionParser (that works as current): + - Remove the implicit addition of the -h|--help and --version + options. They can get in the way (e.g. if want '-?' and '-V' for + these as well) and it is not hard to do: + optparser.add_option("-h", "--help", action="help") + optparser.add_option("--version", action="version") + These are good practices, just not valid defaults if they can + get in the way. + """ + def error(self, msg): + raise optparse.OptParseError(msg) + + def exit(self, status=0, msg=None): + if status == 0: + raise StopOptionProcessing(msg) + else: + #TODO: don't lose status info here + raise optparse.OptParseError(msg) + + + +#---- optparse.py-based option processing support + +class CmdlnOptionParser(_OptionParserEx): + """An optparse.OptionParser class more appropriate for top-level + Cmdln options. For parsing of sub-command options, see + SubCmdOptionParser. + + Changes: + - disable_interspersed_args() by default, because a Cmdln instance + has sub-commands which may themselves have options. + - Redirect print_help() to the Cmdln.do_help() which is better + equiped to handle the "help" action. + - error() will raise a CmdlnUserError: OptionParse.error() is meant + to be called for user errors. Raising a well-known error here can + make error handling clearer. + - Also see the changes in _OptionParserEx. + """ + def __init__(self, cmdln, **kwargs): + self.cmdln = cmdln + kwargs["prog"] = self.cmdln.name + _OptionParserEx.__init__(self, **kwargs) + self.disable_interspersed_args() + + def print_help(self, file=None): + self.cmdln.onecmd(["help"]) + + def error(self, msg): + raise CmdlnUserError(msg) + + +class SubCmdOptionParser(_OptionParserEx): + def set_cmdln_info(self, cmdln, subcmd): + """Called by Cmdln to pass relevant info about itself needed + for print_help(). + """ + self.cmdln = cmdln + self.subcmd = subcmd + + def print_help(self, file=None): + self.cmdln.onecmd(["help", self.subcmd]) + + def error(self, msg): + raise CmdlnUserError(msg) + + +def option(*args, **kwargs): + """Decorator to add an option to the optparser argument of a Cmdln + subcommand. + + Example: + class MyShell(cmdln.Cmdln): + @cmdln.option("-f", "--force", help="force removal") + def do_remove(self, subcmd, opts, *args): + #... + """ + #XXX Is there a possible optimization for many options to not have a + # large stack depth here? + def decorate(f): + if not hasattr(f, "optparser"): + f.optparser = SubCmdOptionParser() + f.optparser.add_option(*args, **kwargs) + return f + return decorate + + +class Cmdln(RawCmdln): + """An improved (on cmd.Cmd) framework for building multi-subcommand + scripts (think "svn" & "cvs") and simple shells (think "pdb" and + "gdb"). + + A simple example: + + import cmdln + + class MySVN(cmdln.Cmdln): + name = "svn" + + @cmdln.aliases('stat', 'st') + @cmdln.option('-v', '--verbose', action='store_true' + help='print verbose information') + def do_status(self, subcmd, opts, *paths): + print "handle 'svn status' command" + + #... + + if __name__ == "__main__": + shell = MySVN() + retval = shell.main() + sys.exit(retval) + + 'Cmdln' extends 'RawCmdln' by providing optparse option processing + integration. See this class' _dispatch_cmd() docstring and + for more information. + """ + def _dispatch_cmd(self, handler, argv): + """Introspect sub-command handler signature to determine how to + dispatch the command. The raw handler provided by the base + 'RawCmdln' class is still supported: + + def do_foo(self, argv): + # 'argv' is the vector of command line args, argv[0] is + # the command name itself (i.e. "foo" or an alias) + pass + + In addition, if the handler has more than 2 arguments option + processing is automatically done (using optparse): + + @cmdln.option('-v', '--verbose', action='store_true') + def do_bar(self, subcmd, opts, *args): + # subcmd = <"bar" or an alias> + # opts = + if opts.verbose: + print "lots of debugging output..." + # args = + for arg in args: + bar(arg) + + TODO: explain that "*args" can be other signatures as well. + + The `cmdln.option` decorator corresponds to an `add_option()` + method call on an `optparse.OptionParser` instance. + + You can declare a specific number of arguments: + + @cmdln.option('-v', '--verbose', action='store_true') + def do_bar2(self, subcmd, opts, bar_one, bar_two): + #... + + and an appropriate error message will be raised/printed if the + command is called with a different number of args. + """ + co_argcount = handler.im_func.func_code.co_argcount + if co_argcount == 2: # handler ::= do_foo(self, argv) + return handler(argv) + elif co_argcount >= 3: # handler ::= do_foo(self, subcmd, opts, ...) + try: + optparser = handler.optparser + except AttributeError: + optparser = handler.im_func.optparser = SubCmdOptionParser() + assert isinstance(optparser, SubCmdOptionParser) + optparser.set_cmdln_info(self, argv[0]) + try: + opts, args = optparser.parse_args(argv[1:]) + except StopOptionProcessing: + #TODO: this doesn't really fly for a replacement of + # optparse.py behaviour, does it? + return 0 # Normal command termination + + try: + return handler(argv[0], opts, *args) + except TypeError, ex: + # Some TypeError's are user errors: + # do_foo() takes at least 4 arguments (3 given) + # do_foo() takes at most 5 arguments (6 given) + # do_foo() takes exactly 5 arguments (6 given) + # Raise CmdlnUserError for these with a suitably + # massaged error message. + import sys + tb = sys.exc_info()[2] # the traceback object + if tb.tb_next is not None: + # If the traceback is more than one level deep, then the + # TypeError do *not* happen on the "handler(...)" call + # above. In that we don't want to handle it specially + # here: it would falsely mask deeper code errors. + raise + msg = ex.args[0] + match = _INCORRECT_NUM_ARGS_RE.search(msg) + if match: + msg = list(match.groups()) + msg[1] = int(msg[1]) - 3 + if msg[1] == 1: + msg[2] = msg[2].replace("arguments", "argument") + msg[3] = int(msg[3]) - 3 + msg = ''.join(map(str, msg)) + raise CmdlnUserError(msg) + else: + raise + else: + raise CmdlnError("incorrect argcount for %s(): takes %d, must " + "take 2 for 'argv' signature or 3+ for 'opts' " + "signature" % (handler.__name__, co_argcount)) + + + +#---- internal support functions + +def _format_linedata(linedata, indent, indent_width): + """Format specific linedata into a pleasant layout. + + "linedata" is a list of 2-tuples of the form: + (, ) + "indent" is a string to use for one level of indentation + "indent_width" is a number of columns by which the + formatted data will be indented when printed. + + The column is held to 15 columns. + """ + lines = [] + WIDTH = 78 - indent_width + SPACING = 2 + NAME_WIDTH_LOWER_BOUND = 13 + NAME_WIDTH_UPPER_BOUND = 16 + NAME_WIDTH = max([len(s) for s,d in linedata]) + if NAME_WIDTH < NAME_WIDTH_LOWER_BOUND: + NAME_WIDTH = NAME_WIDTH_LOWER_BOUND + else: + NAME_WIDTH = NAME_WIDTH_UPPER_BOUND + + DOC_WIDTH = WIDTH - NAME_WIDTH - SPACING + for namestr, doc in linedata: + line = indent + namestr + if len(namestr) <= NAME_WIDTH: + line += ' ' * (NAME_WIDTH + SPACING - len(namestr)) + else: + lines.append(line) + line = indent + ' ' * (NAME_WIDTH + SPACING) + line += _summarize_doc(doc, DOC_WIDTH) + lines.append(line.rstrip()) + return lines + +def _summarize_doc(doc, length=60): + r"""Parse out a short one line summary from the given doclines. + + "doc" is the doc string to summarize. + "length" is the max length for the summary + + >>> _summarize_doc("this function does this") + 'this function does this' + >>> _summarize_doc("this function does this", 10) + 'this fu...' + >>> _summarize_doc("this function does this\nand that") + 'this function does this and that' + >>> _summarize_doc("this function does this\n\nand that") + 'this function does this' + """ + import re + if doc is None: + return "" + assert length > 3, "length <= 3 is absurdly short for a doc summary" + doclines = doc.strip().splitlines(0) + if not doclines: + return "" + + summlines = [] + for i, line in enumerate(doclines): + stripped = line.strip() + if not stripped: + break + summlines.append(stripped) + if len(''.join(summlines)) >= length: + break + + summary = ' '.join(summlines) + if len(summary) > length: + summary = summary[:length-3] + "..." + return summary + + +def line2argv(line): + r"""Parse the given line into an argument vector. + + "line" is the line of input to parse. + + This may get niggly when dealing with quoting and escaping. The + current state of this parsing may not be completely thorough/correct + in this respect. + + >>> from cmdln import line2argv + >>> line2argv("foo") + ['foo'] + >>> line2argv("foo bar") + ['foo', 'bar'] + >>> line2argv("foo bar ") + ['foo', 'bar'] + >>> line2argv(" foo bar") + ['foo', 'bar'] + + Quote handling: + + >>> line2argv("'foo bar'") + ['foo bar'] + >>> line2argv('"foo bar"') + ['foo bar'] + >>> line2argv(r'"foo\"bar"') + ['foo"bar'] + >>> line2argv("'foo bar' spam") + ['foo bar', 'spam'] + >>> line2argv("'foo 'bar spam") + ['foo bar', 'spam'] + + >>> line2argv('some\tsimple\ttests') + ['some', 'simple', 'tests'] + >>> line2argv('a "more complex" test') + ['a', 'more complex', 'test'] + >>> line2argv('a more="complex test of " quotes') + ['a', 'more=complex test of ', 'quotes'] + >>> line2argv('a more" complex test of " quotes') + ['a', 'more complex test of ', 'quotes'] + >>> line2argv('an "embedded \\"quote\\""') + ['an', 'embedded "quote"'] + + # Komodo bug 48027 + >>> line2argv('foo bar C:\\') + ['foo', 'bar', 'C:\\'] + + # Komodo change 127581 + >>> line2argv(r'"\test\slash" "foo bar" "foo\"bar"') + ['\\test\\slash', 'foo bar', 'foo"bar'] + + # Komodo change 127629 + >>> if sys.platform == "win32": + ... line2argv(r'\foo\bar') == ['\\foo\\bar'] + ... line2argv(r'\\foo\\bar') == ['\\\\foo\\\\bar'] + ... line2argv('"foo') == ['foo'] + ... else: + ... line2argv(r'\foo\bar') == ['foobar'] + ... line2argv(r'\\foo\\bar') == ['\\foo\\bar'] + ... try: + ... line2argv('"foo') + ... except ValueError, ex: + ... "not terminated" in str(ex) + True + True + True + """ + import string + line = line.strip() + argv = [] + state = "default" + arg = None # the current argument being parsed + i = -1 + while 1: + i += 1 + if i >= len(line): break + ch = line[i] + + if ch == "\\" and i+1 < len(line): + # escaped char always added to arg, regardless of state + if arg is None: arg = "" + if (sys.platform == "win32" + or state in ("double-quoted", "single-quoted") + ) and line[i+1] not in tuple('"\''): + arg += ch + i += 1 + arg += line[i] + continue + + if state == "single-quoted": + if ch == "'": + state = "default" + else: + arg += ch + elif state == "double-quoted": + if ch == '"': + state = "default" + else: + arg += ch + elif state == "default": + if ch == '"': + if arg is None: arg = "" + state = "double-quoted" + elif ch == "'": + if arg is None: arg = "" + state = "single-quoted" + elif ch in string.whitespace: + if arg is not None: + argv.append(arg) + arg = None + else: + if arg is None: arg = "" + arg += ch + if arg is not None: + argv.append(arg) + if not sys.platform == "win32" and state != "default": + raise ValueError("command line is not terminated: unfinished %s " + "segment" % state) + return argv + + +def argv2line(argv): + r"""Put together the given argument vector into a command line. + + "argv" is the argument vector to process. + + >>> from cmdln import argv2line + >>> argv2line(['foo']) + 'foo' + >>> argv2line(['foo', 'bar']) + 'foo bar' + >>> argv2line(['foo', 'bar baz']) + 'foo "bar baz"' + >>> argv2line(['foo"bar']) + 'foo"bar' + >>> print argv2line(['foo" bar']) + 'foo" bar' + >>> print argv2line(["foo' bar"]) + "foo' bar" + >>> argv2line(["foo'bar"]) + "foo'bar" + """ + escapedArgs = [] + for arg in argv: + if ' ' in arg and '"' not in arg: + arg = '"'+arg+'"' + elif ' ' in arg and "'" not in arg: + arg = "'"+arg+"'" + elif ' ' in arg: + arg = arg.replace('"', r'\"') + arg = '"'+arg+'"' + escapedArgs.append(arg) + return ' '.join(escapedArgs) + + +# Recipe: dedent (0.1) in /Users/trentm/tm/recipes/cookbook +def _dedentlines(lines, tabsize=8, skip_first_line=False): + """_dedentlines(lines, tabsize=8, skip_first_line=False) -> dedented lines + + "lines" is a list of lines to dedent. + "tabsize" is the tab width to use for indent width calculations. + "skip_first_line" is a boolean indicating if the first line should + be skipped for calculating the indent width and for dedenting. + This is sometimes useful for docstrings and similar. + + Same as dedent() except operates on a sequence of lines. Note: the + lines list is modified **in-place**. + """ + DEBUG = False + if DEBUG: + print "dedent: dedent(..., tabsize=%d, skip_first_line=%r)"\ + % (tabsize, skip_first_line) + indents = [] + margin = None + for i, line in enumerate(lines): + if i == 0 and skip_first_line: continue + indent = 0 + for ch in line: + if ch == ' ': + indent += 1 + elif ch == '\t': + indent += tabsize - (indent % tabsize) + elif ch in '\r\n': + continue # skip all-whitespace lines + else: + break + else: + continue # skip all-whitespace lines + if DEBUG: print "dedent: indent=%d: %r" % (indent, line) + if margin is None: + margin = indent + else: + margin = min(margin, indent) + if DEBUG: print "dedent: margin=%r" % margin + + if margin is not None and margin > 0: + for i, line in enumerate(lines): + if i == 0 and skip_first_line: continue + removed = 0 + for j, ch in enumerate(line): + if ch == ' ': + removed += 1 + elif ch == '\t': + removed += tabsize - (removed % tabsize) + elif ch in '\r\n': + if DEBUG: print "dedent: %r: EOL -> strip up to EOL" % line + lines[i] = lines[i][j:] + break + else: + raise ValueError("unexpected non-whitespace char %r in " + "line %r while removing %d-space margin" + % (ch, line, margin)) + if DEBUG: + print "dedent: %r: %r -> removed %d/%d"\ + % (line, ch, removed, margin) + if removed == margin: + lines[i] = lines[i][j+1:] + break + elif removed > margin: + lines[i] = ' '*(removed-margin) + lines[i][j+1:] + break + return lines + +def _dedent(text, tabsize=8, skip_first_line=False): + """_dedent(text, tabsize=8, skip_first_line=False) -> dedented text + + "text" is the text to dedent. + "tabsize" is the tab width to use for indent width calculations. + "skip_first_line" is a boolean indicating if the first line should + be skipped for calculating the indent width and for dedenting. + This is sometimes useful for docstrings and similar. + + textwrap.dedent(s), but don't expand tabs to spaces + """ + lines = text.splitlines(1) + _dedentlines(lines, tabsize=tabsize, skip_first_line=skip_first_line) + return ''.join(lines) + + +def _get_indent(marker, s, tab_width=8): + """_get_indent(marker, s, tab_width=8) -> + (, )""" + # Figure out how much the marker is indented. + INDENT_CHARS = tuple(' \t') + start = s.index(marker) + i = start + while i > 0: + if s[i-1] not in INDENT_CHARS: + break + i -= 1 + indent = s[i:start] + indent_width = 0 + for ch in indent: + if ch == ' ': + indent_width += 1 + elif ch == '\t': + indent_width += tab_width - (indent_width % tab_width) + return indent, indent_width + +def _get_trailing_whitespace(marker, s): + """Return the whitespace content trailing the given 'marker' in string 's', + up to and including a newline. + """ + suffix = '' + start = s.index(marker) + len(marker) + i = start + while i < len(s): + if s[i] in ' \t': + suffix += s[i] + elif s[i] in '\r\n': + suffix += s[i] + if s[i] == '\r' and i+1 < len(s) and s[i+1] == '\n': + suffix += s[i+1] + break + else: + break + i += 1 + return suffix + + + +#---- bash completion support +# Note: This is still experimental. I expect to change this +# significantly. +# +# To get Bash completion for a cmdln.Cmdln class, run the following +# bash command: +# $ complete -C 'python -m cmdln /path/to/script.py CmdlnClass' cmdname +# For example: +# $ complete -C 'python -m cmdln ~/bin/svn.py SVN' svn +# +#TODO: Simplify the above so don't have to given path to script (try to +# find it on PATH, if possible). Could also make class name +# optional if there is only one in the module (common case). + +if __name__ == "__main__" and len(sys.argv) == 6: + def _log(s): + return # no-op, comment out for debugging + from os.path import expanduser + fout = open(expanduser("~/tmp/bashcpln.log"), 'a') + fout.write(str(s) + '\n') + fout.close() + + # Recipe: module_from_path (1.0.1+) + def _module_from_path(path): + import imp, os, sys + path = os.path.expanduser(path) + dir = os.path.dirname(path) or os.curdir + name = os.path.splitext(os.path.basename(path))[0] + sys.path.insert(0, dir) + try: + iinfo = imp.find_module(name, [dir]) + return imp.load_module(name, *iinfo) + finally: + sys.path.remove(dir) + + def _get_bash_cplns(script_path, class_name, cmd_name, + token, preceding_token): + _log('--') + _log('get_cplns(%r, %r, %r, %r, %r)' + % (script_path, class_name, cmd_name, token, preceding_token)) + comp_line = os.environ["COMP_LINE"] + comp_point = int(os.environ["COMP_POINT"]) + _log("COMP_LINE: %r" % comp_line) + _log("COMP_POINT: %r" % comp_point) + + try: + script = _module_from_path(script_path) + except ImportError, ex: + _log("error importing `%s': %s" % (script_path, ex)) + return [] + shell = getattr(script, class_name)() + cmd_map = shell._get_canonical_map() + del cmd_map["EOF"] + + # Determine if completing the sub-command name. + parts = comp_line[:comp_point].split(None, 1) + _log(parts) + if len(parts) == 1 or not (' ' in parts[1] or '\t' in parts[1]): + #TODO: if parts[1].startswith('-'): handle top-level opts + _log("complete sub-command names") + matches = {} + for name, canon_name in cmd_map.items(): + if name.startswith(token): + matches[name] = canon_name + if not matches: + return [] + elif len(matches) == 1: + return matches.keys() + elif len(set(matches.values())) == 1: + return [matches.values()[0]] + else: + return matches.keys() + + # Otherwise, complete options for the given sub-command. + #TODO: refine this so it does the right thing with option args + if token.startswith('-'): + cmd_name = comp_line.split(None, 2)[1] + try: + cmd_canon_name = cmd_map[cmd_name] + except KeyError: + return [] + handler = shell._get_cmd_handler(cmd_canon_name) + optparser = getattr(handler, "optparser", None) + if optparser is None: + optparser = SubCmdOptionParser() + opt_strs = [] + for option in optparser.option_list: + for opt_str in option._short_opts + option._long_opts: + if opt_str.startswith(token): + opt_strs.append(opt_str) + return opt_strs + + return [] + + for cpln in _get_bash_cplns(*sys.argv[1:]): + print cpln + diff --git a/scripts/lib/wic/utils/errors.py b/scripts/lib/wic/utils/errors.py new file mode 100644 index 0000000000..9410311875 --- /dev/null +++ b/scripts/lib/wic/utils/errors.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2007 Red Hat, Inc. +# Copyright (c) 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +class CreatorError(Exception): + """An exception base class for all imgcreate errors.""" + keyword = '' + + def __init__(self, msg): + self.msg = msg + + def __str__(self): + if isinstance(self.msg, unicode): + self.msg = self.msg.encode('utf-8', 'ignore') + else: + self.msg = str(self.msg) + return self.keyword + self.msg + +class Usage(CreatorError): + keyword = '' + + def __str__(self): + if isinstance(self.msg, unicode): + self.msg = self.msg.encode('utf-8', 'ignore') + else: + self.msg = str(self.msg) + return self.keyword + self.msg + ', please use "--help" for more info' + +class KsError(CreatorError): + keyword = '' + +class ImageError(CreatorError): + keyword = '' diff --git a/scripts/lib/wic/utils/fs_related.py b/scripts/lib/wic/utils/fs_related.py new file mode 100644 index 0000000000..ea9f85c60f --- /dev/null +++ b/scripts/lib/wic/utils/fs_related.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2007, Red Hat, Inc. +# Copyright (c) 2009, 2010, 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +from __future__ import with_statement +import os +import sys +import errno +import stat +import random +import string +import time +import uuid + +from wic import msger +from wic.utils import runner +from wic.utils.errors import * +from wic.utils.oe.misc import * + +def find_binary_path(binary): + if os.environ.has_key("PATH"): + paths = os.environ["PATH"].split(":") + else: + paths = [] + if os.environ.has_key("HOME"): + paths += [os.environ["HOME"] + "/bin"] + paths += ["/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"] + + for path in paths: + bin_path = "%s/%s" % (path, binary) + if os.path.exists(bin_path): + return bin_path + + print "External command '%s' not found, exiting." % binary + print " (Please install '%s' on your host system)" % binary + sys.exit(1) + +def makedirs(dirname): + """A version of os.makedirs() that doesn't throw an + exception if the leaf directory already exists. + """ + try: + os.makedirs(dirname) + except OSError, err: + if err.errno != errno.EEXIST: + raise + +class Disk: + """ + Generic base object for a disk. + """ + def __init__(self, size, device = None): + self._device = device + self._size = size + + def create(self): + pass + + def cleanup(self): + pass + + def get_device(self): + return self._device + def set_device(self, path): + self._device = path + device = property(get_device, set_device) + + def get_size(self): + return self._size + size = property(get_size) + + +class DiskImage(Disk): + """ + A Disk backed by a file. + """ + def __init__(self, image_file, size): + Disk.__init__(self, size) + self.image_file = image_file + + def exists(self): + return os.path.exists(self.image_file) + + def create(self): + if self.device is not None: + return + + blocks = self.size / 1024 + if self.size - blocks * 1024: + blocks += 1 + + # create disk image + dd_cmd = "dd if=/dev/zero of=%s bs=1024 seek=%d count=1" % \ + (self.image_file, blocks) + exec_cmd(dd_cmd) + + self.device = self.image_file diff --git a/scripts/lib/wic/utils/misc.py b/scripts/lib/wic/utils/misc.py new file mode 100644 index 0000000000..6e56316608 --- /dev/null +++ b/scripts/lib/wic/utils/misc.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2010, 2011 Intel Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os +import sys +import time + +def build_name(kscfg, release=None, prefix = None, suffix = None): + """Construct and return an image name string. + + This is a utility function to help create sensible name and fslabel + strings. The name is constructed using the sans-prefix-and-extension + kickstart filename and the supplied prefix and suffix. + + kscfg -- a path to a kickstart file + release -- a replacement to suffix for image release + prefix -- a prefix to prepend to the name; defaults to None, which causes + no prefix to be used + suffix -- a suffix to append to the name; defaults to None, which causes + a YYYYMMDDHHMM suffix to be used + + Note, if maxlen is less then the len(suffix), you get to keep both pieces. + + """ + name = os.path.basename(kscfg) + idx = name.rfind('.') + if idx >= 0: + name = name[:idx] + + if release is not None: + suffix = "" + if prefix is None: + prefix = "" + if suffix is None: + suffix = time.strftime("%Y%m%d%H%M") + + if name.startswith(prefix): + name = name[len(prefix):] + + prefix = "%s-" % prefix if prefix else "" + suffix = "-%s" % suffix if suffix else "" + + ret = prefix + name + suffix + + return ret diff --git a/scripts/lib/wic/utils/oe/__init__.py b/scripts/lib/wic/utils/oe/__init__.py new file mode 100644 index 0000000000..0a81575a74 --- /dev/null +++ b/scripts/lib/wic/utils/oe/__init__.py @@ -0,0 +1,22 @@ +# +# OpenEmbedded wic utils library +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# AUTHORS +# Tom Zanussi +# diff --git a/scripts/lib/wic/utils/oe/misc.py b/scripts/lib/wic/utils/oe/misc.py new file mode 100644 index 0000000000..b0b5baab73 --- /dev/null +++ b/scripts/lib/wic/utils/oe/misc.py @@ -0,0 +1,205 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2013, Intel Corporation. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This module provides a place to collect various wic-related utils +# for the OpenEmbedded Image Tools. +# +# AUTHORS +# Tom Zanussi +# + +from wic import msger +from wic.utils import runner + +def __exec_cmd(cmd_and_args, as_shell = False, catch = 3): + """ + Execute command, catching stderr, stdout + + Need to execute as_shell if the command uses wildcards + """ + msger.debug("__exec_cmd: %s" % cmd_and_args) + args = cmd_and_args.split() + msger.debug(args) + + if (as_shell): + rc, out = runner.runtool(cmd_and_args, catch) + else: + rc, out = runner.runtool(args, catch) + out = out.strip() + msger.debug("__exec_cmd: output for %s (rc = %d): %s" % \ + (cmd_and_args, rc, out)) + + return (rc, out) + + +def exec_cmd(cmd_and_args, as_shell = False, catch = 3): + """ + Execute command, catching stderr, stdout + + Exits if rc non-zero + """ + rc, out = __exec_cmd(cmd_and_args, as_shell, catch) + + if rc != 0: + msger.error("exec_cmd: %s returned '%s' instead of 0" % (cmd_and_args, rc)) + + return out + + +def exec_cmd_quiet(cmd_and_args, as_shell = False): + """ + Execute command, catching nothing in the output + + Exits if rc non-zero + """ + return exec_cmd(cmd_and_args, as_shell, 0) + + +def exec_native_cmd(cmd_and_args, native_sysroot, catch = 3): + """ + Execute native command, catching stderr, stdout + + Need to execute as_shell if the command uses wildcards + + Always need to execute native commands as_shell + """ + native_paths = \ + "export PATH=%s/sbin:%s/usr/sbin:%s/usr/bin:$PATH" % \ + (native_sysroot, native_sysroot, native_sysroot) + native_cmd_and_args = "%s;%s" % (native_paths, cmd_and_args) + msger.debug("exec_native_cmd: %s" % cmd_and_args) + + args = cmd_and_args.split() + msger.debug(args) + + rc, out = __exec_cmd(native_cmd_and_args, True, catch) + + if rc == 127: # shell command-not-found + msger.error("A native (host) program required to build the image " + "was not found (see details above). Please make sure " + "it's installed and try again.") + + return (rc, out) + + +def exec_native_cmd_quiet(cmd_and_args, native_sysroot): + """ + Execute native command, catching nothing in the output + + Need to execute as_shell if the command uses wildcards + + Always need to execute native commands as_shell + """ + return exec_native_cmd(cmd_and_args, native_sysroot, 0) + + +# kickstart doesn't support variable substution in commands, so this +# is our current simplistic scheme for supporting that + +wks_vars = dict() + +def get_wks_var(key): + return wks_vars[key] + +def add_wks_var(key, val): + wks_vars[key] = val + +BOOTDD_EXTRA_SPACE = 16384 +IMAGE_EXTRA_SPACE = 10240 +IMAGE_OVERHEAD_FACTOR = 1.3 + +__bitbake_env_lines = "" + +def set_bitbake_env_lines(bitbake_env_lines): + global __bitbake_env_lines + __bitbake_env_lines = bitbake_env_lines + +def get_bitbake_env_lines(): + return __bitbake_env_lines + +def find_bitbake_env_lines(image_name): + """ + If image_name is empty, plugins might still be able to use the + environment, so set it regardless. + """ + if image_name: + bitbake_env_cmd = "bitbake -e %s" % image_name + else: + bitbake_env_cmd = "bitbake -e" + rc, bitbake_env_lines = __exec_cmd(bitbake_env_cmd) + if rc != 0: + print "Couldn't get '%s' output." % bitbake_env_cmd + return None + + return bitbake_env_lines + +def find_artifact(bitbake_env_lines, variable): + """ + Gather the build artifact for the current image (the image_name + e.g. core-image-minimal) for the current MACHINE set in local.conf + """ + retval = "" + + for line in bitbake_env_lines.split('\n'): + if (get_line_val(line, variable)): + retval = get_line_val(line, variable) + break + + return retval + +def get_line_val(line, key): + """ + Extract the value from the VAR="val" string + """ + if line.startswith(key + "="): + stripped_line = line.split('=')[1] + stripped_line = stripped_line.replace('\"', '') + return stripped_line + return None + +def get_bitbake_var(key): + for line in __bitbake_env_lines.split('\n'): + if (get_line_val(line, key)): + val = get_line_val(line, key) + return val + return None + +def parse_sourceparams(sourceparams): + """ + Split sourceparams string of the form key1=val1[,key2=val2,...] + into a dict. Also accepts valueless keys i.e. without =. + + Returns dict of param key/val pairs (note that val may be None). + """ + params_dict = {} + + params = sourceparams.split(',') + if params: + for p in params: + if not p: + continue + if not '=' in p: + key = p + val = None + else: + key, val = p.split('=') + params_dict[key] = val + + return params_dict diff --git a/scripts/lib/wic/utils/oe/package_manager.py b/scripts/lib/wic/utils/oe/package_manager.py new file mode 100644 index 0000000000..92ce98e2ce --- /dev/null +++ b/scripts/lib/wic/utils/oe/package_manager.py @@ -0,0 +1,810 @@ +# ex:ts=4:sw=4:sts=4:et +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- +# +# Copyright (c) 2014, Enea AB. +# All rights reserved. +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# DESCRIPTION +# This implements the opkg package manager wrapper as a combination of +# meta/lib/oe/package_manager.py and bitbake/lib/bb/utils.py files and +# adaptation of those files to 'wic'. +# +# AUTHORS +# Adrian Calianu +# +# This file incorporates work covered by the following copyright and +# permission notice: +# +# meta/COPYING.GPLv2 (GPLv2) +# meta/COPYING.MIT (MIT) +# +# Copyright (C) 2004 Michael Lauer +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +from abc import ABCMeta, abstractmethod +import os +import glob +import subprocess +import shutil +import multiprocessing +import re +import errno +import fcntl + +from mic.utils.oe.misc import * +from mic import msger + +def mkdirhier(directory): + """Create a directory like 'mkdir -p', but does not complain if + directory already exists like os.makedirs + """ + + try: + os.makedirs(directory) + except OSError as e: + if e.errno != errno.EEXIST: + raise e + +def remove(path, recurse=False): + """Equivalent to rm -f or rm -rf""" + if not path: + return + if recurse: + # shutil.rmtree(name) would be ideal but its too slow + subprocess.call(['rm', '-rf'] + glob.glob(path)) + return + for name in glob.glob(path): + try: + os.unlink(name) + except OSError as exc: + if exc.errno != errno.ENOENT: + raise + +def lockfile(name, shared=False, retry=True): + """ + Use the file fn as a lock file, return when the lock has been acquired. + Returns a variable to pass to unlockfile(). + """ + dirname = os.path.dirname(name) + mkdirhier(dirname) + + if not os.access(dirname, os.W_OK): + logger.error("Unable to acquire lock '%s', directory is not writable", + name) + sys.exit(1) + + op = fcntl.LOCK_EX + if shared: + op = fcntl.LOCK_SH + if not retry: + op = op | fcntl.LOCK_NB + + while True: + # If we leave the lockfiles lying around there is no problem + # but we should clean up after ourselves. This gives potential + # for races though. To work around this, when we acquire the lock + # we check the file we locked was still the lock file on disk. + # by comparing inode numbers. If they don't match or the lockfile + # no longer exists, we start again. + + # This implementation is unfair since the last person to request the + # lock is the most likely to win it. + + try: + lf = open(name, 'a+') + fileno = lf.fileno() + fcntl.flock(fileno, op) + statinfo = os.fstat(fileno) + if os.path.exists(lf.name): + statinfo2 = os.stat(lf.name) + if statinfo.st_ino == statinfo2.st_ino: + return lf + lf.close() + except Exception: + try: + lf.close() + except Exception: + pass + pass + if not retry: + return None + +def unlockfile(lf): + """ + Unlock a file locked using lockfile() + """ + try: + # If we had a shared lock, we need to promote to exclusive before + # removing the lockfile. Attempt this, ignore failures. + fcntl.flock(lf.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB) + os.unlink(lf.name) + except (IOError, OSError): + pass + fcntl.flock(lf.fileno(), fcntl.LOCK_UN) + lf.close() + +def which(path, item, direction = 0, history = False): + """ + Locate a file in a PATH + """ + + hist = [] + paths = (path or "").split(':') + if direction != 0: + paths.reverse() + + for p in paths: + next = os.path.join(p, item) + hist.append(next) + if os.path.exists(next): + if not os.path.isabs(next): + next = os.path.abspath(next) + if history: + return next, hist + return next + + if history: + return "", hist + return "" + + + +# this can be used by all PM backends to create the index files in parallel +def wic_create_index(arg): + index_cmd = arg + + try: + msger.info("Executing '%s' ..." % index_cmd) + subprocess.check_output(index_cmd, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError as e: + return("Index creation command '%s' failed with return code %d:\n%s" % + (e.cmd, e.returncode, e.output)) + + return None + + +class WicIndexer(object): + __metaclass__ = ABCMeta + + def __init__(self, d, deploy_dir): + self.d = d + self.deploy_dir = deploy_dir + + @abstractmethod + def write_index(self): + pass + +class WicOpkgIndexer(WicIndexer): + def write_index(self): + arch_vars = ["ALL_MULTILIB_PACKAGE_ARCHS", + "SDK_PACKAGE_ARCHS", + "MULTILIB_ARCHS"] + + opkg_index_cmd = which(os.getenv('PATH'), "opkg-make-index") + + if not os.path.exists(os.path.join(self.deploy_dir, "Packages")): + open(os.path.join(self.deploy_dir, "Packages"), "w").close() + + index_cmds = [] + for arch_var in arch_vars: + if self.d.has_key(arch_var): + archs = self.d[arch_var] + else: + archs = None + + if archs is None: + continue + + for arch in archs.split(): + pkgs_dir = os.path.join(self.deploy_dir, arch) + pkgs_file = os.path.join(pkgs_dir, "Packages") + + if not os.path.isdir(pkgs_dir): + continue + + if not os.path.exists(pkgs_file): + open(pkgs_file, "w").close() + + index_cmds.append('%s -r %s -p %s -m %s' % + (opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir)) + + if len(index_cmds) == 0: + msger.info("There are no packages in %s!" % self.deploy_dir) + return + + nproc = multiprocessing.cpu_count() + pool = multiprocessing.Pool(nproc) + results = list(pool.imap(wic_create_index, index_cmds)) + pool.close() + pool.join() + + for result in results: + if result is not None: + return(result) + +class WicPkgsList(object): + __metaclass__ = ABCMeta + + def __init__(self, d, rootfs_dir): + self.d = d + self.rootfs_dir = rootfs_dir + + @abstractmethod + def list(self, format=None): + pass + + +class WicOpkgPkgsList(WicPkgsList): + def __init__(self, d, rootfs_dir, config_file): + super(WicOpkgPkgsList, self).__init__(d, rootfs_dir) + + self.opkg_cmd = which(os.getenv('PATH'), "opkg-cl") + self.opkg_args = "-f %s -o %s " % (config_file, rootfs_dir) + if self.d.has_key("OPKG_ARGS"): + self.opkg_args += self.d["OPKG_ARGS"] + + def list(self, format=None): + opkg_query_cmd = which(os.getenv('PATH'), "opkg-query-helper.py") + + if format == "arch": + cmd = "%s %s status | %s -a" % \ + (self.opkg_cmd, self.opkg_args, opkg_query_cmd) + elif format == "file": + cmd = "%s %s status | %s -f" % \ + (self.opkg_cmd, self.opkg_args, opkg_query_cmd) + elif format == "ver": + cmd = "%s %s status | %s -v" % \ + (self.opkg_cmd, self.opkg_args, opkg_query_cmd) + elif format == "deps": + cmd = "%s %s status | %s" % \ + (self.opkg_cmd, self.opkg_args, opkg_query_cmd) + else: + cmd = "%s %s list_installed | cut -d' ' -f1" % \ + (self.opkg_cmd, self.opkg_args) + + try: + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).strip() + except subprocess.CalledProcessError as e: + msger.error("Cannot get the installed packages list. Command '%s' " + "returned %d:\n%s" % (cmd, e.returncode, e.output)) + + if output and format == "file": + tmp_output = "" + for line in output.split('\n'): + pkg, pkg_file, pkg_arch = line.split() + full_path = os.path.join(self.rootfs_dir, pkg_arch, pkg_file) + if os.path.exists(full_path): + tmp_output += "%s %s %s\n" % (pkg, full_path, pkg_arch) + else: + tmp_output += "%s %s %s\n" % (pkg, pkg_file, pkg_arch) + + output = tmp_output + + return output + + +class WicPackageManager(object): + """ + This is an abstract class. Do not instantiate this directly. + """ + __metaclass__ = ABCMeta + + def __init__(self, d, pseudo, native_sysroot): + self.d = d + self.deploy_dir = None + self.deploy_lock = None + if self.d.has_key('PACKAGE_FEED_URIS'): + self.feed_uris = self.d['PACKAGE_FEED_URIS'] + else: + self.feed_uris = "" + self.pseudo = pseudo + self.native_sysroot = native_sysroot + + """ + Update the package manager package database. + """ + @abstractmethod + def update(self): + pass + + """ + Install a list of packages. 'pkgs' is a list object. If 'attempt_only' is + True, installation failures are ignored. + """ + @abstractmethod + def install(self, pkgs, attempt_only=False): + pass + + """ + Remove a list of packages. 'pkgs' is a list object. If 'with_dependencies' + is False, the any dependencies are left in place. + """ + @abstractmethod + def remove(self, pkgs, with_dependencies=True): + pass + + """ + This function creates the index files + """ + @abstractmethod + def write_index(self): + pass + + @abstractmethod + def remove_packaging_data(self): + pass + + @abstractmethod + def list_installed(self, format=None): + pass + + @abstractmethod + def insert_feeds_uris(self): + pass + + """ + Install complementary packages based upon the list of currently installed + packages e.g. locales, *-dev, *-dbg, etc. This will only attempt to install + these packages, if they don't exist then no error will occur. Note: every + backend needs to call this function explicitly after the normal package + installation + """ + def install_complementary(self, globs=None): + # we need to write the list of installed packages to a file because the + # oe-pkgdata-util reads it from a file + if self.d.has_key('WORKDIR'): + installed_pkgs_file = os.path.join(self.d['WORKDIR'], + "installed_pkgs.txt") + else: + msger.error("No WORKDIR provided!") + + with open(installed_pkgs_file, "w+") as installed_pkgs: + installed_pkgs.write(self.list_installed("arch")) + + if globs is None: + if self.d.has_key('IMAGE_INSTALL_COMPLEMENTARY'): + globs = self.d['IMAGE_INSTALL_COMPLEMENTARY'] + split_linguas = set() + + if self.d.has_key('IMAGE_LINGUAS'): + for translation in self.d['IMAGE_LINGUAS'].split(): + split_linguas.add(translation) + split_linguas.add(translation.split('-')[0]) + + split_linguas = sorted(split_linguas) + + for lang in split_linguas: + globs += " *-locale-%s" % lang + + if globs is None: + return + + if not self.d.has_key('PKGDATA_DIR'): + msger.error("No PKGDATA_DIR provided!") + + cmd = [which(os.getenv('PATH'), "oe-pkgdata-util"), + "glob", self.d['PKGDATA_DIR'], installed_pkgs_file, + globs] + + rc, out = exec_native_cmd(self.pseudo + cmd, self.native_sysroot) + if rc != 0: + msger.error("Could not compute complementary packages list. Command " + "'%s' returned %d" % + (' '.join(cmd), rc)) + + self.install(out.split(), attempt_only=True) + + + def deploy_dir_lock(self): + if self.deploy_dir is None: + raise RuntimeError("deploy_dir is not set!") + + lock_file_name = os.path.join(self.deploy_dir, "deploy.lock") + + self.deploy_lock = lockfile(lock_file_name) + + def deploy_dir_unlock(self): + if self.deploy_lock is None: + return + + unlockfile(self.deploy_lock) + + self.deploy_lock = None + + +class WicOpkgPM(WicPackageManager): + def __init__(self, d, target_rootfs, config_file, archs, pseudo, native_sysroot, task_name='target'): + super(WicOpkgPM, self).__init__(d, pseudo, native_sysroot) + + self.target_rootfs = target_rootfs + self.config_file = config_file + self.pkg_archs = archs + self.task_name = task_name + + if self.d.has_key("DEPLOY_DIR_IPK"): + self.deploy_dir = self.d["DEPLOY_DIR_IPK"] + + self.deploy_lock_file = os.path.join(self.deploy_dir, "deploy.lock") + self.opkg_cmd = which(os.getenv('PATH'), "opkg-cl") + self.opkg_args = "-f %s -o %s " % (self.config_file, target_rootfs) + if self.d.has_key("OPKG_ARGS"): + self.opkg_args += self.d["OPKG_ARGS"] + + if self.d.has_key('OPKGLIBDIR'): + opkg_lib_dir = self.d['OPKGLIBDIR'] + else: + opkg_lib_dir = "" + + if opkg_lib_dir[0] == "/": + opkg_lib_dir = opkg_lib_dir[1:] + + self.opkg_dir = os.path.join(target_rootfs, opkg_lib_dir, "opkg") + + mkdirhier(self.opkg_dir) + + if self.d.has_key("TMPDIR"): + tmp_dir = self.d["TMPDIR"] + else: + tmp_dir = "" + + self.saved_opkg_dir = '%s/saved/%s' % (tmp_dir, self.task_name) + if not os.path.exists('%s/saved' % tmp_dir): + mkdirhier('%s/saved' % tmp_dir) + + if self.d.has_key('BUILD_IMAGES_FROM_FEEDS') and self.d['BUILD_IMAGES_FROM_FEEDS'] != "1": + self._create_config() + else: + self._create_custom_config() + + self.indexer = WicOpkgIndexer(self.d, self.deploy_dir) + + """ + This function will change a package's status in /var/lib/opkg/status file. + If 'packages' is None then the new_status will be applied to all + packages + """ + def mark_packages(self, status_tag, packages=None): + status_file = os.path.join(self.opkg_dir, "status") + + with open(status_file, "r") as sf: + with open(status_file + ".tmp", "w+") as tmp_sf: + if packages is None: + tmp_sf.write(re.sub(r"Package: (.*?)\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)", + r"Package: \1\n\2Status: \3%s" % status_tag, + sf.read())) + else: + if type(packages).__name__ != "list": + raise TypeError("'packages' should be a list object") + + status = sf.read() + for pkg in packages: + status = re.sub(r"Package: %s\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)" % pkg, + r"Package: %s\n\1Status: \2%s" % (pkg, status_tag), + status) + + tmp_sf.write(status) + + os.rename(status_file + ".tmp", status_file) + + def _create_custom_config(self): + msger.info("Building from feeds activated!") + + with open(self.config_file, "w+") as config_file: + priority = 1 + for arch in self.pkg_archs.split(): + config_file.write("arch %s %d\n" % (arch, priority)) + priority += 5 + + if self.d.has_key('IPK_FEED_URIS'): + ipk_feed_uris = self.d['IPK_FEED_URIS'] + else: + ipk_feed_uris = "" + + for line in ipk_feed_uris.split(): + feed_match = re.match("^[ \t]*(.*)##([^ \t]*)[ \t]*$", line) + + if feed_match is not None: + feed_name = feed_match.group(1) + feed_uri = feed_match.group(2) + + msger.info("Add %s feed with URL %s" % (feed_name, feed_uri)) + + config_file.write("src/gz %s %s\n" % (feed_name, feed_uri)) + + """ + Allow to use package deploy directory contents as quick devel-testing + feed. This creates individual feed configs for each arch subdir of those + specified as compatible for the current machine. + NOTE: Development-helper feature, NOT a full-fledged feed. + """ + if self.d.has_key('FEED_DEPLOYDIR_BASE_URI'): + feed_deploydir_base_dir = self.d['FEED_DEPLOYDIR_BASE_URI'] + else: + feed_deploydir_base_dir = "" + + if feed_deploydir_base_dir != "": + for arch in self.pkg_archs.split(): + if self.d.has_key("sysconfdir"): + sysconfdir = self.d["sysconfdir"] + else: + sysconfdir = None + + cfg_file_name = os.path.join(self.target_rootfs, + sysconfdir, + "opkg", + "local-%s-feed.conf" % arch) + + with open(cfg_file_name, "w+") as cfg_file: + cfg_file.write("src/gz local-%s %s/%s" % + arch, + feed_deploydir_base_dir, + arch) + + def _create_config(self): + with open(self.config_file, "w+") as config_file: + priority = 1 + for arch in self.pkg_archs.split(): + config_file.write("arch %s %d\n" % (arch, priority)) + priority += 5 + + config_file.write("src oe file:%s\n" % self.deploy_dir) + + for arch in self.pkg_archs.split(): + pkgs_dir = os.path.join(self.deploy_dir, arch) + if os.path.isdir(pkgs_dir): + config_file.write("src oe-%s file:%s\n" % + (arch, pkgs_dir)) + + def insert_feeds_uris(self): + if self.feed_uris == "": + return + + rootfs_config = os.path.join('%s/etc/opkg/base-feeds.conf' + % self.target_rootfs) + + with open(rootfs_config, "w+") as config_file: + uri_iterator = 0 + for uri in self.feed_uris.split(): + config_file.write("src/gz url-%d %s/ipk\n" % + (uri_iterator, uri)) + + for arch in self.pkg_archs.split(): + if not os.path.exists(os.path.join(self.deploy_dir, arch)): + continue + msger.info('Note: adding opkg channel url-%s-%d (%s)' % + (arch, uri_iterator, uri)) + + config_file.write("src/gz uri-%s-%d %s/ipk/%s\n" % + (arch, uri_iterator, uri, arch)) + uri_iterator += 1 + + def update(self): + self.deploy_dir_lock() + + cmd = "%s %s update" % (self.opkg_cmd, self.opkg_args) + + rc, out = exec_native_cmd(self.pseudo + cmd, self.native_sysroot) + if rc != 0: + self.deploy_dir_unlock() + msger.error("Unable to update the package index files. Command '%s' " + "returned %d" % (cmd, rc)) + + self.deploy_dir_unlock() + + def install(self, pkgs, attempt_only=False): + if attempt_only and len(pkgs) == 0: + return + + cmd = "%s %s install %s" % (self.opkg_cmd, self.opkg_args, ' '.join(pkgs)) + + os.environ['D'] = self.target_rootfs + os.environ['OFFLINE_ROOT'] = self.target_rootfs + os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs + os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs + if self.d.has_key('WORKDIR'): + os.environ['INTERCEPT_DIR'] = os.path.join(self.d['WORKDIR'], + "intercept_scripts") + else: + os.environ['INTERCEPT_DIR'] = "." + msger.warning("No WORKDIR provided!") + + if self.d.has_key('STAGING_DIR_NATIVE'): + os.environ['NATIVE_ROOT'] = self.d['STAGING_DIR_NATIVE'] + else: + msger.error("No STAGING_DIR_NATIVE provided!") + + rc, out = exec_native_cmd(self.pseudo + cmd, self.native_sysroot) + if rc != 0: + msger.error("Unable to install packages. " + "Command '%s' returned %d" % (cmd, rc)) + + + def remove(self, pkgs, with_dependencies=True): + if with_dependencies: + cmd = "%s %s --force-depends --force-remove --force-removal-of-dependent-packages remove %s" % \ + (self.opkg_cmd, self.opkg_args, ' '.join(pkgs)) + else: + cmd = "%s %s --force-depends remove %s" % \ + (self.opkg_cmd, self.opkg_args, ' '.join(pkgs)) + + rc, out = exec_native_cmd(self.pseudo + cmd, self.native_sysroot) + if rc != 0: + msger.error("Unable to remove packages. Command '%s' " + "returned %d" % (cmd, rc)) + + + def write_index(self): + self.deploy_dir_lock() + + result = self.indexer.write_index() + + self.deploy_dir_unlock() + + if result is not None: + msger.error(result) + + def remove_packaging_data(self): + remove(self.opkg_dir, True) + # create the directory back, it's needed by PM lock + mkdirhier(self.opkg_dir) + + def list_installed(self, format=None): + return WicOpkgPkgsList(self.d, self.target_rootfs, self.config_file).list(format) + + def handle_bad_recommendations(self): + if self.d.has_key("BAD_RECOMMENDATIONS"): + bad_recommendations = self.d["BAD_RECOMMENDATIONS"] + else: + bad_recommendations = "" + + if bad_recommendations.strip() == "": + return + + status_file = os.path.join(self.opkg_dir, "status") + + # If status file existed, it means the bad recommendations has already + # been handled + if os.path.exists(status_file): + return + + cmd = "%s %s info " % (self.opkg_cmd, self.opkg_args) + + with open(status_file, "w+") as status: + for pkg in bad_recommendations.split(): + pkg_info = cmd + pkg + + try: + output = subprocess.check_output(pkg_info.split(), stderr=subprocess.STDOUT).strip() + except subprocess.CalledProcessError as e: + msger.error("Cannot get package info. Command '%s' " + "returned %d:\n%s" % (pkg_info, e.returncode, e.output)) + + if output == "": + msger.info("Ignored bad recommendation: '%s' is " + "not a package" % pkg) + continue + + for line in output.split('\n'): + if line.startswith("Status:"): + status.write("Status: deinstall hold not-installed\n") + else: + status.write(line + "\n") + + ''' + The following function dummy installs pkgs and returns the log of output. + ''' + def dummy_install(self, pkgs): + if len(pkgs) == 0: + return + + # Create an temp dir as opkg root for dummy installation + if self.d.has_key("TMPDIR"): + tmp_dir = self.d["TMPDIR"] + else: + tmp_dir = "." + msger.warning("No TMPDIR provided!") + + temp_rootfs = '%s/opkg' % tmp_dir + temp_opkg_dir = os.path.join(temp_rootfs, 'var/lib/opkg') + mkdirhier(temp_opkg_dir) + + opkg_args = "-f %s -o %s " % (self.config_file, temp_rootfs) + if self.d.has_key("OPKG_ARGS"): + opkg_args += self.d["OPKG_ARGS"] + + cmd = "%s %s update" % (self.opkg_cmd, opkg_args) + try: + subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError as e: + msger.error("Unable to update. Command '%s' " + "returned %d:\n%s" % (cmd, e.returncode, e.output)) + + # Dummy installation + cmd = "%s %s --noaction install %s " % (self.opkg_cmd, + opkg_args, + ' '.join(pkgs)) + try: + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError as e: + msger.error("Unable to dummy install packages. Command '%s' " + "returned %d:\n%s" % (cmd, e.returncode, e.output)) + + remove(temp_rootfs, True) + + return output + + def backup_packaging_data(self): + # Save the opkglib for increment ipk image generation + if os.path.exists(self.saved_opkg_dir): + remove(self.saved_opkg_dir, True) + shutil.copytree(self.opkg_dir, + self.saved_opkg_dir, + symlinks=True) + + def recover_packaging_data(self): + # Move the opkglib back + if os.path.exists(self.saved_opkg_dir): + if os.path.exists(self.opkg_dir): + remove(self.opkg_dir, True) + + msger.info('Recover packaging data') + shutil.copytree(self.saved_opkg_dir, + self.opkg_dir, + symlinks=True) + + +def wic_generate_index_files(d): + if d.has_key('PACKAGE_CLASSES'): + classes = d['PACKAGE_CLASSES'].replace("package_", "").split() + else: + classes = "" + msger.warning("No PACKAGE_CLASSES provided!") + + if d.has_key('DEPLOY_DIR_IPK'): + deploy_dir_ipk = d['DEPLOY_DIR_IPK'] + else: + deploy_dir_ipk = None + msger.warning("No DEPLOY_DIR_IPK provided!") + + indexer_map = { + "ipk": (WicOpkgIndexer, deploy_dir_ipk) + } + + result = None + + for pkg_class in classes: + if not pkg_class in indexer_map: + continue + + if os.path.exists(indexer_map[pkg_class][1]): + result = indexer_map[pkg_class][0](d, indexer_map[pkg_class][1]).write_index() + + if result is not None: + msger.error(result) diff --git a/scripts/lib/wic/utils/partitionedfs.py b/scripts/lib/wic/utils/partitionedfs.py new file mode 100644 index 0000000000..fb95cc790e --- /dev/null +++ b/scripts/lib/wic/utils/partitionedfs.py @@ -0,0 +1,360 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2009, 2010, 2011 Intel, Inc. +# Copyright (c) 2007, 2008 Red Hat, Inc. +# Copyright (c) 2008 Daniel P. Berrange +# Copyright (c) 2008 David P. Huff +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os + +from wic import msger +from wic.utils import runner +from wic.utils.errors import ImageError +from wic.utils.fs_related import * +from wic.utils.oe.misc import * + +# Overhead of the MBR partitioning scheme (just one sector) +MBR_OVERHEAD = 1 + +# Size of a sector in bytes +SECTOR_SIZE = 512 + +class Image: + """ + Generic base object for an image. + + An Image is a container for a set of DiskImages and associated + partitions. + """ + def __init__(self): + self.disks = {} + self.partitions = [] + self.parted = find_binary_path("parted") + # Size of a sector used in calculations + self.sector_size = SECTOR_SIZE + self._partitions_layed_out = False + + def __add_disk(self, disk_name): + """ Add a disk 'disk_name' to the internal list of disks. Note, + 'disk_name' is the name of the disk in the target system + (e.g., sdb). """ + + if disk_name in self.disks: + # We already have this disk + return + + assert not self._partitions_layed_out + + self.disks[disk_name] = \ + { 'disk': None, # Disk object + 'numpart': 0, # Number of allocate partitions + 'partitions': [], # Indexes to self.partitions + 'offset': 0, # Offset of next partition (in sectors) + # Minimum required disk size to fit all partitions (in bytes) + 'min_size': 0, + 'ptable_format': "msdos" } # Partition table format + + def add_disk(self, disk_name, disk_obj): + """ Add a disk object which have to be partitioned. More than one disk + can be added. In case of multiple disks, disk partitions have to be + added for each disk separately with 'add_partition()". """ + + self.__add_disk(disk_name) + self.disks[disk_name]['disk'] = disk_obj + + def __add_partition(self, part): + """ This is a helper function for 'add_partition()' which adds a + partition to the internal list of partitions. """ + + assert not self._partitions_layed_out + + self.partitions.append(part) + self.__add_disk(part['disk_name']) + + def add_partition(self, size, disk_name, mountpoint, source_file = None, fstype = None, + label=None, fsopts = None, boot = False, align = None, + part_type = None): + """ Add the next partition. Prtitions have to be added in the + first-to-last order. """ + + ks_pnum = len(self.partitions) + + # Converting MB to sectors for parted + size = size * 1024 * 1024 / self.sector_size + + # We still need partition for "/" or non-subvolume + if mountpoint == "/" or not fsopts: + part = { 'ks_pnum' : ks_pnum, # Partition number in the KS file + 'size': size, # In sectors + 'mountpoint': mountpoint, # Mount relative to chroot + 'source_file': source_file, # partition contents + 'fstype': fstype, # Filesystem type + 'fsopts': fsopts, # Filesystem mount options + 'label': label, # Partition label + 'disk_name': disk_name, # physical disk name holding partition + 'device': None, # kpartx device node for partition + 'num': None, # Partition number + 'boot': boot, # Bootable flag + 'align': align, # Partition alignment + 'part_type' : part_type } # Partition type + + self.__add_partition(part) + + def layout_partitions(self, ptable_format = "msdos"): + """ Layout the partitions, meaning calculate the position of every + partition on the disk. The 'ptable_format' parameter defines the + partition table format and may be "msdos". """ + + msger.debug("Assigning %s partitions to disks" % ptable_format) + + if ptable_format not in ('msdos'): + raise ImageError("Unknown partition table format '%s', supported " \ + "formats are: 'msdos'" % ptable_format) + + if self._partitions_layed_out: + return + + self._partitions_layed_out = True + + # Go through partitions in the order they are added in .ks file + for n in range(len(self.partitions)): + p = self.partitions[n] + + if not self.disks.has_key(p['disk_name']): + raise ImageError("No disk %s for partition %s" \ + % (p['disk_name'], p['mountpoint'])) + + if p['part_type']: + # The --part-type can also be implemented for MBR partitions, + # in which case it would map to the 1-byte "partition type" + # filed at offset 3 of the partition entry. + raise ImageError("setting custom partition type is not " \ + "implemented for msdos partitions") + + # Get the disk where the partition is located + d = self.disks[p['disk_name']] + d['numpart'] += 1 + d['ptable_format'] = ptable_format + + if d['numpart'] == 1: + if ptable_format == "msdos": + overhead = MBR_OVERHEAD + + # Skip one sector required for the partitioning scheme overhead + d['offset'] += overhead + + if p['align']: + # If not first partition and we do have alignment set we need + # to align the partition. + # FIXME: This leaves a empty spaces to the disk. To fill the + # gaps we could enlargea the previous partition? + + # Calc how much the alignment is off. + align_sectors = d['offset'] % (p['align'] * 1024 / self.sector_size) + + if align_sectors: + # If partition is not aligned as required, we need + # to move forward to the next alignment point + align_sectors = (p['align'] * 1024 / self.sector_size) - align_sectors + + msger.debug("Realignment for %s%s with %s sectors, original" + " offset %s, target alignment is %sK." % + (p['disk_name'], d['numpart'], align_sectors, + d['offset'], p['align'])) + + # increase the offset so we actually start the partition on right alignment + d['offset'] += align_sectors + + p['start'] = d['offset'] + d['offset'] += p['size'] + + p['type'] = 'primary' + p['num'] = d['numpart'] + + if d['ptable_format'] == "msdos": + if d['numpart'] > 2: + # Every logical partition requires an additional sector for + # the EBR, so steal the last sector from the end of each + # partition starting from the 3rd one for the EBR. This + # will make sure the logical partitions are aligned + # correctly. + p['size'] -= 1 + + if d['numpart'] > 3: + p['type'] = 'logical' + p['num'] = d['numpart'] + 1 + + d['partitions'].append(n) + msger.debug("Assigned %s to %s%d, sectors range %d-%d size %d " + "sectors (%d bytes)." \ + % (p['mountpoint'], p['disk_name'], p['num'], + p['start'], p['start'] + p['size'] - 1, + p['size'], p['size'] * self.sector_size)) + + # Once all the partitions have been layed out, we can calculate the + # minumim disk sizes. + for disk_name, d in self.disks.items(): + d['min_size'] = d['offset'] + + d['min_size'] *= self.sector_size + + def __run_parted(self, args): + """ Run parted with arguments specified in the 'args' list. """ + + args.insert(0, self.parted) + msger.debug(args) + + rc, out = runner.runtool(args, catch = 3) + out = out.strip() + if out: + msger.debug('"parted" output: %s' % out) + + if rc != 0: + # We don't throw exception when return code is not 0, because + # parted always fails to reload part table with loop devices. This + # prevents us from distinguishing real errors based on return + # code. + msger.error("WARNING: parted returned '%s' instead of 0 (use --debug for details)" % rc) + + def __create_partition(self, device, parttype, fstype, start, size): + """ Create a partition on an image described by the 'device' object. """ + + # Start is included to the size so we need to substract one from the end. + end = start + size - 1 + msger.debug("Added '%s' partition, sectors %d-%d, size %d sectors" % + (parttype, start, end, size)) + + args = ["-s", device, "unit", "s", "mkpart", parttype] + if fstype: + args.extend([fstype]) + args.extend(["%d" % start, "%d" % end]) + + return self.__run_parted(args) + + def __format_disks(self): + self.layout_partitions() + + for dev in self.disks.keys(): + d = self.disks[dev] + msger.debug("Initializing partition table for %s" % \ + (d['disk'].device)) + self.__run_parted(["-s", d['disk'].device, "mklabel", + d['ptable_format']]) + + msger.debug("Creating partitions") + + for p in self.partitions: + d = self.disks[p['disk_name']] + if d['ptable_format'] == "msdos" and p['num'] == 5: + # The last sector of the 3rd partition was reserved for the EBR + # of the first _logical_ partition. This is why the extended + # partition should start one sector before the first logical + # partition. + self.__create_partition(d['disk'].device, "extended", + None, p['start'] - 1, + d['offset'] - p['start']) + + if p['fstype'] == "swap": + parted_fs_type = "linux-swap" + elif p['fstype'] == "vfat": + parted_fs_type = "fat32" + elif p['fstype'] == "msdos": + parted_fs_type = "fat16" + else: + # Type for ext2/ext3/ext4/btrfs + parted_fs_type = "ext2" + + # Boot ROM of OMAP boards require vfat boot partition to have an + # even number of sectors. + if p['mountpoint'] == "/boot" and p['fstype'] in ["vfat", "msdos"] \ + and p['size'] % 2: + msger.debug("Substracting one sector from '%s' partition to " \ + "get even number of sectors for the partition" % \ + p['mountpoint']) + p['size'] -= 1 + + self.__create_partition(d['disk'].device, p['type'], + parted_fs_type, p['start'], p['size']) + + if p['boot']: + flag_name = "boot" + msger.debug("Set '%s' flag for partition '%s' on disk '%s'" % \ + (flag_name, p['num'], d['disk'].device)) + self.__run_parted(["-s", d['disk'].device, "set", + "%d" % p['num'], flag_name, "on"]) + + # Parted defaults to enabling the lba flag for fat16 partitions, + # which causes compatibility issues with some firmware (and really + # isn't necessary). + if parted_fs_type == "fat16": + if d['ptable_format'] == 'msdos': + msger.debug("Disable 'lba' flag for partition '%s' on disk '%s'" % \ + (p['num'], d['disk'].device)) + self.__run_parted(["-s", d['disk'].device, "set", + "%d" % p['num'], "lba", "off"]) + + def cleanup(self): + if self.disks: + for dev in self.disks.keys(): + d = self.disks[dev] + try: + d['disk'].cleanup() + except: + pass + + def __write_partition(self, num, source_file, start, size): + """ + Install source_file contents into a partition. + """ + if not source_file: # nothing to write + return + + # Start is included in the size so need to substract one from the end. + end = start + size - 1 + msger.debug("Installed %s in partition %d, sectors %d-%d, size %d sectors" % (source_file, num, start, end, size)) + + dd_cmd = "dd if=%s of=%s bs=%d seek=%d count=%d conv=notrunc" % \ + (source_file, self.image_file, self.sector_size, start, size) + exec_cmd(dd_cmd) + + + def assemble(self, image_file): + msger.debug("Installing partitions") + + self.image_file = image_file + + for p in self.partitions: + d = self.disks[p['disk_name']] + if d['ptable_format'] == "msdos" and p['num'] == 5: + # The last sector of the 3rd partition was reserved for the EBR + # of the first _logical_ partition. This is why the extended + # partition should start one sector before the first logical + # partition. + self.__write_partition(p['num'], p['source_file'], + p['start'] - 1, + d['offset'] - p['start']) + + self.__write_partition(p['num'], p['source_file'], + p['start'], p['size']) + + def create(self): + for dev in self.disks.keys(): + d = self.disks[dev] + d['disk'].create() + + self.__format_disks() + + return diff --git a/scripts/lib/wic/utils/runner.py b/scripts/lib/wic/utils/runner.py new file mode 100644 index 0000000000..2ae9f417c5 --- /dev/null +++ b/scripts/lib/wic/utils/runner.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python -tt +# +# Copyright (c) 2011 Intel, Inc. +# +# 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; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import os +import subprocess + +from wic import msger + +def runtool(cmdln_or_args, catch=1): + """ wrapper for most of the subprocess calls + input: + cmdln_or_args: can be both args and cmdln str (shell=True) + catch: 0, quitely run + 1, only STDOUT + 2, only STDERR + 3, both STDOUT and STDERR + return: + (rc, output) + if catch==0: the output will always None + """ + + if catch not in (0, 1, 2, 3): + # invalid catch selection, will cause exception, that's good + return None + + if isinstance(cmdln_or_args, list): + cmd = cmdln_or_args[0] + shell = False + else: + import shlex + cmd = shlex.split(cmdln_or_args)[0] + shell = True + + if catch != 3: + dev_null = os.open("/dev/null", os.O_WRONLY) + + if catch == 0: + sout = dev_null + serr = dev_null + elif catch == 1: + sout = subprocess.PIPE + serr = dev_null + elif catch == 2: + sout = dev_null + serr = subprocess.PIPE + elif catch == 3: + sout = subprocess.PIPE + serr = subprocess.STDOUT + + try: + p = subprocess.Popen(cmdln_or_args, stdout=sout, + stderr=serr, shell=shell) + (sout, serr) = p.communicate() + # combine stdout and stderr, filter None out + out = ''.join(filter(None, [sout, serr])) + except OSError, e: + if e.errno == 2: + # [Errno 2] No such file or directory + msger.error('Cannot run command: %s, lost dependency?' % cmd) + else: + raise # relay + finally: + if catch != 3: + os.close(dev_null) + + return (p.returncode, out) + +def show(cmdln_or_args): + # show all the message using msger.verbose + + rc, out = runtool(cmdln_or_args, catch=3) + + if isinstance(cmdln_or_args, list): + cmd = ' '.join(cmdln_or_args) + else: + cmd = cmdln_or_args + + msg = 'running command: "%s"' % cmd + if out: out = out.strip() + if out: + msg += ', with output::' + msg += '\n +----------------' + for line in out.splitlines(): + msg += '\n | %s' % line + msg += '\n +----------------' + + msger.verbose(msg) + return rc + +def outs(cmdln_or_args, catch=1): + # get the outputs of tools + return runtool(cmdln_or_args, catch)[1].strip() + +def quiet(cmdln_or_args): + return runtool(cmdln_or_args, catch=0)[0] -- cgit v1.2.3-54-g00ecf