diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 66fd13c90..000000000
--- a/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Test binary, built with `go test -c`
-*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
-
-# Dependency directories (remove the comment below to include it)
-# vendor/
diff --git a/README.md b/README.md
deleted file mode 100644
index 32459150d..000000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# distros
-These are mutually dependent distros that use u-root. This includes weboot, NiChrome, and other images.
diff --git a/nichrome/.github/workflows/go.yml b/nichrome/.github/workflows/go.yml
new file mode 100644
index 000000000..51f71649c
--- /dev/null
+++ b/nichrome/.github/workflows/go.yml
@@ -0,0 +1,24 @@
+name: Go
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Go
+ uses: actions/setup-go@v2
+ with:
+ go-version: 1.17
+
+ - name: Build
+ run: (cd usb && go build .)
+ - name: usb
+ run: ./usb/usb -fetch
diff --git a/nichrome/.gitignore b/nichrome/.gitignore
new file mode 100644
index 000000000..e9e0554ec
--- /dev/null
+++ b/nichrome/.gitignore
@@ -0,0 +1,27 @@
+nocontent.efi
+linux-stable
+linux-firmware
+vboot_reference
+config.txt
+newKern
+usb/usb
+*.cpio
+*~
+uinit/uinit
+tcz/
+.bb/
+
+# definitely ignore upspin! It may have keys.
+upspin/
+
+# and ignore .ssh. We DO NOT pull in ~/.ssh.
+# if you want .ssh config stuff, you have to put it here.
+# This still scares me however. We might want to make
+# it not a . file -- they're dangerous.
+.ssh/
+
+# Also ignore etc
+etc/
+
+# we install binaries into usr/bin, ignore it.
+usr/bin/
diff --git a/nichrome/.travis.yml b/nichrome/.travis.yml
new file mode 100644
index 000000000..9c6882d46
--- /dev/null
+++ b/nichrome/.travis.yml
@@ -0,0 +1,27 @@
+sudo: true
+language: go
+go:
+ - 1.12.x
+env:
+ - "PATH=/home/travis/gopath/bin:$PATH"
+addons:
+ apt:
+ packages:
+ - gcc-4.8
+ - bc
+ - uuid-dev
+before_install:
+ - pwd
+ - ls -l
+install:
+ - ls
+ - curl -L -o /home/travis/gopath/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64
+ - chmod +x /home/travis/gopath/bin/dep
+script:
+ - cat travis.sh
+ - bash travis.sh
+after_success:
+ - if [ "$TRAVIS_BRANCH" == "master" ]; then ghr --username u-root --token $GITHUB_TOKEN --replace --prerelease --debug `git describe --always` dist/; fi
+
+notifications:
+ slack: u-root:S74GnNB8ekAiqNYTjwbEhkQE
diff --git a/nichrome/CONFIG b/nichrome/CONFIG
new file mode 100644
index 000000000..05f2e9b04
--- /dev/null
+++ b/nichrome/CONFIG
@@ -0,0 +1,6148 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86_64 5.10.0 Kernel Configuration
+#
+CONFIG_CC_VERSION_TEXT="gcc (Ubuntu 10.3.0-1ubuntu1~20.10) 10.3.0"
+CONFIG_CC_IS_GCC=y
+CONFIG_GCC_VERSION=100300
+CONFIG_LD_VERSION=235010000
+CONFIG_CLANG_VERSION=0
+CONFIG_LLD_VERSION=0
+CONFIG_CC_CAN_LINK=y
+CONFIG_CC_CAN_LINK_STATIC=y
+CONFIG_CC_HAS_ASM_GOTO=y
+CONFIG_CC_HAS_ASM_INLINE=y
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_TABLE_SORT=y
+CONFIG_THREAD_INFO_IN_TASK=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_BUILD_SALT=""
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_HAVE_KERNEL_ZSTD=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_ZSTD is not set
+CONFIG_DEFAULT_INIT=""
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_WATCH_QUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_GENERIC_IRQ_MIGRATION=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+CONFIG_IRQ_MSI_IOMMU=y
+CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
+CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_GENERIC_IRQ_DEBUGFS is not set
+# end of IRQ subsystem
+
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
+CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
+CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+# CONFIG_NO_HZ_FULL is not set
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+# end of Timers subsystem
+
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_PREEMPTION=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_PSI is not set
+# end of CPU/Task time and stats accounting
+
+CONFIG_CPU_ISOLATION=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+CONFIG_PREEMPT_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_TASKS_RCU_GENERIC=y
+CONFIG_TASKS_RCU=y
+CONFIG_TASKS_RUDE_RCU=y
+CONFIG_TASKS_TRACE_RCU=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+# end of RCU Subsystem
+
+# CONFIG_IKCONFIG is not set
+# CONFIG_IKHEADERS is not set
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+
+#
+# Scheduler features
+#
+# CONFIG_UCLAMP_TASK is not set
+# end of Scheduler features
+
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
+CONFIG_CC_HAS_INT128=y
+CONFIG_ARCH_SUPPORTS_INT128=y
+CONFIG_CGROUPS=y
+CONFIG_PAGE_COUNTER=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_WRITEBACK=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+# CONFIG_CGROUP_RDMA is not set
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+# CONFIG_CGROUP_BPF is not set
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_TIME_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="initramfs.linux_amd64.cpio"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_RD_ZSTD is not set
+CONFIG_INITRAMFS_COMPRESSION_LZMA=y
+# CONFIG_INITRAMFS_COMPRESSION_NONE is not set
+# CONFIG_BOOT_CONFIG is not set
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_LD_ORPHAN_WARN=y
+CONFIG_SYSCTL=y
+CONFIG_HAVE_UID16=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+CONFIG_SGETMASK_SYSCALL=y
+CONFIG_SYSFS_SYSCALL=y
+CONFIG_FHANDLE=y
+CONFIG_POSIX_TIMERS=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_FUTEX_PI=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_IO_URING=y
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_MEMBARRIER=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y
+# CONFIG_BPF_PRELOAD is not set
+# CONFIG_USERFAULTFD is not set
+CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
+CONFIG_RSEQ=y
+# CONFIG_DEBUG_RSEQ is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+# CONFIG_PC104 is not set
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+# end of Kernel Performance Events And Counters
+
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLUB_MEMCG_SYSFS_ON is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_SLAB_MERGE_DEFAULT=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SLAB_FREELIST_HARDENED is not set
+# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_SYSTEM_DATA_VERIFICATION=y
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# end of General setup
+
+CONFIG_64BIT=y
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=28
+CONFIG_ARCH_MMAP_RND_BITS_MAX=32
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_FILTER_PGPROT=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ZONE_DMA32=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_HAVE_INTEL_TXT=y
+CONFIG_X86_64_SMP=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_PGTABLE_LEVELS=4
+CONFIG_CC_HAS_SANE_STACKPROTECTOR=y
+
+#
+# Processor type and features
+#
+CONFIG_ZONE_DMA=y
+CONFIG_SMP=y
+CONFIG_X86_FEATURE_NAMES=y
+CONFIG_X86_X2APIC=y
+# CONFIG_X86_MPPARSE is not set
+# CONFIG_GOLDFISH is not set
+CONFIG_RETPOLINE=y
+# CONFIG_X86_CPU_RESCTRL is not set
+# CONFIG_X86_EXTENDED_PLATFORM is not set
+CONFIG_X86_INTEL_LPSS=y
+# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
+CONFIG_IOSF_MBI=y
+CONFIG_IOSF_MBI_DEBUG=y
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_HYPERVISOR_GUEST=y
+CONFIG_PARAVIRT=y
+# CONFIG_PARAVIRT_DEBUG is not set
+CONFIG_PARAVIRT_SPINLOCKS=y
+CONFIG_X86_HV_CALLBACK_VECTOR=y
+# CONFIG_XEN is not set
+CONFIG_KVM_GUEST=y
+CONFIG_ARCH_CPUIDLE_HALTPOLL=y
+# CONFIG_PVH is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+CONFIG_PARAVIRT_CLOCK=y
+# CONFIG_JAILHOUSE_GUEST is not set
+# CONFIG_ACRN_GUEST is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_IA32_FEAT_CTL=y
+CONFIG_X86_VMX_FEATURE_NAMES=y
+CONFIG_PROCESSOR_SELECT=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+# CONFIG_CPU_SUP_HYGON is not set
+# CONFIG_CPU_SUP_CENTAUR is not set
+# CONFIG_CPU_SUP_ZHAOXIN is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+# CONFIG_GART_IOMMU is not set
+# CONFIG_MAXSMP is not set
+CONFIG_NR_CPUS_RANGE_BEGIN=2
+CONFIG_NR_CPUS_RANGE_END=512
+CONFIG_NR_CPUS_DEFAULT=64
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+# CONFIG_SCHED_MC is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCELOG_LEGACY is not set
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_AMD=y
+CONFIG_X86_MCE_THRESHOLD=y
+# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_THERMAL_VECTOR=y
+
+#
+# Performance monitoring
+#
+CONFIG_PERF_EVENTS_INTEL_UNCORE=y
+CONFIG_PERF_EVENTS_INTEL_RAPL=y
+CONFIG_PERF_EVENTS_INTEL_CSTATE=y
+# CONFIG_PERF_EVENTS_AMD_POWER is not set
+# end of Performance monitoring
+
+CONFIG_X86_16BIT=y
+CONFIG_X86_ESPFIX64=y
+# CONFIG_X86_VSYSCALL_EMULATION is not set
+CONFIG_X86_IOPL_IOPERM=y
+# CONFIG_I8K is not set
+CONFIG_MICROCODE=y
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+# CONFIG_X86_5LEVEL is not set
+CONFIG_X86_DIRECT_GBPAGES=y
+# CONFIG_X86_CPA_STATISTICS is not set
+# CONFIG_AMD_MEM_ENCRYPT is not set
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+# CONFIG_X86_PMEM_LEGACY is not set
+CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
+CONFIG_X86_RESERVE_LOW=64
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+CONFIG_ARCH_RANDOM=y
+CONFIG_X86_SMAP=y
+CONFIG_X86_UMIP=y
+CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y
+CONFIG_X86_INTEL_TSX_MODE_OFF=y
+# CONFIG_X86_INTEL_TSX_MODE_ON is not set
+# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
+# CONFIG_EFI is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_KEXEC_FILE is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_RELOCATABLE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_X86_NEED_RELOCS=y
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_DYNAMIC_MEMORY_LAYOUT=y
+CONFIG_RANDOMIZE_MEMORY=y
+CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set
+# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_LEGACY_VSYSCALL_EMULATE=y
+# CONFIG_LEGACY_VSYSCALL_XONLY is not set
+# CONFIG_LEGACY_VSYSCALL_NONE is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MODIFY_LDT_SYSCALL=y
+CONFIG_HAVE_LIVEPATCH=y
+# end of Processor type and features
+
+CONFIG_ARCH_HAS_ADD_PAGES=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_ARCH_HIBERNATION_HEADER=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_SUSPEND_SKIP_SYNC is not set
+CONFIG_HIBERNATE_CALLBACKS=y
+CONFIG_HIBERNATION=y
+CONFIG_HIBERNATION_SNAPSHOT_DEV=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_AUTOSLEEP is not set
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=100
+CONFIG_PM_WAKELOCKS_GC=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_PM_SLEEP_DEBUG=y
+# CONFIG_DPM_WATCHDOG is not set
+CONFIG_PM_TRACE=y
+CONFIG_PM_TRACE_RTC=y
+CONFIG_PM_CLK=y
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
+# CONFIG_ENERGY_MODEL is not set
+CONFIG_ARCH_SUPPORTS_ACPI=y
+CONFIG_ACPI=y
+CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
+CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
+CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
+# CONFIG_ACPI_DEBUGGER is not set
+# CONFIG_ACPI_SPCR_TABLE is not set
+CONFIG_ACPI_LPIT=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y
+CONFIG_ACPI_EC_DEBUGFS=y
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+CONFIG_ACPI_VIDEO=y
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_TAD is not set
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_CPU_FREQ_PSS=y
+CONFIG_ACPI_PROCESSOR_CSTATE=y
+CONFIG_ACPI_PROCESSOR_IDLE=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_IPMI=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_PROCESSOR_AGGREGATOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_CUSTOM_DSDT_FILE=""
+CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
+CONFIG_ACPI_TABLE_UPGRADE=y
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_HOTPLUG_IOAPIC=y
+CONFIG_ACPI_SBS=y
+CONFIG_ACPI_HED=y
+# CONFIG_ACPI_CUSTOM_METHOD is not set
+# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
+# CONFIG_ACPI_NFIT is not set
+CONFIG_HAVE_ACPI_APEI=y
+CONFIG_HAVE_ACPI_APEI_NMI=y
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=y
+CONFIG_ACPI_APEI_PCIEAER=y
+CONFIG_ACPI_APEI_MEMORY_FAILURE=y
+CONFIG_ACPI_APEI_EINJ=y
+# CONFIG_ACPI_APEI_ERST_DEBUG is not set
+# CONFIG_ACPI_DPTF is not set
+# CONFIG_ACPI_CONFIGFS is not set
+# CONFIG_PMIC_OPREGION is not set
+CONFIG_X86_PM_TIMER=y
+CONFIG_SFI=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+
+#
+# CPU frequency scaling drivers
+#
+CONFIG_X86_INTEL_PSTATE=y
+CONFIG_X86_PCC_CPUFREQ=y
+CONFIG_X86_ACPI_CPUFREQ=y
+CONFIG_X86_ACPI_CPUFREQ_CPB=y
+# CONFIG_X86_POWERNOW_K8 is not set
+# CONFIG_X86_AMD_FREQ_SENSITIVITY is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_P4_CLOCKMOD is not set
+
+#
+# shared options
+#
+# end of CPU Frequency scaling
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_CPU_IDLE_GOV_TEO is not set
+# CONFIG_CPU_IDLE_GOV_HALTPOLL is not set
+CONFIG_HALTPOLL_CPUIDLE=y
+# end of CPU Idle
+
+CONFIG_INTEL_IDLE=y
+# end of Power management and ACPI options
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_MMCONF_FAM10H=y
+# CONFIG_PCI_CNB20LE_QUIRK is not set
+# CONFIG_ISA_BUS is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_AMD_NB=y
+# CONFIG_X86_SYSFB is not set
+# end of Bus options (PCI etc.)
+
+#
+# Binary Emulations
+#
+CONFIG_IA32_EMULATION=y
+CONFIG_X86_X32=y
+CONFIG_COMPAT_32=y
+CONFIG_COMPAT=y
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_SYSVIPC_COMPAT=y
+# end of Binary Emulations
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DMIID=y
+CONFIG_DMI_SYSFS=y
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_GOOGLE_FIRMWARE=y
+# CONFIG_GOOGLE_SMI is not set
+CONFIG_GOOGLE_COREBOOT_TABLE=y
+CONFIG_GOOGLE_MEMCONSOLE=y
+# CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY is not set
+CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=y
+CONFIG_GOOGLE_VPD=y
+CONFIG_UEFI_CPER=y
+CONFIG_UEFI_CPER_X86=y
+
+#
+# Tegra firmware driver
+#
+# end of Tegra firmware driver
+# end of Firmware Drivers
+
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+CONFIG_AS_AVX512=y
+CONFIG_AS_SHA1_NI=y
+CONFIG_AS_SHA256_NI=y
+CONFIG_AS_TPAUSE=y
+
+#
+# General architecture-dependent options
+#
+CONFIG_CRASH_CORE=y
+CONFIG_HOTPLUG_SMT=y
+CONFIG_GENERIC_ENTRY=y
+CONFIG_OPROFILE=y
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_STATIC_CALL_SELFTEST is not set
+CONFIG_UPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_HAVE_ASM_MODVERSIONS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
+CONFIG_MMU_GATHER_TABLE_FREE=y
+CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
+CONFIG_HAVE_ARCH_SECCOMP=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_STACKLEAK=y
+CONFIG_HAVE_STACKPROTECTOR=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOVE_PMD=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_HAVE_ARCH_SOFT_DIRTY=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS=28
+CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
+CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
+CONFIG_HAVE_STACK_VALIDATION=y
+CONFIG_HAVE_RELIABLE_STACKTRACE=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_HAVE_ARCH_VMAP_STACK=y
+CONFIG_VMAP_STACK=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
+# CONFIG_LOCK_EVENT_COUNTS is not set
+CONFIG_ARCH_HAS_MEM_ENCRYPT=y
+CONFIG_HAVE_STATIC_CALL=y
+CONFIG_HAVE_STATIC_CALL_INLINE=y
+CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+# end of GCOV-based kernel profiling
+
+CONFIG_HAVE_GCC_PLUGINS=y
+# end of General architecture-dependent options
+
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BLK_CGROUP_RWSTAT=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_INTEGRITY_T10=y
+# CONFIG_BLK_DEV_ZONED is not set
+CONFIG_BLK_DEV_THROTTLING=y
+# CONFIG_BLK_DEV_THROTTLING_LOW is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+# CONFIG_BLK_WBT is not set
+# CONFIG_BLK_CGROUP_IOLATENCY is not set
+# CONFIG_BLK_CGROUP_IOCOST is not set
+CONFIG_BLK_DEBUG_FS=y
+# CONFIG_BLK_SED_OPAL is not set
+# CONFIG_BLK_INLINE_ENCRYPTION is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_CUMANA=y
+CONFIG_ACORN_PARTITION_EESOX=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_ADFS=y
+CONFIG_ACORN_PARTITION_POWERTEC=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_AIX_PARTITION=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_CMDLINE_PARTITION=y
+# end of Partition Types
+
+CONFIG_BLOCK_COMPAT=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_PM=y
+
+#
+# IO Schedulers
+#
+CONFIG_MQ_IOSCHED_DEADLINE=y
+CONFIG_MQ_IOSCHED_KYBER=y
+# CONFIG_IOSCHED_BFQ is not set
+# end of IO Schedulers
+
+CONFIG_PADATA=y
+CONFIG_ASN1=y
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
+CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_FREEZER=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+CONFIG_BINFMT_MISC=y
+CONFIG_COREDUMP=y
+# end of Executable file formats
+
+#
+# Memory Management options
+#
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_FAST_GUP=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+# CONFIG_PAGE_REPORTING is not set
+CONFIG_MIGRATION=y
+CONFIG_CONTIG_ALLOC=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_MEMORY_FAILURE=y
+CONFIG_HWPOISON_INJECT=y
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_AREAS=7
+CONFIG_ZSWAP=y
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_DEFLATE is not set
+CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZO=y
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_842 is not set
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4 is not set
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4HC is not set
+# CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD is not set
+CONFIG_ZSWAP_COMPRESSOR_DEFAULT="lzo"
+CONFIG_ZSWAP_ZPOOL_DEFAULT_ZBUD=y
+# CONFIG_ZSWAP_ZPOOL_DEFAULT_Z3FOLD is not set
+# CONFIG_ZSWAP_ZPOOL_DEFAULT_ZSMALLOC is not set
+CONFIG_ZSWAP_ZPOOL_DEFAULT="zbud"
+# CONFIG_ZSWAP_DEFAULT_ON is not set
+CONFIG_ZPOOL=y
+CONFIG_ZBUD=y
+# CONFIG_Z3FOLD is not set
+CONFIG_ZSMALLOC=y
+# CONFIG_ZSMALLOC_STAT is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_ARCH_HAS_PTE_DEVMAP=y
+CONFIG_VMAP_PFN=y
+CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
+CONFIG_ARCH_HAS_PKEYS=y
+# CONFIG_PERCPU_STATS is not set
+# CONFIG_GUP_BENCHMARK is not set
+CONFIG_ARCH_HAS_PTE_SPECIAL=y
+# end of Memory Management options
+
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+CONFIG_NET_INGRESS=y
+CONFIG_SKB_EXTENSIONS=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+CONFIG_UNIX_SCM=y
+# CONFIG_UNIX_DIAG is not set
+# CONFIG_TLS is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_AH=y
+CONFIG_XFRM_ESP=y
+CONFIG_XFRM_IPCOMP=y
+# CONFIG_NET_KEY is not set
+# CONFIG_XDP_SOCKETS is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_FIB_TRIE_STATS=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IP_TUNNEL=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE_COMMON=y
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=y
+CONFIG_NET_UDP_TUNNEL=y
+CONFIG_NET_FOU=y
+CONFIG_NET_FOU_IP_TUNNELS=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_ESP_OFFLOAD is not set
+# CONFIG_INET_ESPINTCP is not set
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_UDP_DIAG=y
+# CONFIG_INET_RAW_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_TCP_CONG_HTCP=y
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_MPTCP is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NET_PTP_CLASSIFY=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_INGRESS=y
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NETFILTER_NETLINK_OSF is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NF_LOG_NETDEV is not set
+# CONFIG_NF_TABLES is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# end of Core Netfilter Configuration
+
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_SOCKET_IPV4 is not set
+# CONFIG_NF_TPROXY_IPV4 is not set
+# CONFIG_NF_DUP_IPV4 is not set
+# CONFIG_NF_LOG_ARP is not set
+# CONFIG_NF_LOG_IPV4 is not set
+# CONFIG_NF_REJECT_IPV4 is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# end of IP: Netfilter Configuration
+
+# CONFIG_BPFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_DNS_RESOLVER is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_NET_NSH is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_QRTR is not set
+# CONFIG_NET_NCSI is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# end of Network testing
+# end of Networking options
+
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
+CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_CFG80211_WEXT_EXPORT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_MAC80211_MESSAGE_TRACING=y
+CONFIG_MAC80211_DEBUG_MENU=y
+# CONFIG_MAC80211_NOINLINE is not set
+CONFIG_MAC80211_VERBOSE_DEBUG=y
+# CONFIG_MAC80211_MLME_DEBUG is not set
+CONFIG_MAC80211_STA_DEBUG=y
+CONFIG_MAC80211_HT_DEBUG=y
+CONFIG_MAC80211_OCB_DEBUG=y
+CONFIG_MAC80211_IBSS_DEBUG=y
+CONFIG_MAC80211_PS_DEBUG=y
+CONFIG_MAC80211_TDLS_DEBUG=y
+# CONFIG_MAC80211_DEBUG_COUNTERS is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+CONFIG_WIMAX=y
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=y
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_PSAMPLE is not set
+# CONFIG_NET_IFE is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+CONFIG_GRO_CELLS=y
+# CONFIG_FAILOVER is not set
+CONFIG_ETHTOOL_NETLINK=y
+CONFIG_HAVE_EBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_HAVE_EISA=y
+# CONFIG_EISA is not set
+CONFIG_HAVE_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+CONFIG_PCIEAER=y
+# CONFIG_PCIEAER_INJECT is not set
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
+CONFIG_PCIE_PME=y
+# CONFIG_PCIE_DPC is not set
+# CONFIG_PCIE_PTM is not set
+# CONFIG_PCIE_BW is not set
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_PCI_REALLOC_ENABLE_AUTO=y
+CONFIG_PCI_STUB=y
+# CONFIG_PCI_PF_STUB is not set
+CONFIG_PCI_ATS=y
+CONFIG_PCI_LOCKLESS_CONFIG=y
+CONFIG_PCI_IOV=y
+CONFIG_PCI_PRI=y
+CONFIG_PCI_PASID=y
+CONFIG_PCI_LABEL=y
+# CONFIG_PCIE_BUS_TUNE_OFF is not set
+CONFIG_PCIE_BUS_DEFAULT=y
+# CONFIG_PCIE_BUS_SAFE is not set
+# CONFIG_PCIE_BUS_PERFORMANCE is not set
+# CONFIG_PCIE_BUS_PEER2PEER is not set
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_ACPI=y
+CONFIG_HOTPLUG_PCI_ACPI_IBM=y
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=y
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=y
+CONFIG_HOTPLUG_PCI_SHPC=y
+
+#
+# PCI controller drivers
+#
+# CONFIG_VMD is not set
+
+#
+# DesignWare PCI Core Support
+#
+# CONFIG_PCIE_DW_PLAT_HOST is not set
+# CONFIG_PCI_MESON is not set
+# end of DesignWare PCI Core Support
+
+#
+# Mobiveil PCIe Core Support
+#
+# end of Mobiveil PCIe Core Support
+
+#
+# Cadence PCIe controllers support
+#
+# end of Cadence PCIe controllers support
+# end of PCI controller drivers
+
+#
+# PCI Endpoint
+#
+# CONFIG_PCI_ENDPOINT is not set
+# end of PCI Endpoint
+
+#
+# PCI switch controller drivers
+#
+# CONFIG_PCI_SW_SWITCHTEC is not set
+# end of PCI switch controller drivers
+
+CONFIG_PCCARD=y
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=y
+CONFIG_I82092=y
+CONFIG_PCCARD_NONSTATIC=y
+CONFIG_RAPIDIO=y
+CONFIG_RAPIDIO_TSI721=y
+CONFIG_RAPIDIO_DISC_TIMEOUT=30
+# CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS is not set
+CONFIG_RAPIDIO_DMA_ENGINE=y
+# CONFIG_RAPIDIO_DEBUG is not set
+CONFIG_RAPIDIO_ENUM_BASIC=y
+# CONFIG_RAPIDIO_CHMAN is not set
+# CONFIG_RAPIDIO_MPORT_CDEV is not set
+
+#
+# RapidIO Switch drivers
+#
+CONFIG_RAPIDIO_TSI57X=y
+CONFIG_RAPIDIO_CPS_XX=y
+CONFIG_RAPIDIO_TSI568=y
+CONFIG_RAPIDIO_CPS_GEN2=y
+# CONFIG_RAPIDIO_RXS_GEN3 is not set
+# end of RapidIO Switch drivers
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Firmware loader
+#
+CONFIG_FW_LOADER=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_EXTRA_FIRMWARE="iwlwifi-7265D-29.ucode iwlwifi-7265-17.ucode"
+CONFIG_EXTRA_FIRMWARE_DIR="../linux-firmware"
+CONFIG_FW_LOADER_USER_HELPER=y
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+# CONFIG_FW_LOADER_COMPRESS is not set
+CONFIG_FW_CACHE=y
+# end of Firmware loader
+
+CONFIG_WANT_DEV_COREDUMP=y
+CONFIG_ALLOW_DEV_COREDUMP=y
+CONFIG_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_CPU_VULNERABILITIES=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_DMA_FENCE_TRACE is not set
+# end of Generic Driver Options
+
+#
+# Bus devices
+#
+# CONFIG_MHI_BUS is not set
+# end of Bus devices
+
+# CONFIG_CONNECTOR is not set
+# CONFIG_GNSS is not set
+# CONFIG_MTD is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_NULL_BLK=y
+# CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION is not set
+CONFIG_BLK_DEV_FD=y
+CONFIG_CDROM=y
+CONFIG_BLK_DEV_PCIESSD_MTIP32XX=y
+CONFIG_ZRAM=y
+# CONFIG_ZRAM_WRITEBACK is not set
+# CONFIG_ZRAM_MEMORY_TRACKING is not set
+CONFIG_BLK_DEV_UMEM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_SKD=y
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_BLK_DEV_RSXX is not set
+
+#
+# NVME Support
+#
+CONFIG_NVME_CORE=y
+CONFIG_BLK_DEV_NVME=y
+# CONFIG_NVME_MULTIPATH is not set
+# CONFIG_NVME_HWMON is not set
+# CONFIG_NVME_FC is not set
+# CONFIG_NVME_TCP is not set
+# CONFIG_NVME_TARGET is not set
+# end of NVME Support
+
+#
+# Misc devices
+#
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+CONFIG_TIFM_CORE=y
+# CONFIG_TIFM_7XX1 is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+CONFIG_SRAM=y
+# CONFIG_PCI_ENDPOINT_TEST is not set
+# CONFIG_XILINX_SDFEC is not set
+# CONFIG_PVPANIC is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=y
+# CONFIG_EEPROM_93XX46 is not set
+# CONFIG_EEPROM_IDT_89HPESX is not set
+# CONFIG_EEPROM_EE1004 is not set
+# end of EEPROM support
+
+CONFIG_CB710_CORE=y
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# end of Texas Instruments shared transport line discipline
+
+# CONFIG_SENSORS_LIS3_I2C is not set
+# CONFIG_ALTERA_STAPL is not set
+# CONFIG_INTEL_MEI is not set
+# CONFIG_INTEL_MEI_ME is not set
+# CONFIG_INTEL_MEI_TXE is not set
+# CONFIG_INTEL_MEI_HDCP is not set
+# CONFIG_VMWARE_VMCI is not set
+# CONFIG_GENWQE is not set
+# CONFIG_ECHO is not set
+# CONFIG_MISC_ALCOR_PCI is not set
+# CONFIG_MISC_RTSX_PCI is not set
+# CONFIG_MISC_RTSX_USB is not set
+# CONFIG_HABANA_AI is not set
+# CONFIG_UACCE is not set
+# end of Misc devices
+
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
+CONFIG_SCSI_SAS_LIBSAS=y
+# CONFIG_SCSI_SAS_ATA is not set
+CONFIG_SCSI_SAS_HOST_SMP=y
+CONFIG_SCSI_SRP_ATTRS=y
+# end of SCSI Transports
+
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# end of SCSI device support
+
+CONFIG_ATA=y
+CONFIG_SATA_HOST=y
+CONFIG_PATA_TIMINGS=y
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_FORCE=y
+CONFIG_ATA_ACPI=y
+# CONFIG_SATA_ZPODD is not set
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_MOBILE_LPM_POLICY=0
+CONFIG_SATA_AHCI_PLATFORM=y
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_SATA_ACARD_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_DWC is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+
+#
+# PATA SFF controllers with BMDMA
+#
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+
+#
+# PIO-only SFF controllers
+#
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_PCMCIA is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_RZ1000 is not set
+
+#
+# Generic fallback / legacy drivers
+#
+# CONFIG_PATA_ACPI is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_LEGACY is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_AUTODETECT is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BCACHE=y
+# CONFIG_BCACHE_DEBUG is not set
+# CONFIG_BCACHE_CLOSURES_DEBUG is not set
+# CONFIG_BCACHE_ASYNC_REGISTRATION is not set
+CONFIG_BLK_DEV_DM_BUILTIN=y
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_BUFIO=y
+# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set
+CONFIG_DM_BIO_PRISON=y
+CONFIG_DM_PERSISTENT_DATA=y
+# CONFIG_DM_UNSTRIPED is not set
+CONFIG_DM_CRYPT=y
+CONFIG_DM_SNAPSHOT=y
+CONFIG_DM_THIN_PROVISIONING=y
+CONFIG_DM_CACHE=y
+CONFIG_DM_CACHE_SMQ=y
+# CONFIG_DM_WRITECACHE is not set
+# CONFIG_DM_EBS is not set
+CONFIG_DM_ERA=y
+# CONFIG_DM_CLONE is not set
+CONFIG_DM_MIRROR=y
+# CONFIG_DM_LOG_USERSPACE is not set
+# CONFIG_DM_RAID is not set
+CONFIG_DM_ZERO=y
+CONFIG_DM_MULTIPATH=y
+CONFIG_DM_MULTIPATH_QL=y
+CONFIG_DM_MULTIPATH_ST=y
+# CONFIG_DM_MULTIPATH_HST is not set
+CONFIG_DM_DELAY=y
+# CONFIG_DM_DUST is not set
+# CONFIG_DM_INIT is not set
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=y
+CONFIG_DM_VERITY=y
+# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG is not set
+# CONFIG_DM_VERITY_FEC is not set
+CONFIG_DM_SWITCH=y
+# CONFIG_DM_LOG_WRITES is not set
+# CONFIG_DM_INTEGRITY is not set
+CONFIG_TARGET_CORE=y
+CONFIG_TCM_IBLOCK=y
+CONFIG_TCM_FILEIO=y
+CONFIG_TCM_PSCSI=y
+# CONFIG_TCM_USER2 is not set
+CONFIG_LOOPBACK_TARGET=y
+# CONFIG_ISCSI_TARGET is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# end of IEEE 1394 (FireWire) support
+
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_WIREGUARD is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_IPVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_GENEVE is not set
+# CONFIG_BAREUDP is not set
+# CONFIG_GTP is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_RIONET is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+# CONFIG_ARCNET is not set
+
+#
+# Distributed Switch Architecture drivers
+#
+# end of Distributed Switch Architecture drivers
+
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_VORTEX is not set
+# CONFIG_TYPHOON is not set
+CONFIG_NET_VENDOR_ADAPTEC=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_NET_VENDOR_AGERE=y
+# CONFIG_ET131X is not set
+CONFIG_NET_VENDOR_ALACRITECH=y
+# CONFIG_SLICOSS is not set
+CONFIG_NET_VENDOR_ALTEON=y
+# CONFIG_ACENIC is not set
+# CONFIG_ALTERA_TSE is not set
+CONFIG_NET_VENDOR_AMAZON=y
+# CONFIG_ENA_ETHERNET is not set
+CONFIG_NET_VENDOR_AMD=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_PCNET32 is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_AMD_XGBE is not set
+CONFIG_NET_VENDOR_AQUANTIA=y
+# CONFIG_AQTION is not set
+CONFIG_NET_VENDOR_ARC=y
+CONFIG_NET_VENDOR_ATHEROS=y
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ALX is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BCMGENET is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+CONFIG_TIGON3=y
+# CONFIG_TIGON3_HWMON is not set
+# CONFIG_BNX2X is not set
+# CONFIG_SYSTEMPORT is not set
+# CONFIG_BNXT is not set
+CONFIG_NET_VENDOR_BROCADE=y
+# CONFIG_BNA is not set
+CONFIG_NET_VENDOR_CADENCE=y
+# CONFIG_MACB is not set
+CONFIG_NET_VENDOR_CAVIUM=y
+# CONFIG_THUNDER_NIC_PF is not set
+# CONFIG_THUNDER_NIC_VF is not set
+# CONFIG_THUNDER_NIC_BGX is not set
+# CONFIG_THUNDER_NIC_RGX is not set
+# CONFIG_LIQUIDIO is not set
+# CONFIG_LIQUIDIO_VF is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_CHELSIO_T4VF is not set
+CONFIG_NET_VENDOR_CISCO=y
+# CONFIG_ENIC is not set
+CONFIG_NET_VENDOR_CORTINA=y
+# CONFIG_CX_ECAT is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_DEC=y
+# CONFIG_NET_TULIP is not set
+CONFIG_NET_VENDOR_DLINK=y
+# CONFIG_DL2K is not set
+# CONFIG_SUNDANCE is not set
+CONFIG_NET_VENDOR_EMULEX=y
+# CONFIG_BE2NET is not set
+CONFIG_NET_VENDOR_EZCHIP=y
+CONFIG_NET_VENDOR_FUJITSU=y
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_NET_VENDOR_GOOGLE=y
+# CONFIG_GVE is not set
+CONFIG_NET_VENDOR_HUAWEI=y
+# CONFIG_HINIC is not set
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
+# CONFIG_I40E is not set
+# CONFIG_I40EVF is not set
+# CONFIG_ICE is not set
+# CONFIG_FM10K is not set
+# CONFIG_IGC is not set
+# CONFIG_JME is not set
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+CONFIG_NET_VENDOR_MELLANOX=y
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX5_CORE is not set
+# CONFIG_MLXSW_CORE is not set
+# CONFIG_MLXFW is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSZ884X_PCI is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_LAN743X is not set
+CONFIG_NET_VENDOR_MICROSEMI=y
+CONFIG_NET_VENDOR_MYRI=y
+# CONFIG_MYRI10GE is not set
+# CONFIG_FEALNX is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+# CONFIG_NATSEMI is not set
+# CONFIG_NS83820 is not set
+CONFIG_NET_VENDOR_NETERION=y
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+CONFIG_NET_VENDOR_NETRONOME=y
+# CONFIG_NFP is not set
+CONFIG_NET_VENDOR_NI=y
+# CONFIG_NI_XGE_MANAGEMENT_ENET is not set
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_PCMCIA_PCNET is not set
+CONFIG_NET_VENDOR_NVIDIA=y
+# CONFIG_FORCEDETH is not set
+CONFIG_NET_VENDOR_OKI=y
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_PACKET_ENGINES=y
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_NET_VENDOR_PENSANDO=y
+# CONFIG_IONIC is not set
+CONFIG_NET_VENDOR_QLOGIC=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_QED is not set
+CONFIG_NET_VENDOR_QUALCOMM=y
+# CONFIG_QCOM_EMAC is not set
+# CONFIG_RMNET is not set
+CONFIG_NET_VENDOR_RDC=y
+# CONFIG_R6040 is not set
+CONFIG_NET_VENDOR_REALTEK=y
+CONFIG_8139CP=y
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+CONFIG_8139TOO_TUNE_TWISTER=y
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R8169=y
+CONFIG_NET_VENDOR_RENESAS=y
+CONFIG_NET_VENDOR_ROCKER=y
+CONFIG_NET_VENDOR_SAMSUNG=y
+# CONFIG_SXGBE_ETH is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SOLARFLARE=y
+# CONFIG_SFC is not set
+# CONFIG_SFC_FALCON is not set
+CONFIG_NET_VENDOR_SILAN=y
+# CONFIG_SC92031 is not set
+CONFIG_NET_VENDOR_SIS=y
+# CONFIG_SIS900 is not set
+# CONFIG_SIS190 is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_SMSC9420 is not set
+CONFIG_NET_VENDOR_SOCIONEXT=y
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_SUN=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NIU is not set
+CONFIG_NET_VENDOR_SYNOPSYS=y
+# CONFIG_DWC_XLGMAC is not set
+CONFIG_NET_VENDOR_TEHUTI=y
+# CONFIG_TEHUTI is not set
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TI_CPSW_PHY_SEL is not set
+# CONFIG_TLAN is not set
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+CONFIG_NET_VENDOR_XILINX=y
+# CONFIG_XILINX_AXI_EMAC is not set
+# CONFIG_XILINX_LL_TEMAC is not set
+CONFIG_NET_VENDOR_XIRCOM=y
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_NET_SB1000 is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+CONFIG_LED_TRIGGER_PHY=y
+CONFIG_FIXED_PHY=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_ADIN_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AX88796B_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM54140_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM84881_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_CORTINA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MARVELL_10G_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROCHIP_T1_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_NXP_TJA11XX_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+CONFIG_REALTEK_PHY=y
+# CONFIG_RENESAS_PHY is not set
+# CONFIG_ROCKCHIP_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_DP83822_PHY is not set
+# CONFIG_DP83TC811_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+# CONFIG_DP83869_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVRES=y
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_MVUSB is not set
+# CONFIG_MDIO_MSCC_MIIM is not set
+# CONFIG_MDIO_THUNDER is not set
+
+#
+# MDIO Multiplexers
+#
+
+#
+# PCS device drivers
+#
+# CONFIG_PCS_XPCS is not set
+# end of PCS device drivers
+
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_RTL8152=y
+# CONFIG_USB_LAN78XX is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_AX88179_178A=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set
+# CONFIG_USB_NET_CDC_MBIM is not set
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SR9700 is not set
+# CONFIG_USB_NET_SR9800 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+# CONFIG_USB_NET_SMSC95XX is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET_ENABLE=y
+CONFIG_USB_NET_CDC_SUBSET=y
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_QMI_WWAN is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+# CONFIG_USB_NET_CH9200 is not set
+# CONFIG_USB_NET_AQC111 is not set
+CONFIG_WLAN=y
+# CONFIG_WIRELESS_WDS is not set
+CONFIG_WLAN_VENDOR_ADMTEK=y
+# CONFIG_ADM8211 is not set
+CONFIG_ATH_COMMON=y
+CONFIG_WLAN_VENDOR_ATH=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH_TRACEPOINTS=y
+# CONFIG_ATH5K is not set
+# CONFIG_ATH5K_PCI is not set
+CONFIG_ATH9K_HW=y
+CONFIG_ATH9K_COMMON=y
+CONFIG_ATH9K_COMMON_DEBUG=y
+CONFIG_ATH9K_BTCOEX_SUPPORT=y
+CONFIG_ATH9K=y
+CONFIG_ATH9K_PCI=y
+# CONFIG_ATH9K_AHB is not set
+CONFIG_ATH9K_DEBUGFS=y
+CONFIG_ATH9K_STATION_STATISTICS=y
+# CONFIG_ATH9K_DYNACK is not set
+# CONFIG_ATH9K_WOW is not set
+CONFIG_ATH9K_RFKILL=y
+# CONFIG_ATH9K_CHANNEL_CONTEXT is not set
+CONFIG_ATH9K_PCOEM=y
+# CONFIG_ATH9K_PCI_NO_EEPROM is not set
+CONFIG_ATH9K_HTC=y
+CONFIG_ATH9K_HTC_DEBUGFS=y
+# CONFIG_ATH9K_HWRNG is not set
+# CONFIG_ATH9K_COMMON_SPECTRAL is not set
+# CONFIG_CARL9170 is not set
+# CONFIG_ATH6KL is not set
+# CONFIG_AR5523 is not set
+# CONFIG_WIL6210 is not set
+# CONFIG_ATH10K is not set
+# CONFIG_WCN36XX is not set
+# CONFIG_ATH11K is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+# CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMSMAC is not set
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+# CONFIG_AIRO is not set
+# CONFIG_AIRO_CS is not set
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_IPW2100=y
+# CONFIG_IPW2100_MONITOR is not set
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=y
+# CONFIG_IPW2200_MONITOR is not set
+# CONFIG_IPW2200_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=y
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLEGACY=y
+CONFIG_IWL4965=y
+CONFIG_IWL3945=y
+
+#
+# iwl3945 / iwl4965 Debugging Options
+#
+# CONFIG_IWLEGACY_DEBUG is not set
+# CONFIG_IWLEGACY_DEBUGFS is not set
+# end of iwl3945 / iwl4965 Debugging Options
+
+CONFIG_IWLWIFI=y
+CONFIG_IWLWIFI_LEDS=y
+CONFIG_IWLDVM=y
+CONFIG_IWLMVM=y
+# CONFIG_IWLWIFI_BCAST_FILTERING is not set
+
+#
+# Debugging Options
+#
+# CONFIG_IWLWIFI_DEBUG is not set
+# CONFIG_IWLWIFI_DEBUGFS is not set
+CONFIG_IWLWIFI_DEVICE_TRACING=y
+# end of Debugging Options
+
+CONFIG_WLAN_VENDOR_INTERSIL=y
+# CONFIG_HOSTAP is not set
+# CONFIG_HERMES is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_PRISM54 is not set
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MWIFIEX is not set
+# CONFIG_MWL8K is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+# CONFIG_MT7601U is not set
+# CONFIG_MT76x0U is not set
+# CONFIG_MT76x0E is not set
+# CONFIG_MT76x2E is not set
+# CONFIG_MT76x2U is not set
+# CONFIG_MT7603E is not set
+# CONFIG_MT7615E is not set
+# CONFIG_MT7663U is not set
+# CONFIG_MT7663S is not set
+# CONFIG_MT7915E is not set
+CONFIG_WLAN_VENDOR_MICROCHIP=y
+# CONFIG_WILC1000_SDIO is not set
+# CONFIG_WILC1000_SPI is not set
+CONFIG_WLAN_VENDOR_RALINK=y
+# CONFIG_RT2X00 is not set
+CONFIG_WLAN_VENDOR_REALTEK=y
+# CONFIG_RTL8180 is not set
+# CONFIG_RTL8187 is not set
+CONFIG_RTL_CARDS=y
+# CONFIG_RTL8192CE is not set
+# CONFIG_RTL8192SE is not set
+# CONFIG_RTL8192DE is not set
+# CONFIG_RTL8723AE is not set
+# CONFIG_RTL8723BE is not set
+# CONFIG_RTL8188EE is not set
+# CONFIG_RTL8192EE is not set
+# CONFIG_RTL8821AE is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_RTL8XXXU is not set
+# CONFIG_RTW88 is not set
+CONFIG_WLAN_VENDOR_RSI=y
+# CONFIG_RSI_91X is not set
+CONFIG_WLAN_VENDOR_ST=y
+# CONFIG_CW1200 is not set
+CONFIG_WLAN_VENDOR_TI=y
+# CONFIG_WL1251 is not set
+# CONFIG_WL12XX is not set
+# CONFIG_WL18XX is not set
+# CONFIG_WLCORE is not set
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_ZD1211RW is not set
+CONFIG_WLAN_VENDOR_QUANTENNA=y
+# CONFIG_QTNFMAC_PCIE is not set
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_VIRT_WIFI is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# end of WiMAX Wireless Broadband devices
+
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_FUJITSU_ES is not set
+# CONFIG_NETDEVSIM is not set
+# CONFIG_NET_FAILOVER is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_LEDS=y
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_SPARSEKMAP is not set
+CONFIG_INPUT_MATRIXKMAP=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ADC=y
+CONFIG_KEYBOARD_ADP5588=y
+CONFIG_KEYBOARD_ADP5589=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1050 is not set
+CONFIG_KEYBOARD_QT1070=y
+CONFIG_KEYBOARD_QT2160=y
+# CONFIG_KEYBOARD_DLINK_DIR685 is not set
+CONFIG_KEYBOARD_LKKBD=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+CONFIG_KEYBOARD_TCA6416=y
+CONFIG_KEYBOARD_TCA8418=y
+CONFIG_KEYBOARD_MATRIX=y
+CONFIG_KEYBOARD_LM8323=y
+CONFIG_KEYBOARD_LM8333=y
+CONFIG_KEYBOARD_MAX7359=y
+CONFIG_KEYBOARD_MCS=y
+CONFIG_KEYBOARD_MPR121=y
+CONFIG_KEYBOARD_NEWTON=y
+CONFIG_KEYBOARD_OPENCORES=y
+CONFIG_KEYBOARD_SAMSUNG=y
+CONFIG_KEYBOARD_STOWAWAY=y
+CONFIG_KEYBOARD_SUNKBD=y
+# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set
+CONFIG_KEYBOARD_XTKBD=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_PS2_ELANTECH_SMBUS=y
+CONFIG_MOUSE_PS2_SENTELIC=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_PS2_FOCALTECH=y
+CONFIG_MOUSE_PS2_VMMOUSE=y
+CONFIG_MOUSE_PS2_SMBUS=y
+CONFIG_MOUSE_SERIAL=y
+CONFIG_MOUSE_APPLETOUCH=y
+CONFIG_MOUSE_BCM5974=y
+CONFIG_MOUSE_CYAPA=y
+CONFIG_MOUSE_ELAN_I2C=y
+CONFIG_MOUSE_ELAN_I2C_I2C=y
+CONFIG_MOUSE_ELAN_I2C_SMBUS=y
+CONFIG_MOUSE_VSXXXAA=y
+CONFIG_MOUSE_GPIO=y
+CONFIG_MOUSE_SYNAPTICS_I2C=y
+CONFIG_MOUSE_SYNAPTICS_USB=y
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=y
+CONFIG_JOYSTICK_A3D=y
+# CONFIG_JOYSTICK_ADC is not set
+CONFIG_JOYSTICK_ADI=y
+CONFIG_JOYSTICK_COBRA=y
+CONFIG_JOYSTICK_GF2K=y
+CONFIG_JOYSTICK_GRIP=y
+CONFIG_JOYSTICK_GRIP_MP=y
+CONFIG_JOYSTICK_GUILLEMOT=y
+CONFIG_JOYSTICK_INTERACT=y
+CONFIG_JOYSTICK_SIDEWINDER=y
+CONFIG_JOYSTICK_TMDC=y
+CONFIG_JOYSTICK_IFORCE=y
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=y
+CONFIG_JOYSTICK_MAGELLAN=y
+CONFIG_JOYSTICK_SPACEORB=y
+CONFIG_JOYSTICK_SPACEBALL=y
+CONFIG_JOYSTICK_STINGER=y
+CONFIG_JOYSTICK_TWIDJOY=y
+CONFIG_JOYSTICK_ZHENHUA=y
+CONFIG_JOYSTICK_AS5011=y
+CONFIG_JOYSTICK_JOYDUMP=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+# CONFIG_JOYSTICK_PSXPAD_SPI is not set
+# CONFIG_JOYSTICK_PXRC is not set
+# CONFIG_JOYSTICK_FSIA6B is not set
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+# CONFIG_TABLET_USB_PEGASUS is not set
+CONFIG_TABLET_SERIAL_WACOM4=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ADC is not set
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_BU21029 is not set
+# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
+# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set
+# CONFIG_TOUCHSCREEN_EXC3000 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GOODIX is not set
+# CONFIG_TOUCHSCREEN_HIDEEP is not set
+# CONFIG_TOUCHSCREEN_ILI210X is not set
+# CONFIG_TOUCHSCREEN_S6SY761 is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_EKTF2127 is not set
+CONFIG_TOUCHSCREEN_ELAN=y
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MMS114 is not set
+# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set
+# CONFIG_TOUCHSCREEN_WM97XX is not set
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=y
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_ELO=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+# CONFIG_TOUCHSCREEN_TSC2004 is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_RM_TS is not set
+# CONFIG_TOUCHSCREEN_SILEAD is not set
+# CONFIG_TOUCHSCREEN_SIS_I2C is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_STMFTS is not set
+# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set
+# CONFIG_TOUCHSCREEN_SX8654 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+# CONFIG_TOUCHSCREEN_ZET6223 is not set
+# CONFIG_TOUCHSCREEN_ZFORCE is not set
+# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set
+# CONFIG_TOUCHSCREEN_IQS5XX is not set
+# CONFIG_TOUCHSCREEN_ZINITIX is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_PCSPKR is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_APANEL is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_GPIO_VIBRA is not set
+# CONFIG_INPUT_ATLAS_BTNS is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_REGULATOR_HAPTIC is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_PWM_BEEPER is not set
+# CONFIG_INPUT_PWM_VIBRA is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_IMS_PCU is not set
+# CONFIG_INPUT_IQS269A is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set
+# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+CONFIG_RMI4_CORE=y
+# CONFIG_RMI4_I2C is not set
+# CONFIG_RMI4_SPI is not set
+# CONFIG_RMI4_SMB is not set
+CONFIG_RMI4_F03=y
+CONFIG_RMI4_F03_SERIO=y
+CONFIG_RMI4_2D_SENSOR=y
+CONFIG_RMI4_F11=y
+CONFIG_RMI4_F12=y
+CONFIG_RMI4_F30=y
+# CONFIG_RMI4_F34 is not set
+# CONFIG_RMI4_F3A is not set
+# CONFIG_RMI4_F55 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_GPIO_PS2 is not set
+# CONFIG_USERIO is not set
+CONFIG_GAMEPORT=y
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# end of Hardware I/O ports
+# end of Input device support
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_LDISC_AUTOLOAD=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_PNP=y
+# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
+# CONFIG_SERIAL_8250_FINTEK is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DMA=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_EXAR=y
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=48
+CONFIG_SERIAL_8250_RUNTIME_UARTS=32
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_8250_DWLIB=y
+CONFIG_SERIAL_8250_DW=y
+# CONFIG_SERIAL_8250_RT288X is not set
+CONFIG_SERIAL_8250_LPSS=y
+# CONFIG_SERIAL_8250_MID is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_KGDB_NMI=y
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_CONSOLE_POLL=y
+CONFIG_SERIAL_JSM=y
+# CONFIG_SERIAL_LANTIQ is not set
+CONFIG_SERIAL_SCCNXP=y
+CONFIG_SERIAL_SCCNXP_CONSOLE=y
+CONFIG_SERIAL_SC16IS7XX_CORE=y
+CONFIG_SERIAL_SC16IS7XX=y
+CONFIG_SERIAL_SC16IS7XX_I2C=y
+# CONFIG_SERIAL_SC16IS7XX_SPI is not set
+CONFIG_SERIAL_ALTERA_JTAGUART=y
+# CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE is not set
+CONFIG_SERIAL_ALTERA_UART=y
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+# CONFIG_SERIAL_ALTERA_UART_CONSOLE is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+CONFIG_SERIAL_ARC=y
+# CONFIG_SERIAL_ARC_CONSOLE is not set
+CONFIG_SERIAL_ARC_NR_PORTS=1
+CONFIG_SERIAL_RP2=y
+CONFIG_SERIAL_RP2_NR_UARTS=32
+CONFIG_SERIAL_FSL_LPUART=y
+# CONFIG_SERIAL_FSL_LPUART_CONSOLE is not set
+# CONFIG_SERIAL_FSL_LINFLEXUART is not set
+# CONFIG_SERIAL_SPRD is not set
+# end of Serial drivers
+
+CONFIG_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_ROCKETPORT=y
+CONFIG_CYCLADES=y
+# CONFIG_CYZ_INTR is not set
+CONFIG_MOXA_INTELLIO=y
+CONFIG_MOXA_SMARTIO=y
+CONFIG_SYNCLINK=y
+CONFIG_SYNCLINKMP=y
+CONFIG_SYNCLINK_GT=y
+CONFIG_ISI=y
+CONFIG_N_HDLC=y
+# CONFIG_N_GSM is not set
+CONFIG_NOZOMI=y
+# CONFIG_NULL_TTY is not set
+CONFIG_TRACE_ROUTER=y
+CONFIG_TRACE_SINK=y
+# CONFIG_SERIAL_DEV_BUS is not set
+CONFIG_TTY_PRINTK=y
+CONFIG_TTY_PRINTK_LEVEL=6
+# CONFIG_VIRTIO_CONSOLE is not set
+CONFIG_IPMI_HANDLER=y
+CONFIG_IPMI_DMI_DECODE=y
+CONFIG_IPMI_PLAT_DATA=y
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=y
+CONFIG_IPMI_SI=y
+CONFIG_IPMI_SSIF=y
+CONFIG_IPMI_WATCHDOG=y
+CONFIG_IPMI_POWEROFF=y
+# CONFIG_IPMB_DEVICE_INTERFACE is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=y
+CONFIG_HW_RANDOM_INTEL=y
+CONFIG_HW_RANDOM_AMD=y
+# CONFIG_HW_RANDOM_BA431 is not set
+CONFIG_HW_RANDOM_VIA=y
+# CONFIG_HW_RANDOM_XIPHERA is not set
+CONFIG_APPLICOM=y
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=y
+CONFIG_CARDMAN_4000=y
+CONFIG_CARDMAN_4040=y
+# CONFIG_SCR24X is not set
+# CONFIG_IPWIRELESS is not set
+# end of PCMCIA character devices
+
+CONFIG_MWAVE=y
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+CONFIG_NVRAM=y
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_DEVPORT=y
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HPET_MMAP_DEFAULT=y
+CONFIG_HANGCHECK_TIMER=y
+CONFIG_TCG_TPM=y
+CONFIG_HW_RANDOM_TPM=y
+CONFIG_TCG_TIS_CORE=y
+CONFIG_TCG_TIS=y
+# CONFIG_TCG_TIS_SPI is not set
+CONFIG_TCG_TIS_I2C_ATMEL=y
+CONFIG_TCG_TIS_I2C_INFINEON=y
+CONFIG_TCG_TIS_I2C_NUVOTON=y
+CONFIG_TCG_NSC=y
+CONFIG_TCG_ATMEL=y
+CONFIG_TCG_INFINEON=y
+# CONFIG_TCG_CRB is not set
+# CONFIG_TCG_VTPM_PROXY is not set
+# CONFIG_TCG_TIS_ST33ZP24_I2C is not set
+# CONFIG_TCG_TIS_ST33ZP24_SPI is not set
+CONFIG_TELCLOCK=y
+CONFIG_XILLYBUS=y
+CONFIG_XILLYBUS_PCIE=y
+# end of Character devices
+
+# CONFIG_RANDOM_TRUST_CPU is not set
+# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_ACPI_I2C_OPREGION=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_GPIO=y
+# CONFIG_I2C_MUX_LTC4306 is not set
+CONFIG_I2C_MUX_PCA9541=y
+CONFIG_I2C_MUX_PCA954x=y
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_MUX_MLXCPLD is not set
+# end of Multiplexer I2C Chip support
+
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_AMD_MP2 is not set
+CONFIG_I2C_I801=y
+CONFIG_I2C_ISCH=y
+CONFIG_I2C_ISMT=y
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_NVIDIA_GPU is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=y
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+CONFIG_I2C_DESIGNWARE_CORE=y
+# CONFIG_I2C_DESIGNWARE_SLAVE is not set
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_DESIGNWARE_BAYTRAIL=y
+CONFIG_I2C_DESIGNWARE_PCI=y
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_MLXCPLD is not set
+# end of I2C Hardware Bus support
+
+CONFIG_I2C_SLAVE=y
+CONFIG_I2C_SLAVE_EEPROM=y
+# CONFIG_I2C_SLAVE_TESTUNIT is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# end of I2C support
+
+# CONFIG_I3C is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+CONFIG_SPI_DESIGNWARE=y
+# CONFIG_SPI_DW_DMA is not set
+CONFIG_SPI_DW_PCI=y
+CONFIG_SPI_DW_MMIO=y
+# CONFIG_SPI_NXP_FLEXSPI is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_LANTIQ_SSC is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_SIFIVE is not set
+# CONFIG_SPI_MXIC is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+# CONFIG_SPI_AMD is not set
+
+#
+# SPI Multiplexer support
+#
+# CONFIG_SPI_MUX is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPI_SLAVE is not set
+CONFIG_SPI_DYNAMIC=y
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+CONFIG_PPS=y
+# CONFIG_PPS_DEBUG is not set
+
+#
+# PPS clients support
+#
+# CONFIG_PPS_CLIENT_KTIMER is not set
+CONFIG_PPS_CLIENT_LDISC=y
+CONFIG_PPS_CLIENT_GPIO=y
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+# end of PTP clock support
+
+CONFIG_PINCTRL=y
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_MCP23S08 is not set
+CONFIG_PINCTRL_SX150X=y
+CONFIG_PINCTRL_BAYTRAIL=y
+CONFIG_PINCTRL_CHERRYVIEW=y
+# CONFIG_PINCTRL_LYNXPOINT is not set
+CONFIG_PINCTRL_INTEL=y
+# CONFIG_PINCTRL_BROXTON is not set
+# CONFIG_PINCTRL_CANNONLAKE is not set
+# CONFIG_PINCTRL_CEDARFORK is not set
+# CONFIG_PINCTRL_DENVERTON is not set
+# CONFIG_PINCTRL_EMMITSBURG is not set
+# CONFIG_PINCTRL_GEMINILAKE is not set
+# CONFIG_PINCTRL_ICELAKE is not set
+# CONFIG_PINCTRL_JASPERLAKE is not set
+# CONFIG_PINCTRL_LEWISBURG is not set
+# CONFIG_PINCTRL_SUNRISEPOINT is not set
+# CONFIG_PINCTRL_TIGERLAKE is not set
+
+#
+# Renesas pinctrl drivers
+#
+# end of Renesas pinctrl drivers
+
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_FASTPATH_LIMIT=512
+CONFIG_GPIO_ACPI=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_CDEV=y
+CONFIG_GPIO_CDEV_V1=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GPIO_MAX730X=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_AMDPT is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EXAR is not set
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_ICH=y
+# CONFIG_GPIO_MB86S7X is not set
+CONFIG_GPIO_VX855=y
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_AMD_FCH is not set
+# end of Memory mapped GPIO drivers
+
+#
+# Port-mapped I/O GPIO drivers
+#
+CONFIG_GPIO_F7188X=y
+# CONFIG_GPIO_IT87 is not set
+CONFIG_GPIO_SCH=y
+CONFIG_GPIO_SCH311X=y
+# CONFIG_GPIO_WINBOND is not set
+# CONFIG_GPIO_WS16C48 is not set
+# end of Port-mapped I/O GPIO drivers
+
+#
+# I2C GPIO expanders
+#
+CONFIG_GPIO_ADP5588=y
+# CONFIG_GPIO_ADP5588_IRQ is not set
+CONFIG_GPIO_MAX7300=y
+CONFIG_GPIO_MAX732X=y
+# CONFIG_GPIO_MAX732X_IRQ is not set
+CONFIG_GPIO_PCA953X=y
+# CONFIG_GPIO_PCA953X_IRQ is not set
+# CONFIG_GPIO_PCA9570 is not set
+CONFIG_GPIO_PCF857X=y
+# CONFIG_GPIO_TPIC2810 is not set
+# end of I2C GPIO expanders
+
+#
+# MFD GPIO expanders
+#
+# end of MFD GPIO expanders
+
+#
+# PCI GPIO expanders
+#
+CONFIG_GPIO_AMD8111=y
+# CONFIG_GPIO_BT8XX is not set
+CONFIG_GPIO_ML_IOH=y
+# CONFIG_GPIO_PCI_IDIO_16 is not set
+# CONFIG_GPIO_PCIE_IDIO_24 is not set
+CONFIG_GPIO_RDC321X=y
+# end of PCI GPIO expanders
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX3191X is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+# CONFIG_GPIO_XRA1403 is not set
+# end of SPI GPIO expanders
+
+#
+# USB GPIO expanders
+#
+# end of USB GPIO expanders
+
+# CONFIG_GPIO_AGGREGATOR is not set
+# CONFIG_GPIO_MOCKUP is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_MATROX is not set
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+# CONFIG_W1_MASTER_SGI is not set
+# end of 1-wire Bus Masters
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2405 is not set
+# CONFIG_W1_SLAVE_DS2408 is not set
+# CONFIG_W1_SLAVE_DS2413 is not set
+# CONFIG_W1_SLAVE_DS2406 is not set
+# CONFIG_W1_SLAVE_DS2423 is not set
+# CONFIG_W1_SLAVE_DS2805 is not set
+# CONFIG_W1_SLAVE_DS2430 is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2438 is not set
+# CONFIG_W1_SLAVE_DS250X is not set
+CONFIG_W1_SLAVE_DS2780=y
+CONFIG_W1_SLAVE_DS2781=y
+# CONFIG_W1_SLAVE_DS28E04 is not set
+# CONFIG_W1_SLAVE_DS28E17 is not set
+# end of 1-wire Slaves
+
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_RESTART is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_POWER_SUPPLY_HWMON=y
+CONFIG_PDA_POWER=y
+CONFIG_GENERIC_ADC_BATTERY=y
+CONFIG_TEST_POWER=y
+# CONFIG_CHARGER_ADP5061 is not set
+# CONFIG_BATTERY_CW2015 is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_DS2780=y
+CONFIG_BATTERY_DS2781=y
+CONFIG_BATTERY_DS2782=y
+CONFIG_BATTERY_SBS=y
+# CONFIG_CHARGER_SBS is not set
+# CONFIG_MANAGER_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+CONFIG_BATTERY_MAX17040=y
+CONFIG_BATTERY_MAX17042=y
+# CONFIG_BATTERY_MAX1721X is not set
+CONFIG_CHARGER_ISP1704=y
+CONFIG_CHARGER_MAX8903=y
+CONFIG_CHARGER_LP8727=y
+CONFIG_CHARGER_GPIO=y
+CONFIG_CHARGER_MANAGER=y
+# CONFIG_CHARGER_LT3651 is not set
+CONFIG_CHARGER_BQ2415X=y
+CONFIG_CHARGER_BQ24190=y
+# CONFIG_CHARGER_BQ24257 is not set
+CONFIG_CHARGER_BQ24735=y
+# CONFIG_CHARGER_BQ2515X is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_BQ25980 is not set
+CONFIG_CHARGER_SMB347=y
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_CHARGER_BD99954 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7314 is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM1177 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7310 is not set
+# CONFIG_SENSORS_ADT7410 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_AS370 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_AXI_FAN_CONTROL is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_K10TEMP is not set
+# CONFIG_SENSORS_FAM15H_POWER is not set
+# CONFIG_SENSORS_AMD_ENERGY is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ASPEED is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_CORSAIR_CPRO is not set
+# CONFIG_SENSORS_DRIVETEMP is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+CONFIG_SENSORS_DELL_SMM=y
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_G762 is not set
+# CONFIG_SENSORS_HIH6130 is not set
+# CONFIG_SENSORS_IBMAEM is not set
+# CONFIG_SENSORS_IBMPEX is not set
+# CONFIG_SENSORS_IIO_HWMON is not set
+CONFIG_SENSORS_I5500=y
+CONFIG_SENSORS_CORETEMP=y
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_POWR1220 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LTC2945 is not set
+# CONFIG_SENSORS_LTC2947_I2C is not set
+# CONFIG_SENSORS_LTC2947_SPI is not set
+# CONFIG_SENSORS_LTC2990 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4222 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4260 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX31722 is not set
+# CONFIG_SENSORS_MAX31730 is not set
+# CONFIG_SENSORS_MAX6621 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MAX6697 is not set
+# CONFIG_SENSORS_MAX31790 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_TC654 is not set
+# CONFIG_SENSORS_MR75203 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LM95234 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_NCT6683 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_NCT7802 is not set
+# CONFIG_SENSORS_NPCM7XX is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SHT3x is not set
+# CONFIG_SENSORS_SHTC1 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_STTS751 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_ADC128D818 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA209 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_INA3221 is not set
+# CONFIG_SENSORS_TC74 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP103 is not set
+# CONFIG_SENSORS_TMP108 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_TMP513 is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83773G is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_XGENE is not set
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ACPI_POWER=y
+# CONFIG_SENSORS_ATK0110 is not set
+CONFIG_THERMAL=y
+# CONFIG_THERMAL_NETLINK is not set
+# CONFIG_THERMAL_STATISTICS is not set
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+CONFIG_THERMAL_GOV_FAIR_SHARE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_BANG_BANG=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_EMULATION=y
+
+#
+# Intel thermal drivers
+#
+CONFIG_INTEL_POWERCLAMP=y
+CONFIG_X86_PKG_TEMP_THERMAL=y
+CONFIG_INTEL_SOC_DTS_IOSF_CORE=y
+CONFIG_INTEL_SOC_DTS_THERMAL=y
+
+#
+# ACPI INT340X thermal drivers
+#
+CONFIG_INT340X_THERMAL=y
+CONFIG_ACPI_THERMAL_REL=y
+# CONFIG_INT3406_THERMAL is not set
+CONFIG_PROC_THERMAL_MMIO_RAPL=y
+# end of ACPI INT340X thermal drivers
+
+# CONFIG_INTEL_PCH_THERMAL is not set
+# end of Intel thermal drivers
+
+# CONFIG_GENERIC_ADC_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+CONFIG_SSB=y
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+# CONFIG_SSB_PCMCIAHOST is not set
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+# CONFIG_SSB_SDIOHOST is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+# CONFIG_SSB_DRIVER_GPIO is not set
+CONFIG_BCMA_POSSIBLE=y
+CONFIG_BCMA=y
+CONFIG_BCMA_HOST_PCI_POSSIBLE=y
+# CONFIG_BCMA_HOST_PCI is not set
+# CONFIG_BCMA_HOST_SOC is not set
+# CONFIG_BCMA_DRIVER_PCI is not set
+# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
+# CONFIG_BCMA_DRIVER_GPIO is not set
+# CONFIG_BCMA_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_BD9571MWV is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_MADERA is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_MP2629 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
+CONFIG_LPC_ICH=y
+CONFIG_LPC_SCH=y
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_INTEL_SOC_PMIC_CHTWC is not set
+# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set
+CONFIG_MFD_INTEL_LPSS=y
+CONFIG_MFD_INTEL_LPSS_ACPI=y
+CONFIG_MFD_INTEL_LPSS_PCI=y
+# CONFIG_MFD_INTEL_PMC_BXT is not set
+# CONFIG_MFD_IQS62X is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6360 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_UCB1400_CORE is not set
+CONFIG_MFD_RDC321X=y
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SL28CPLD is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_TI_LMU is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS68470 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TQMX86 is not set
+CONFIG_MFD_VX855=y
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_INTEL_M10_BMC is not set
+# end of Multifunction device drivers
+
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+# CONFIG_REGULATOR_88PG86X is not set
+CONFIG_REGULATOR_ACT8865=y
+CONFIG_REGULATOR_AD5398=y
+CONFIG_REGULATOR_DA9210=y
+CONFIG_REGULATOR_DA9211=y
+CONFIG_REGULATOR_FAN53555=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_ISL9305=y
+CONFIG_REGULATOR_ISL6271A=y
+CONFIG_REGULATOR_LP3971=y
+CONFIG_REGULATOR_LP3972=y
+CONFIG_REGULATOR_LP872X=y
+CONFIG_REGULATOR_LP8755=y
+CONFIG_REGULATOR_LTC3589=y
+# CONFIG_REGULATOR_LTC3676 is not set
+CONFIG_REGULATOR_MAX1586=y
+CONFIG_REGULATOR_MAX8649=y
+CONFIG_REGULATOR_MAX8660=y
+CONFIG_REGULATOR_MAX8952=y
+# CONFIG_REGULATOR_MAX77826 is not set
+# CONFIG_REGULATOR_MP8859 is not set
+# CONFIG_REGULATOR_MT6311 is not set
+# CONFIG_REGULATOR_PCA9450 is not set
+CONFIG_REGULATOR_PFUZE100=y
+# CONFIG_REGULATOR_PV88060 is not set
+# CONFIG_REGULATOR_PV88080 is not set
+# CONFIG_REGULATOR_PV88090 is not set
+# CONFIG_REGULATOR_PWM is not set
+# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set
+# CONFIG_REGULATOR_RT4801 is not set
+# CONFIG_REGULATOR_RTMV20 is not set
+# CONFIG_REGULATOR_SLG51000 is not set
+CONFIG_REGULATOR_TPS51632=y
+CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
+# CONFIG_REGULATOR_TPS65132 is not set
+# CONFIG_REGULATOR_TPS6524X is not set
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_CEC_SUPPORT is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+CONFIG_INTEL_GTT=y
+# CONFIG_VGA_ARB is not set
+# CONFIG_VGA_SWITCHEROO is not set
+CONFIG_DRM=y
+CONFIG_DRM_MIPI_DSI=y
+CONFIG_DRM_DP_AUX_CHARDEV=y
+# CONFIG_DRM_DEBUG_MM is not set
+# CONFIG_DRM_DEBUG_SELFTEST is not set
+CONFIG_DRM_KMS_HELPER=y
+CONFIG_DRM_KMS_FB_HELPER=y
+# CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS is not set
+CONFIG_DRM_FBDEV_EMULATION=y
+CONFIG_DRM_FBDEV_OVERALLOC=100
+# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set
+# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
+# CONFIG_DRM_DP_CEC is not set
+
+#
+# I2C encoder or helper chips
+#
+CONFIG_DRM_I2C_CH7006=y
+CONFIG_DRM_I2C_SIL164=y
+CONFIG_DRM_I2C_NXP_TDA998X=y
+# CONFIG_DRM_I2C_NXP_TDA9950 is not set
+# end of I2C encoder or helper chips
+
+#
+# ARM devices
+#
+# end of ARM devices
+
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_AMDGPU is not set
+# CONFIG_DRM_NOUVEAU is not set
+CONFIG_DRM_I915=y
+CONFIG_DRM_I915_FORCE_PROBE=""
+CONFIG_DRM_I915_CAPTURE_ERROR=y
+CONFIG_DRM_I915_COMPRESS_ERROR=y
+CONFIG_DRM_I915_USERPTR=y
+# CONFIG_DRM_I915_GVT is not set
+
+#
+# drm/i915 Debugging
+#
+CONFIG_DRM_I915_WERROR=y
+# CONFIG_DRM_I915_DEBUG is not set
+# CONFIG_DRM_I915_DEBUG_MMIO is not set
+# CONFIG_DRM_I915_DEBUG_GEM is not set
+# CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS is not set
+# CONFIG_DRM_I915_SW_FENCE_CHECK_DAG is not set
+# CONFIG_DRM_I915_DEBUG_GUC is not set
+# CONFIG_DRM_I915_SELFTEST is not set
+# CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS is not set
+# CONFIG_DRM_I915_DEBUG_VBLANK_EVADE is not set
+# CONFIG_DRM_I915_DEBUG_RUNTIME_PM is not set
+# end of drm/i915 Debugging
+
+#
+# drm/i915 Profile Guided Optimisation
+#
+CONFIG_DRM_I915_FENCE_TIMEOUT=10000
+CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND=250
+CONFIG_DRM_I915_HEARTBEAT_INTERVAL=2500
+CONFIG_DRM_I915_PREEMPT_TIMEOUT=640
+CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT=8000
+CONFIG_DRM_I915_STOP_TIMEOUT=100
+CONFIG_DRM_I915_TIMESLICE_DURATION=1
+# end of drm/i915 Profile Guided Optimisation
+
+CONFIG_DRM_VGEM=y
+# CONFIG_DRM_VKMS is not set
+# CONFIG_DRM_VMWGFX is not set
+# CONFIG_DRM_GMA500 is not set
+# CONFIG_DRM_UDL is not set
+# CONFIG_DRM_AST is not set
+# CONFIG_DRM_MGAG200 is not set
+# CONFIG_DRM_QXL is not set
+# CONFIG_DRM_BOCHS is not set
+CONFIG_DRM_PANEL=y
+
+#
+# Display Panels
+#
+# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set
+# end of Display Panels
+
+CONFIG_DRM_BRIDGE=y
+CONFIG_DRM_PANEL_BRIDGE=y
+
+#
+# Display Interface Bridges
+#
+# CONFIG_DRM_ANALOGIX_ANX78XX is not set
+# end of Display Interface Bridges
+
+# CONFIG_DRM_ETNAVIV is not set
+# CONFIG_DRM_CIRRUS_QEMU is not set
+# CONFIG_DRM_GM12U320 is not set
+# CONFIG_TINYDRM_HX8357D is not set
+# CONFIG_TINYDRM_ILI9225 is not set
+# CONFIG_TINYDRM_ILI9341 is not set
+# CONFIG_TINYDRM_ILI9486 is not set
+# CONFIG_TINYDRM_MI0283QT is not set
+# CONFIG_TINYDRM_REPAPER is not set
+# CONFIG_TINYDRM_ST7586 is not set
+# CONFIG_TINYDRM_ST7735R is not set
+# CONFIG_DRM_VBOXVIDEO is not set
+# CONFIG_DRM_LEGACY is not set
+CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_VESA is not set
+# CONFIG_FB_N411 is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I740 is not set
+# CONFIG_FB_LE80578 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SM712 is not set
+# end of Frame buffer Devices
+
+#
+# Backlight & LCD device support
+#
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI922X is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+# CONFIG_LCD_AMS369FG06 is not set
+# CONFIG_LCD_LMS501KF03 is not set
+# CONFIG_LCD_HX8357 is not set
+# CONFIG_LCD_OTM3225A is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_KTD253 is not set
+# CONFIG_BACKLIGHT_PWM is not set
+CONFIG_BACKLIGHT_APPLE=y
+# CONFIG_BACKLIGHT_QCOM_WLED is not set
+CONFIG_BACKLIGHT_SAHARA=y
+CONFIG_BACKLIGHT_ADP8860=y
+CONFIG_BACKLIGHT_ADP8870=y
+# CONFIG_BACKLIGHT_LM3630A is not set
+CONFIG_BACKLIGHT_LM3639=y
+# CONFIG_BACKLIGHT_LP855X is not set
+CONFIG_BACKLIGHT_GPIO=y
+CONFIG_BACKLIGHT_LV5207LP=y
+CONFIG_BACKLIGHT_BD6107=y
+# CONFIG_BACKLIGHT_ARCXCNN is not set
+# end of Backlight & LCD device support
+
+CONFIG_HDMI=y
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=80
+CONFIG_DUMMY_CONSOLE_ROWS=25
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
+# end of Console display driver support
+
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# end of Graphics support
+
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_PCM_ELD=y
+CONFIG_SND_PCM_IEC958=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_SEQ_DEVICE=y
+CONFIG_SND_COMPRESS_OFFLOAD=y
+CONFIG_SND_JACK=y
+CONFIG_SND_JACK_INPUT_DEV=y
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_PCM_TIMER=y
+CONFIG_SND_HRTIMER=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_PROC_FS=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_VERBOSE=y
+CONFIG_SND_PCM_XRUN_DEBUG=y
+# CONFIG_SND_CTL_VALIDATION is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+CONFIG_SND_SEQ_MIDI_EVENT=y
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_PCSP is not set
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ASIHPI is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+CONFIG_SND_INTEL8X0=y
+CONFIG_SND_INTEL8X0M=y
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LOLA is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SE6X is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# HD-Audio
+#
+CONFIG_SND_HDA=y
+CONFIG_SND_HDA_INTEL=y
+CONFIG_SND_HDA_HWDEP=y
+CONFIG_SND_HDA_RECONFIG=y
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_INPUT_BEEP_MODE=1
+CONFIG_SND_HDA_PATCH_LOADER=y
+# CONFIG_SND_HDA_CODEC_REALTEK is not set
+# CONFIG_SND_HDA_CODEC_ANALOG is not set
+# CONFIG_SND_HDA_CODEC_SIGMATEL is not set
+# CONFIG_SND_HDA_CODEC_VIA is not set
+# CONFIG_SND_HDA_CODEC_HDMI is not set
+# CONFIG_SND_HDA_CODEC_CIRRUS is not set
+# CONFIG_SND_HDA_CODEC_CONEXANT is not set
+# CONFIG_SND_HDA_CODEC_CA0110 is not set
+# CONFIG_SND_HDA_CODEC_CA0132 is not set
+# CONFIG_SND_HDA_CODEC_CMEDIA is not set
+# CONFIG_SND_HDA_CODEC_SI3054 is not set
+CONFIG_SND_HDA_GENERIC=y
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
+# CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM is not set
+# end of HD-Audio
+
+CONFIG_SND_HDA_CORE=y
+CONFIG_SND_HDA_COMPONENT=y
+CONFIG_SND_HDA_I915=y
+CONFIG_SND_HDA_PREALLOC_SIZE=64
+CONFIG_SND_INTEL_NHLT=y
+CONFIG_SND_INTEL_DSP_CONFIG=y
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_US122L is not set
+# CONFIG_SND_USB_6FIRE is not set
+# CONFIG_SND_USB_HIFACE is not set
+# CONFIG_SND_BCD2000 is not set
+# CONFIG_SND_USB_POD is not set
+# CONFIG_SND_USB_PODHD is not set
+# CONFIG_SND_USB_TONEPORT is not set
+# CONFIG_SND_USB_VARIAX is not set
+# CONFIG_SND_PCMCIA is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_COMPRESS=y
+CONFIG_SND_SOC_ACPI=y
+# CONFIG_SND_SOC_AMD_ACP is not set
+# CONFIG_SND_SOC_AMD_ACP3x is not set
+# CONFIG_SND_SOC_AMD_RENOIR is not set
+# CONFIG_SND_ATMEL_SOC is not set
+# CONFIG_SND_BCM63XX_I2S_WHISTLER is not set
+# CONFIG_SND_DESIGNWARE_I2S is not set
+
+#
+# SoC Audio for Freescale CPUs
+#
+
+#
+# Common SoC Audio options for Freescale CPUs:
+#
+# CONFIG_SND_SOC_FSL_ASRC is not set
+# CONFIG_SND_SOC_FSL_SAI is not set
+# CONFIG_SND_SOC_FSL_AUDMIX is not set
+# CONFIG_SND_SOC_FSL_SSI is not set
+# CONFIG_SND_SOC_FSL_SPDIF is not set
+# CONFIG_SND_SOC_FSL_ESAI is not set
+# CONFIG_SND_SOC_FSL_MICFIL is not set
+# CONFIG_SND_SOC_IMX_AUDMUX is not set
+# end of SoC Audio for Freescale CPUs
+
+# CONFIG_SND_I2S_HI6210_I2S is not set
+# CONFIG_SND_SOC_IMG is not set
+CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y
+# CONFIG_SND_SOC_INTEL_CATPT is not set
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM=y
+# CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI is not set
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI=y
+# CONFIG_SND_SOC_INTEL_SKYLAKE is not set
+# CONFIG_SND_SOC_INTEL_SKL is not set
+# CONFIG_SND_SOC_INTEL_APL is not set
+# CONFIG_SND_SOC_INTEL_KBL is not set
+# CONFIG_SND_SOC_INTEL_GLK is not set
+# CONFIG_SND_SOC_INTEL_CNL is not set
+# CONFIG_SND_SOC_INTEL_CFL is not set
+# CONFIG_SND_SOC_INTEL_CML_H is not set
+# CONFIG_SND_SOC_INTEL_CML_LP is not set
+CONFIG_SND_SOC_ACPI_INTEL_MATCH=y
+CONFIG_SND_SOC_INTEL_MACH=y
+# CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES is not set
+CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH=y
+CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH=y
+CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH=y
+CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH=y
+CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH=y
+# CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH is not set
+# CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH is not set
+CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH=y
+# CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH is not set
+CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH=y
+# CONFIG_SND_SOC_MTK_BTCVSD is not set
+# CONFIG_SND_SOC_SOF_TOPLEVEL is not set
+
+#
+# STMicroelectronics STM32 SOC audio support
+#
+# end of STMicroelectronics STM32 SOC audio support
+
+# CONFIG_SND_SOC_XILINX_I2S is not set
+# CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER is not set
+# CONFIG_SND_SOC_XILINX_SPDIF is not set
+# CONFIG_SND_SOC_XTFPGA_I2S is not set
+# CONFIG_ZX_TDM is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
+
+#
+# CODEC drivers
+#
+# CONFIG_SND_SOC_AC97_CODEC is not set
+# CONFIG_SND_SOC_ADAU1701 is not set
+# CONFIG_SND_SOC_ADAU1761_I2C is not set
+# CONFIG_SND_SOC_ADAU1761_SPI is not set
+# CONFIG_SND_SOC_ADAU7002 is not set
+# CONFIG_SND_SOC_ADAU7118_HW is not set
+# CONFIG_SND_SOC_ADAU7118_I2C is not set
+# CONFIG_SND_SOC_AK4104 is not set
+# CONFIG_SND_SOC_AK4118 is not set
+# CONFIG_SND_SOC_AK4458 is not set
+# CONFIG_SND_SOC_AK4554 is not set
+# CONFIG_SND_SOC_AK4613 is not set
+# CONFIG_SND_SOC_AK4642 is not set
+# CONFIG_SND_SOC_AK5386 is not set
+# CONFIG_SND_SOC_AK5558 is not set
+# CONFIG_SND_SOC_ALC5623 is not set
+# CONFIG_SND_SOC_BD28623 is not set
+# CONFIG_SND_SOC_BT_SCO is not set
+# CONFIG_SND_SOC_CS35L32 is not set
+# CONFIG_SND_SOC_CS35L33 is not set
+# CONFIG_SND_SOC_CS35L34 is not set
+# CONFIG_SND_SOC_CS35L35 is not set
+# CONFIG_SND_SOC_CS35L36 is not set
+# CONFIG_SND_SOC_CS42L42 is not set
+# CONFIG_SND_SOC_CS42L51_I2C is not set
+# CONFIG_SND_SOC_CS42L52 is not set
+# CONFIG_SND_SOC_CS42L56 is not set
+# CONFIG_SND_SOC_CS42L73 is not set
+# CONFIG_SND_SOC_CS4234 is not set
+# CONFIG_SND_SOC_CS4265 is not set
+# CONFIG_SND_SOC_CS4270 is not set
+# CONFIG_SND_SOC_CS4271_I2C is not set
+# CONFIG_SND_SOC_CS4271_SPI is not set
+# CONFIG_SND_SOC_CS42XX8_I2C is not set
+# CONFIG_SND_SOC_CS43130 is not set
+# CONFIG_SND_SOC_CS4341 is not set
+# CONFIG_SND_SOC_CS4349 is not set
+# CONFIG_SND_SOC_CS53L30 is not set
+# CONFIG_SND_SOC_CX2072X is not set
+CONFIG_SND_SOC_DA7213=y
+# CONFIG_SND_SOC_DMIC is not set
+CONFIG_SND_SOC_HDMI_CODEC=y
+# CONFIG_SND_SOC_ES7134 is not set
+# CONFIG_SND_SOC_ES7241 is not set
+# CONFIG_SND_SOC_ES8316 is not set
+# CONFIG_SND_SOC_ES8328_I2C is not set
+# CONFIG_SND_SOC_ES8328_SPI is not set
+# CONFIG_SND_SOC_GTM601 is not set
+# CONFIG_SND_SOC_INNO_RK3036 is not set
+# CONFIG_SND_SOC_MAX98088 is not set
+CONFIG_SND_SOC_MAX98090=y
+# CONFIG_SND_SOC_MAX98357A is not set
+# CONFIG_SND_SOC_MAX98504 is not set
+# CONFIG_SND_SOC_MAX9867 is not set
+# CONFIG_SND_SOC_MAX98927 is not set
+# CONFIG_SND_SOC_MAX98373_I2C is not set
+# CONFIG_SND_SOC_MAX98390 is not set
+# CONFIG_SND_SOC_MAX9860 is not set
+# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set
+# CONFIG_SND_SOC_PCM1681 is not set
+# CONFIG_SND_SOC_PCM1789_I2C is not set
+# CONFIG_SND_SOC_PCM179X_I2C is not set
+# CONFIG_SND_SOC_PCM179X_SPI is not set
+# CONFIG_SND_SOC_PCM186X_I2C is not set
+# CONFIG_SND_SOC_PCM186X_SPI is not set
+# CONFIG_SND_SOC_PCM3060_I2C is not set
+# CONFIG_SND_SOC_PCM3060_SPI is not set
+# CONFIG_SND_SOC_PCM3168A_I2C is not set
+# CONFIG_SND_SOC_PCM3168A_SPI is not set
+# CONFIG_SND_SOC_PCM512x_I2C is not set
+# CONFIG_SND_SOC_PCM512x_SPI is not set
+# CONFIG_SND_SOC_RK3328 is not set
+CONFIG_SND_SOC_RL6231=y
+# CONFIG_SND_SOC_RT5616 is not set
+# CONFIG_SND_SOC_RT5631 is not set
+CONFIG_SND_SOC_RT5640=y
+CONFIG_SND_SOC_RT5645=y
+CONFIG_SND_SOC_RT5651=y
+CONFIG_SND_SOC_RT5670=y
+# CONFIG_SND_SOC_SGTL5000 is not set
+# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set
+# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set
+# CONFIG_SND_SOC_SPDIF is not set
+# CONFIG_SND_SOC_SSM2305 is not set
+# CONFIG_SND_SOC_SSM2602_SPI is not set
+# CONFIG_SND_SOC_SSM2602_I2C is not set
+# CONFIG_SND_SOC_SSM4567 is not set
+# CONFIG_SND_SOC_STA32X is not set
+# CONFIG_SND_SOC_STA350 is not set
+# CONFIG_SND_SOC_STI_SAS is not set
+# CONFIG_SND_SOC_TAS2552 is not set
+# CONFIG_SND_SOC_TAS2562 is not set
+# CONFIG_SND_SOC_TAS2764 is not set
+# CONFIG_SND_SOC_TAS2770 is not set
+# CONFIG_SND_SOC_TAS5086 is not set
+# CONFIG_SND_SOC_TAS571X is not set
+# CONFIG_SND_SOC_TAS5720 is not set
+# CONFIG_SND_SOC_TAS6424 is not set
+# CONFIG_SND_SOC_TDA7419 is not set
+# CONFIG_SND_SOC_TFA9879 is not set
+# CONFIG_SND_SOC_TLV320AIC23_I2C is not set
+# CONFIG_SND_SOC_TLV320AIC23_SPI is not set
+# CONFIG_SND_SOC_TLV320AIC31XX is not set
+# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set
+# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set
+# CONFIG_SND_SOC_TLV320AIC3X is not set
+# CONFIG_SND_SOC_TLV320ADCX140 is not set
+CONFIG_SND_SOC_TS3A227E=y
+# CONFIG_SND_SOC_TSCS42XX is not set
+# CONFIG_SND_SOC_TSCS454 is not set
+# CONFIG_SND_SOC_UDA1334 is not set
+# CONFIG_SND_SOC_WM8510 is not set
+# CONFIG_SND_SOC_WM8523 is not set
+# CONFIG_SND_SOC_WM8524 is not set
+# CONFIG_SND_SOC_WM8580 is not set
+# CONFIG_SND_SOC_WM8711 is not set
+# CONFIG_SND_SOC_WM8728 is not set
+# CONFIG_SND_SOC_WM8731 is not set
+# CONFIG_SND_SOC_WM8737 is not set
+# CONFIG_SND_SOC_WM8741 is not set
+# CONFIG_SND_SOC_WM8750 is not set
+# CONFIG_SND_SOC_WM8753 is not set
+# CONFIG_SND_SOC_WM8770 is not set
+# CONFIG_SND_SOC_WM8776 is not set
+# CONFIG_SND_SOC_WM8782 is not set
+# CONFIG_SND_SOC_WM8804_I2C is not set
+# CONFIG_SND_SOC_WM8804_SPI is not set
+# CONFIG_SND_SOC_WM8903 is not set
+# CONFIG_SND_SOC_WM8904 is not set
+# CONFIG_SND_SOC_WM8960 is not set
+# CONFIG_SND_SOC_WM8962 is not set
+# CONFIG_SND_SOC_WM8974 is not set
+# CONFIG_SND_SOC_WM8978 is not set
+# CONFIG_SND_SOC_WM8985 is not set
+# CONFIG_SND_SOC_ZL38060 is not set
+# CONFIG_SND_SOC_ZX_AUD96P22 is not set
+# CONFIG_SND_SOC_MAX9759 is not set
+# CONFIG_SND_SOC_MT6351 is not set
+# CONFIG_SND_SOC_MT6358 is not set
+# CONFIG_SND_SOC_MT6660 is not set
+# CONFIG_SND_SOC_NAU8540 is not set
+# CONFIG_SND_SOC_NAU8810 is not set
+# CONFIG_SND_SOC_NAU8822 is not set
+# CONFIG_SND_SOC_NAU8824 is not set
+# CONFIG_SND_SOC_TPA6130A2 is not set
+# end of CODEC drivers
+
+# CONFIG_SND_SIMPLE_CARD is not set
+CONFIG_SND_X86=y
+CONFIG_HDMI_LPE_AUDIO=y
+CONFIG_AC97_BUS=y
+
+#
+# HID support
+#
+CONFIG_HID=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACCUTOUCH is not set
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_APPLEIR=y
+# CONFIG_HID_ASUS is not set
+CONFIG_HID_AUREAL=y
+CONFIG_HID_BELKIN=y
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_BIGBEN_FF is not set
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+# CONFIG_HID_CORSAIR is not set
+# CONFIG_HID_COUGAR is not set
+# CONFIG_HID_MACALLY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CMEDIA is not set
+CONFIG_HID_CP2112=y
+# CONFIG_HID_CREATIVE_SB0540 is not set
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
+# CONFIG_HID_ELAN is not set
+CONFIG_HID_ELECOM=y
+CONFIG_HID_ELO=y
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_GLORIOUS is not set
+CONFIG_HID_HOLTEK=y
+CONFIG_HOLTEK_FF=y
+# CONFIG_HID_VIVALDI is not set
+CONFIG_HID_GT683R=y
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
+# CONFIG_HID_VIEWSONIC is not set
+CONFIG_HID_GYRATION=y
+CONFIG_HID_ICADE=y
+# CONFIG_HID_ITE is not set
+# CONFIG_HID_JABRA is not set
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LED=y
+CONFIG_HID_LENOVO=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_HID_LOGITECH_HIDPP=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MALTRON is not set
+# CONFIG_HID_MAYFLASH is not set
+# CONFIG_HID_REDRAGON is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_MULTITOUCH=y
+# CONFIG_HID_NTI is not set
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PENMOUNT=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_PICOLCD=y
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_PLANTRONICS=y
+CONFIG_HID_PRIMAX=y
+# CONFIG_HID_RETRODE is not set
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_SONY_FF=y
+CONFIG_HID_SPEEDLINK=y
+# CONFIG_HID_STEAM is not set
+CONFIG_HID_STEELSERIES=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_RMI=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THINGM=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_THRUSTMASTER_FF=y
+# CONFIG_HID_UDRAW_PS3 is not set
+# CONFIG_HID_U2FZERO is not set
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
+CONFIG_HID_XINMO=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_ZEROPLUS_FF=y
+CONFIG_HID_ZYDACRON=y
+CONFIG_HID_SENSOR_HUB=y
+# CONFIG_HID_SENSOR_CUSTOM_SENSOR is not set
+# CONFIG_HID_ALPS is not set
+# CONFIG_HID_MCP2221 is not set
+# end of Special HID drivers
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+# end of USB HID support
+
+#
+# I2C HID support
+#
+CONFIG_I2C_HID=y
+# end of I2C HID support
+
+#
+# Intel ISH HID support
+#
+# CONFIG_INTEL_ISH_HID is not set
+# end of Intel ISH HID support
+# end of HID support
+
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+# CONFIG_USB_LED_TRIG is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_USB_CONN_GPIO is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_PCI=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_FEW_INIT_RETRIES is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_PRODUCTLIST is not set
+# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set
+# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set
+CONFIG_USB_AUTOSUSPEND_DELAY=2
+CONFIG_USB_MON=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+# CONFIG_USB_XHCI_DBGCAP is not set
+CONFIG_USB_XHCI_PCI=y
+# CONFIG_USB_XHCI_PCI_RENESAS is not set
+# CONFIG_USB_XHCI_PLATFORM is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_PCI=y
+# CONFIG_USB_EHCI_FSL is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PCI=y
+# CONFIG_USB_OHCI_HCD_SSB is not set
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_BCMA is not set
+# CONFIG_USB_HCD_SSB is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+CONFIG_USB_TMC=y
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_REALTEK=y
+CONFIG_REALTEK_AUTOPM=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_UAS=y
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=y
+CONFIG_USB_MICROTEK=y
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_CDNS3 is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_CONSOLE is not set
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=y
+CONFIG_USB_SERIAL_AIRCABLE=y
+CONFIG_USB_SERIAL_ARK3116=y
+CONFIG_USB_SERIAL_BELKIN=y
+CONFIG_USB_SERIAL_CH341=y
+CONFIG_USB_SERIAL_WHITEHEAT=y
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=y
+CONFIG_USB_SERIAL_CP210X=y
+CONFIG_USB_SERIAL_CYPRESS_M8=y
+CONFIG_USB_SERIAL_EMPEG=y
+CONFIG_USB_SERIAL_FTDI_SIO=y
+CONFIG_USB_SERIAL_VISOR=y
+CONFIG_USB_SERIAL_IPAQ=y
+CONFIG_USB_SERIAL_IR=y
+CONFIG_USB_SERIAL_EDGEPORT=y
+CONFIG_USB_SERIAL_EDGEPORT_TI=y
+CONFIG_USB_SERIAL_F81232=y
+# CONFIG_USB_SERIAL_F8153X is not set
+CONFIG_USB_SERIAL_GARMIN=y
+CONFIG_USB_SERIAL_IPW=y
+CONFIG_USB_SERIAL_IUU=y
+CONFIG_USB_SERIAL_KEYSPAN_PDA=y
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KLSI=y
+CONFIG_USB_SERIAL_KOBIL_SCT=y
+CONFIG_USB_SERIAL_MCT_U232=y
+CONFIG_USB_SERIAL_METRO=y
+CONFIG_USB_SERIAL_MOS7720=y
+CONFIG_USB_SERIAL_MOS7840=y
+CONFIG_USB_SERIAL_MXUPORT=y
+CONFIG_USB_SERIAL_NAVMAN=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_SERIAL_OTI6858=y
+CONFIG_USB_SERIAL_QCAUX=y
+CONFIG_USB_SERIAL_QUALCOMM=y
+CONFIG_USB_SERIAL_SPCP8X5=y
+CONFIG_USB_SERIAL_SAFE=y
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=y
+CONFIG_USB_SERIAL_SYMBOL=y
+CONFIG_USB_SERIAL_TI=y
+CONFIG_USB_SERIAL_CYBERJACK=y
+CONFIG_USB_SERIAL_XIRCOM=y
+CONFIG_USB_SERIAL_WWAN=y
+CONFIG_USB_SERIAL_OPTION=y
+CONFIG_USB_SERIAL_OMNINET=y
+CONFIG_USB_SERIAL_OPTICON=y
+CONFIG_USB_SERIAL_XSENS_MT=y
+CONFIG_USB_SERIAL_WISHBONE=y
+CONFIG_USB_SERIAL_SSU100=y
+CONFIG_USB_SERIAL_QT2=y
+# CONFIG_USB_SERIAL_UPD78F0730 is not set
+CONFIG_USB_SERIAL_DEBUG=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_APPLE_MFI_FASTCHARGE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_EZUSB_FX2=y
+# CONFIG_USB_HUB_USB251XB is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+# CONFIG_USB_CHAOSKEY is not set
+
+#
+# USB Physical Layer drivers
+#
+CONFIG_USB_PHY=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_ISP1301=y
+# end of USB Physical Layer drivers
+
+# CONFIG_USB_GADGET is not set
+# CONFIG_TYPEC is not set
+# CONFIG_USB_ROLE_SWITCH is not set
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_IO_ACCESSORS=y
+CONFIG_MMC_SDHCI_PCI=y
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_ACPI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+CONFIG_MMC_WBSD=y
+CONFIG_MMC_TIFM_SD=y
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_SDRICOH_CS=y
+CONFIG_MMC_CB710=y
+CONFIG_MMC_VIA_SDMMC=y
+CONFIG_MMC_VUB300=y
+CONFIG_MMC_USHC=y
+CONFIG_MMC_USDHI6ROL0=y
+CONFIG_MMC_CQHCI=y
+# CONFIG_MMC_HSQ is not set
+CONFIG_MMC_TOSHIBA_PCI=y
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_SDHCI_XENON is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_CLASS_FLASH is not set
+# CONFIG_LEDS_CLASS_MULTICOLOR is not set
+# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_APU is not set
+CONFIG_LEDS_LM3530=y
+# CONFIG_LEDS_LM3532 is not set
+CONFIG_LEDS_LM3642=y
+CONFIG_LEDS_PCA9532=y
+CONFIG_LEDS_PCA9532_GPIO=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_LP3944=y
+# CONFIG_LEDS_LP3952 is not set
+# CONFIG_LEDS_LP50XX is not set
+CONFIG_LEDS_CLEVO_MAIL=y
+CONFIG_LEDS_PCA955X=y
+# CONFIG_LEDS_PCA955X_GPIO is not set
+CONFIG_LEDS_PCA963X=y
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_PWM is not set
+CONFIG_LEDS_REGULATOR=y
+CONFIG_LEDS_BD2802=y
+CONFIG_LEDS_INTEL_SS4200=y
+CONFIG_LEDS_TCA6507=y
+# CONFIG_LEDS_TLC591XX is not set
+CONFIG_LEDS_LM355x=y
+
+#
+# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
+#
+CONFIG_LEDS_BLINKM=y
+# CONFIG_LEDS_MLXCPLD is not set
+# CONFIG_LEDS_MLXREG is not set
+# CONFIG_LEDS_USER is not set
+# CONFIG_LEDS_NIC78BX is not set
+# CONFIG_LEDS_TI_LMU_COMMON is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+# CONFIG_LEDS_TRIGGER_DISK is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+# CONFIG_LEDS_TRIGGER_ACTIVITY is not set
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+# CONFIG_LEDS_TRIGGER_PANIC is not set
+# CONFIG_LEDS_TRIGGER_NETDEV is not set
+# CONFIG_LEDS_TRIGGER_PATTERN is not set
+# CONFIG_LEDS_TRIGGER_AUDIO is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_MC146818_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+CONFIG_RTC_NVMEM=y
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABEOZ9 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1307_CENTURY is not set
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS1672=y
+CONFIG_RTC_DRV_MAX6900=y
+CONFIG_RTC_DRV_RS5C372=y
+CONFIG_RTC_DRV_ISL1208=y
+CONFIG_RTC_DRV_ISL12022=y
+CONFIG_RTC_DRV_X1205=y
+CONFIG_RTC_DRV_PCF8523=y
+CONFIG_RTC_DRV_PCF85063=y
+# CONFIG_RTC_DRV_PCF85363 is not set
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_PCF8583=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_FM3130=y
+# CONFIG_RTC_DRV_RX8010 is not set
+CONFIG_RTC_DRV_RX8581=y
+CONFIG_RTC_DRV_RX8025=y
+CONFIG_RTC_DRV_EM3027=y
+# CONFIG_RTC_DRV_RV3028 is not set
+# CONFIG_RTC_DRV_RV3032 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+# CONFIG_RTC_DRV_SD3078 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS3232=y
+CONFIG_RTC_DRV_DS3232_HWMON=y
+CONFIG_RTC_DRV_PCF2127=y
+CONFIG_RTC_DRV_RV3029C2=y
+CONFIG_RTC_DRV_RV3029_HWMON=y
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1286=y
+CONFIG_RTC_DRV_DS1511=y
+CONFIG_RTC_DRV_DS1553=y
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+CONFIG_RTC_DRV_DS1742=y
+CONFIG_RTC_DRV_DS2404=y
+CONFIG_RTC_DRV_STK17TA8=y
+CONFIG_RTC_DRV_M48T86=y
+CONFIG_RTC_DRV_M48T35=y
+CONFIG_RTC_DRV_M48T59=y
+CONFIG_RTC_DRV_MSM6242=y
+CONFIG_RTC_DRV_BQ4802=y
+CONFIG_RTC_DRV_RP5C01=y
+CONFIG_RTC_DRV_V3020=y
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_FTRTC010 is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_RTC_DRV_HID_SENSOR_TIME=y
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_ACPI=y
+# CONFIG_ALTERA_MSGDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_INTEL_IDXD is not set
+CONFIG_INTEL_IOATDMA=y
+# CONFIG_PLX_DMA is not set
+# CONFIG_XILINX_ZYNQMP_DPDMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+CONFIG_DW_DMAC_CORE=y
+CONFIG_DW_DMAC=y
+CONFIG_DW_DMAC_PCI=y
+# CONFIG_DW_EDMA is not set
+# CONFIG_DW_EDMA_PCIE is not set
+# CONFIG_SF_PDMA is not set
+
+#
+# DMA Clients
+#
+CONFIG_ASYNC_TX_DMA=y
+# CONFIG_DMATEST is not set
+CONFIG_DMA_ENGINE_RAID=y
+
+#
+# DMABUF options
+#
+CONFIG_SYNC_FILE=y
+# CONFIG_SW_SYNC is not set
+# CONFIG_UDMABUF is not set
+# CONFIG_DMABUF_MOVE_NOTIFY is not set
+# CONFIG_DMABUF_SELFTESTS is not set
+# CONFIG_DMABUF_HEAPS is not set
+# end of DMABUF options
+
+CONFIG_DCA=y
+CONFIG_AUXDISPLAY=y
+# CONFIG_HD44780 is not set
+# CONFIG_IMG_ASCII_LCD is not set
+# CONFIG_CHARLCD_BL_OFF is not set
+# CONFIG_CHARLCD_BL_ON is not set
+CONFIG_CHARLCD_BL_FLASH=y
+CONFIG_UIO=y
+CONFIG_UIO_CIF=y
+CONFIG_UIO_PDRV_GENIRQ=y
+CONFIG_UIO_DMEM_GENIRQ=y
+CONFIG_UIO_AEC=y
+CONFIG_UIO_SERCOS3=y
+CONFIG_UIO_PCI_GENERIC=y
+CONFIG_UIO_NETX=y
+# CONFIG_UIO_PRUSS is not set
+CONFIG_UIO_MF624=y
+# CONFIG_VFIO is not set
+CONFIG_VIRT_DRIVERS=y
+# CONFIG_VBOXGUEST is not set
+# CONFIG_NITRO_ENCLAVES is not set
+CONFIG_VIRTIO_MENU=y
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_MMIO is not set
+# CONFIG_VDPA is not set
+CONFIG_VHOST_MENU=y
+# CONFIG_VHOST_NET is not set
+# CONFIG_VHOST_SCSI is not set
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_HYPERV is not set
+# end of Microsoft Hyper-V guest support
+
+# CONFIG_GREYBUS is not set
+# CONFIG_STAGING is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+# CONFIG_ACPI_WMI is not set
+# CONFIG_ACERHDF is not set
+# CONFIG_ACER_WIRELESS is not set
+# CONFIG_APPLE_GMUX is not set
+# CONFIG_ASUS_LAPTOP is not set
+# CONFIG_ASUS_WIRELESS is not set
+# CONFIG_EEEPC_LAPTOP is not set
+# CONFIG_DCDBAS is not set
+# CONFIG_DELL_SMBIOS is not set
+# CONFIG_DELL_RBTN is not set
+# CONFIG_DELL_RBU is not set
+# CONFIG_DELL_SMO8800 is not set
+# CONFIG_AMILO_RFKILL is not set
+# CONFIG_FUJITSU_LAPTOP is not set
+# CONFIG_FUJITSU_TABLET is not set
+# CONFIG_GPD_POCKET_FAN is not set
+# CONFIG_HP_ACCEL is not set
+# CONFIG_HP_WIRELESS is not set
+# CONFIG_IBM_RTL is not set
+# CONFIG_IDEAPAD_LAPTOP is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_THINKPAD_ACPI is not set
+# CONFIG_INTEL_ATOMISP2_LED is not set
+# CONFIG_INTEL_ATOMISP2_PM is not set
+# CONFIG_INTEL_HID_EVENT is not set
+# CONFIG_INTEL_INT0002_VGPIO is not set
+# CONFIG_INTEL_MENLOW is not set
+# CONFIG_INTEL_OAKTRAIL is not set
+# CONFIG_INTEL_VBTN is not set
+# CONFIG_SURFACE_3_BUTTON is not set
+# CONFIG_SURFACE_3_POWER_OPREGION is not set
+# CONFIG_SURFACE_PRO3_BUTTON is not set
+# CONFIG_MSI_LAPTOP is not set
+# CONFIG_PCENGINES_APU2 is not set
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_SAMSUNG_Q10 is not set
+# CONFIG_TOSHIBA_BT_RFKILL is not set
+# CONFIG_TOSHIBA_HAPS is not set
+# CONFIG_ACPI_CMPC is not set
+# CONFIG_COMPAL_LAPTOP is not set
+# CONFIG_PANASONIC_LAPTOP is not set
+# CONFIG_SONY_LAPTOP is not set
+# CONFIG_SYSTEM76_ACPI is not set
+# CONFIG_TOPSTAR_LAPTOP is not set
+# CONFIG_I2C_MULTI_INSTANTIATE is not set
+# CONFIG_MLX_PLATFORM is not set
+# CONFIG_INTEL_IPS is not set
+# CONFIG_INTEL_RST is not set
+# CONFIG_INTEL_SMARTCONNECT is not set
+
+#
+# Intel Speed Select Technology interface support
+#
+# CONFIG_INTEL_SPEED_SELECT_INTERFACE is not set
+# end of Intel Speed Select Technology interface support
+
+# CONFIG_INTEL_UNCORE_FREQ_CONTROL is not set
+# CONFIG_INTEL_PMC_CORE is not set
+# CONFIG_INTEL_PUNIT_IPC is not set
+# CONFIG_INTEL_SCU_PCI is not set
+# CONFIG_INTEL_SCU_PLATFORM is not set
+CONFIG_PMC_ATOM=y
+CONFIG_CHROME_PLATFORMS=y
+CONFIG_CHROMEOS_LAPTOP=y
+CONFIG_CHROMEOS_PSTORE=y
+# CONFIG_CHROMEOS_TBMC is not set
+# CONFIG_CROS_EC is not set
+CONFIG_CROS_KBD_LED_BACKLIGHT=y
+# CONFIG_MELLANOX_PLATFORM is not set
+CONFIG_HAVE_CLK=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+# CONFIG_COMMON_CLK_MAX9485 is not set
+# CONFIG_COMMON_CLK_SI5341 is not set
+CONFIG_COMMON_CLK_SI5351=y
+# CONFIG_COMMON_CLK_SI544 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_HWSPINLOCK is not set
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKEVT_I8253=y
+CONFIG_I8253_LOCK=y
+CONFIG_CLKBLD_I8253=y
+# end of Clock Source drivers
+
+CONFIG_MAILBOX=y
+CONFIG_PCC=y
+# CONFIG_ALTERA_MBOX is not set
+CONFIG_IOMMU_IOVA=y
+CONFIG_IOASID=y
+CONFIG_IOMMU_API=y
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Generic IOMMU Pagetable Support
+#
+# end of Generic IOMMU Pagetable Support
+
+# CONFIG_IOMMU_DEBUGFS is not set
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
+CONFIG_IOMMU_DMA=y
+CONFIG_AMD_IOMMU=y
+CONFIG_AMD_IOMMU_V2=y
+CONFIG_DMAR_TABLE=y
+CONFIG_INTEL_IOMMU=y
+# CONFIG_INTEL_IOMMU_SVM is not set
+# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU_FLOPPY_WA=y
+# CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON is not set
+CONFIG_IRQ_REMAP=y
+
+#
+# Remoteproc drivers
+#
+# CONFIG_REMOTEPROC is not set
+# end of Remoteproc drivers
+
+#
+# Rpmsg drivers
+#
+# CONFIG_RPMSG_QCOM_GLINK_RPM is not set
+# CONFIG_RPMSG_VIRTIO is not set
+# end of Rpmsg drivers
+
+# CONFIG_SOUNDWIRE is not set
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Amlogic SoC drivers
+#
+# end of Amlogic SoC drivers
+
+#
+# Aspeed SoC drivers
+#
+# end of Aspeed SoC drivers
+
+#
+# Broadcom SoC drivers
+#
+# end of Broadcom SoC drivers
+
+#
+# NXP/Freescale QorIQ SoC drivers
+#
+# end of NXP/Freescale QorIQ SoC drivers
+
+#
+# i.MX SoC drivers
+#
+# end of i.MX SoC drivers
+
+#
+# Qualcomm SoC drivers
+#
+# end of Qualcomm SoC drivers
+
+# CONFIG_SOC_TI is not set
+
+#
+# Xilinx SoC drivers
+#
+# CONFIG_XILINX_VCU is not set
+# end of Xilinx SoC drivers
+# end of SOC (System On Chip) specific Drivers
+
+# CONFIG_PM_DEVFREQ is not set
+CONFIG_EXTCON=y
+
+#
+# Extcon Device Drivers
+#
+# CONFIG_EXTCON_ADC_JACK is not set
+# CONFIG_EXTCON_FSA9480 is not set
+# CONFIG_EXTCON_GPIO is not set
+# CONFIG_EXTCON_INTEL_INT3496 is not set
+# CONFIG_EXTCON_MAX3355 is not set
+# CONFIG_EXTCON_PTN5150 is not set
+# CONFIG_EXTCON_RT8973A is not set
+# CONFIG_EXTCON_SM5502 is not set
+# CONFIG_EXTCON_USB_GPIO is not set
+CONFIG_MEMORY=y
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+# CONFIG_IIO_BUFFER_CB is not set
+# CONFIG_IIO_BUFFER_DMA is not set
+# CONFIG_IIO_BUFFER_DMAENGINE is not set
+# CONFIG_IIO_BUFFER_HW_CONSUMER is not set
+CONFIG_IIO_KFIFO_BUF=y
+CONFIG_IIO_TRIGGERED_BUFFER=y
+# CONFIG_IIO_CONFIGFS is not set
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+# CONFIG_IIO_SW_DEVICE is not set
+# CONFIG_IIO_SW_TRIGGER is not set
+# CONFIG_IIO_TRIGGERED_EVENT is not set
+
+#
+# Accelerometers
+#
+# CONFIG_ADIS16201 is not set
+# CONFIG_ADIS16209 is not set
+# CONFIG_ADXL345_I2C is not set
+# CONFIG_ADXL345_SPI is not set
+# CONFIG_ADXL372_SPI is not set
+# CONFIG_ADXL372_I2C is not set
+# CONFIG_BMA180 is not set
+# CONFIG_BMA220 is not set
+# CONFIG_BMA400 is not set
+# CONFIG_BMC150_ACCEL is not set
+# CONFIG_DA280 is not set
+# CONFIG_DA311 is not set
+# CONFIG_DMARD09 is not set
+# CONFIG_DMARD10 is not set
+# CONFIG_HID_SENSOR_ACCEL_3D is not set
+# CONFIG_IIO_ST_ACCEL_3AXIS is not set
+# CONFIG_KXSD9 is not set
+# CONFIG_KXCJK1013 is not set
+# CONFIG_MC3230 is not set
+# CONFIG_MMA7455_I2C is not set
+# CONFIG_MMA7455_SPI is not set
+# CONFIG_MMA7660 is not set
+# CONFIG_MMA8452 is not set
+# CONFIG_MMA9551 is not set
+# CONFIG_MMA9553 is not set
+# CONFIG_MXC4005 is not set
+# CONFIG_MXC6255 is not set
+# CONFIG_SCA3000 is not set
+# CONFIG_STK8312 is not set
+# CONFIG_STK8BA50 is not set
+# end of Accelerometers
+
+#
+# Analog to digital converters
+#
+# CONFIG_AD7091R5 is not set
+# CONFIG_AD7124 is not set
+# CONFIG_AD7192 is not set
+# CONFIG_AD7266 is not set
+# CONFIG_AD7291 is not set
+# CONFIG_AD7292 is not set
+# CONFIG_AD7298 is not set
+# CONFIG_AD7476 is not set
+# CONFIG_AD7606_IFACE_PARALLEL is not set
+# CONFIG_AD7606_IFACE_SPI is not set
+# CONFIG_AD7766 is not set
+# CONFIG_AD7768_1 is not set
+# CONFIG_AD7780 is not set
+# CONFIG_AD7791 is not set
+# CONFIG_AD7793 is not set
+# CONFIG_AD7887 is not set
+# CONFIG_AD7923 is not set
+# CONFIG_AD7949 is not set
+# CONFIG_AD799X is not set
+# CONFIG_AD9467 is not set
+# CONFIG_ADI_AXI_ADC is not set
+# CONFIG_CC10001_ADC is not set
+# CONFIG_HI8435 is not set
+# CONFIG_HX711 is not set
+# CONFIG_INA2XX_ADC is not set
+# CONFIG_LTC2471 is not set
+# CONFIG_LTC2485 is not set
+# CONFIG_LTC2496 is not set
+# CONFIG_LTC2497 is not set
+# CONFIG_MAX1027 is not set
+# CONFIG_MAX11100 is not set
+# CONFIG_MAX1118 is not set
+# CONFIG_MAX1241 is not set
+# CONFIG_MAX1363 is not set
+# CONFIG_MAX9611 is not set
+# CONFIG_MCP320X is not set
+# CONFIG_MCP3422 is not set
+# CONFIG_MCP3911 is not set
+# CONFIG_NAU7802 is not set
+# CONFIG_TI_ADC081C is not set
+# CONFIG_TI_ADC0832 is not set
+# CONFIG_TI_ADC084S021 is not set
+# CONFIG_TI_ADC12138 is not set
+# CONFIG_TI_ADC108S102 is not set
+# CONFIG_TI_ADC128S052 is not set
+# CONFIG_TI_ADC161S626 is not set
+# CONFIG_TI_ADS1015 is not set
+# CONFIG_TI_ADS7950 is not set
+# CONFIG_TI_TLC4541 is not set
+# CONFIG_XILINX_XADC is not set
+# end of Analog to digital converters
+
+#
+# Analog Front Ends
+#
+# end of Analog Front Ends
+
+#
+# Amplifiers
+#
+# CONFIG_AD8366 is not set
+# CONFIG_HMC425 is not set
+# end of Amplifiers
+
+#
+# Chemical Sensors
+#
+# CONFIG_ATLAS_PH_SENSOR is not set
+# CONFIG_ATLAS_EZO_SENSOR is not set
+# CONFIG_BME680 is not set
+# CONFIG_CCS811 is not set
+# CONFIG_IAQCORE is not set
+# CONFIG_SCD30_CORE is not set
+# CONFIG_SENSIRION_SGP30 is not set
+# CONFIG_SPS30 is not set
+# CONFIG_VZ89X is not set
+# end of Chemical Sensors
+
+#
+# Hid Sensor IIO Common
+#
+CONFIG_HID_SENSOR_IIO_COMMON=y
+CONFIG_HID_SENSOR_IIO_TRIGGER=y
+# end of Hid Sensor IIO Common
+
+#
+# SSP Sensor Common
+#
+# CONFIG_IIO_SSP_SENSORHUB is not set
+# end of SSP Sensor Common
+
+#
+# Digital to analog converters
+#
+# CONFIG_AD5064 is not set
+# CONFIG_AD5360 is not set
+# CONFIG_AD5380 is not set
+# CONFIG_AD5421 is not set
+# CONFIG_AD5446 is not set
+# CONFIG_AD5449 is not set
+# CONFIG_AD5592R is not set
+# CONFIG_AD5593R is not set
+# CONFIG_AD5504 is not set
+# CONFIG_AD5624R_SPI is not set
+# CONFIG_AD5686_SPI is not set
+# CONFIG_AD5696_I2C is not set
+# CONFIG_AD5755 is not set
+# CONFIG_AD5758 is not set
+# CONFIG_AD5761 is not set
+# CONFIG_AD5764 is not set
+# CONFIG_AD5770R is not set
+# CONFIG_AD5791 is not set
+# CONFIG_AD7303 is not set
+# CONFIG_AD8801 is not set
+# CONFIG_DS4424 is not set
+# CONFIG_LTC1660 is not set
+# CONFIG_LTC2632 is not set
+# CONFIG_M62332 is not set
+# CONFIG_MAX517 is not set
+# CONFIG_MCP4725 is not set
+# CONFIG_MCP4922 is not set
+# CONFIG_TI_DAC082S085 is not set
+# CONFIG_TI_DAC5571 is not set
+# CONFIG_TI_DAC7311 is not set
+# CONFIG_TI_DAC7612 is not set
+# end of Digital to analog converters
+
+#
+# IIO dummy driver
+#
+# end of IIO dummy driver
+
+#
+# Frequency Synthesizers DDS/PLL
+#
+
+#
+# Clock Generator/Distribution
+#
+# CONFIG_AD9523 is not set
+# end of Clock Generator/Distribution
+
+#
+# Phase-Locked Loop (PLL) frequency synthesizers
+#
+# CONFIG_ADF4350 is not set
+# CONFIG_ADF4371 is not set
+# end of Phase-Locked Loop (PLL) frequency synthesizers
+# end of Frequency Synthesizers DDS/PLL
+
+#
+# Digital gyroscope sensors
+#
+# CONFIG_ADIS16080 is not set
+# CONFIG_ADIS16130 is not set
+# CONFIG_ADIS16136 is not set
+# CONFIG_ADIS16260 is not set
+# CONFIG_ADXRS290 is not set
+# CONFIG_ADXRS450 is not set
+# CONFIG_BMG160 is not set
+# CONFIG_FXAS21002C is not set
+# CONFIG_HID_SENSOR_GYRO_3D is not set
+# CONFIG_MPU3050_I2C is not set
+# CONFIG_IIO_ST_GYRO_3AXIS is not set
+# CONFIG_ITG3200 is not set
+# end of Digital gyroscope sensors
+
+#
+# Health Sensors
+#
+
+#
+# Heart Rate Monitors
+#
+# CONFIG_AFE4403 is not set
+# CONFIG_AFE4404 is not set
+# CONFIG_MAX30100 is not set
+# CONFIG_MAX30102 is not set
+# end of Heart Rate Monitors
+# end of Health Sensors
+
+#
+# Humidity sensors
+#
+# CONFIG_AM2315 is not set
+# CONFIG_DHT11 is not set
+# CONFIG_HDC100X is not set
+# CONFIG_HDC2010 is not set
+# CONFIG_HID_SENSOR_HUMIDITY is not set
+# CONFIG_HTS221 is not set
+# CONFIG_HTU21 is not set
+# CONFIG_SI7005 is not set
+# CONFIG_SI7020 is not set
+# end of Humidity sensors
+
+#
+# Inertial measurement units
+#
+# CONFIG_ADIS16400 is not set
+# CONFIG_ADIS16460 is not set
+# CONFIG_ADIS16475 is not set
+# CONFIG_ADIS16480 is not set
+# CONFIG_BMI160_I2C is not set
+# CONFIG_BMI160_SPI is not set
+# CONFIG_FXOS8700_I2C is not set
+# CONFIG_FXOS8700_SPI is not set
+# CONFIG_KMX61 is not set
+# CONFIG_INV_ICM42600_I2C is not set
+# CONFIG_INV_ICM42600_SPI is not set
+# CONFIG_INV_MPU6050_I2C is not set
+# CONFIG_INV_MPU6050_SPI is not set
+# CONFIG_IIO_ST_LSM6DSX is not set
+# end of Inertial measurement units
+
+#
+# Light sensors
+#
+# CONFIG_ACPI_ALS is not set
+# CONFIG_ADJD_S311 is not set
+# CONFIG_ADUX1020 is not set
+# CONFIG_AL3010 is not set
+# CONFIG_AL3320A is not set
+# CONFIG_APDS9300 is not set
+# CONFIG_APDS9960 is not set
+# CONFIG_AS73211 is not set
+# CONFIG_BH1750 is not set
+# CONFIG_BH1780 is not set
+# CONFIG_CM32181 is not set
+# CONFIG_CM3232 is not set
+# CONFIG_CM3323 is not set
+# CONFIG_CM36651 is not set
+# CONFIG_GP2AP002 is not set
+# CONFIG_GP2AP020A00F is not set
+# CONFIG_SENSORS_ISL29018 is not set
+# CONFIG_SENSORS_ISL29028 is not set
+# CONFIG_ISL29125 is not set
+# CONFIG_HID_SENSOR_ALS is not set
+# CONFIG_HID_SENSOR_PROX is not set
+# CONFIG_JSA1212 is not set
+# CONFIG_RPR0521 is not set
+# CONFIG_LTR501 is not set
+# CONFIG_LV0104CS is not set
+# CONFIG_MAX44000 is not set
+# CONFIG_MAX44009 is not set
+# CONFIG_NOA1305 is not set
+# CONFIG_OPT3001 is not set
+# CONFIG_PA12203001 is not set
+# CONFIG_SI1133 is not set
+# CONFIG_SI1145 is not set
+# CONFIG_STK3310 is not set
+# CONFIG_ST_UVIS25 is not set
+# CONFIG_TCS3414 is not set
+# CONFIG_TCS3472 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_TSL2583 is not set
+# CONFIG_TSL2772 is not set
+# CONFIG_TSL4531 is not set
+# CONFIG_US5182D is not set
+# CONFIG_VCNL4000 is not set
+# CONFIG_VCNL4035 is not set
+# CONFIG_VEML6030 is not set
+# CONFIG_VEML6070 is not set
+# CONFIG_VL6180 is not set
+# CONFIG_ZOPT2201 is not set
+# end of Light sensors
+
+#
+# Magnetometer sensors
+#
+# CONFIG_AK8975 is not set
+# CONFIG_AK09911 is not set
+# CONFIG_BMC150_MAGN_I2C is not set
+# CONFIG_BMC150_MAGN_SPI is not set
+# CONFIG_MAG3110 is not set
+# CONFIG_HID_SENSOR_MAGNETOMETER_3D is not set
+# CONFIG_MMC35240 is not set
+# CONFIG_IIO_ST_MAGN_3AXIS is not set
+# CONFIG_SENSORS_HMC5843_I2C is not set
+# CONFIG_SENSORS_HMC5843_SPI is not set
+# CONFIG_SENSORS_RM3100_I2C is not set
+# CONFIG_SENSORS_RM3100_SPI is not set
+# end of Magnetometer sensors
+
+#
+# Multiplexers
+#
+# end of Multiplexers
+
+#
+# Inclinometer sensors
+#
+# CONFIG_HID_SENSOR_INCLINOMETER_3D is not set
+# CONFIG_HID_SENSOR_DEVICE_ROTATION is not set
+# end of Inclinometer sensors
+
+#
+# Triggers - standalone
+#
+# CONFIG_IIO_INTERRUPT_TRIGGER is not set
+# CONFIG_IIO_SYSFS_TRIGGER is not set
+# end of Triggers - standalone
+
+#
+# Linear and angular position sensors
+#
+# end of Linear and angular position sensors
+
+#
+# Digital potentiometers
+#
+# CONFIG_AD5272 is not set
+# CONFIG_DS1803 is not set
+# CONFIG_MAX5432 is not set
+# CONFIG_MAX5481 is not set
+# CONFIG_MAX5487 is not set
+# CONFIG_MCP4018 is not set
+# CONFIG_MCP4131 is not set
+# CONFIG_MCP4531 is not set
+# CONFIG_MCP41010 is not set
+# CONFIG_TPL0102 is not set
+# end of Digital potentiometers
+
+#
+# Digital potentiostats
+#
+# CONFIG_LMP91000 is not set
+# end of Digital potentiostats
+
+#
+# Pressure sensors
+#
+# CONFIG_ABP060MG is not set
+# CONFIG_BMP280 is not set
+# CONFIG_DLHL60D is not set
+# CONFIG_DPS310 is not set
+# CONFIG_HID_SENSOR_PRESS is not set
+# CONFIG_HP03 is not set
+# CONFIG_ICP10100 is not set
+# CONFIG_MPL115_I2C is not set
+# CONFIG_MPL115_SPI is not set
+# CONFIG_MPL3115 is not set
+# CONFIG_MS5611 is not set
+# CONFIG_MS5637 is not set
+# CONFIG_IIO_ST_PRESS is not set
+# CONFIG_T5403 is not set
+# CONFIG_HP206C is not set
+# CONFIG_ZPA2326 is not set
+# end of Pressure sensors
+
+#
+# Lightning sensors
+#
+# CONFIG_AS3935 is not set
+# end of Lightning sensors
+
+#
+# Proximity and distance sensors
+#
+# CONFIG_ISL29501 is not set
+# CONFIG_LIDAR_LITE_V2 is not set
+# CONFIG_MB1232 is not set
+# CONFIG_PING is not set
+# CONFIG_RFD77402 is not set
+# CONFIG_SRF04 is not set
+# CONFIG_SX9310 is not set
+# CONFIG_SX9500 is not set
+# CONFIG_SRF08 is not set
+# CONFIG_VCNL3020 is not set
+# CONFIG_VL53L0X_I2C is not set
+# end of Proximity and distance sensors
+
+#
+# Resolver to digital converters
+#
+# CONFIG_AD2S90 is not set
+# CONFIG_AD2S1200 is not set
+# end of Resolver to digital converters
+
+#
+# Temperature sensors
+#
+# CONFIG_LTC2983 is not set
+# CONFIG_MAXIM_THERMOCOUPLE is not set
+# CONFIG_HID_SENSOR_TEMP is not set
+# CONFIG_MLX90614 is not set
+# CONFIG_MLX90632 is not set
+# CONFIG_TMP006 is not set
+# CONFIG_TMP007 is not set
+# CONFIG_TSYS01 is not set
+# CONFIG_TSYS02D is not set
+# CONFIG_MAX31856 is not set
+# end of Temperature sensors
+
+# CONFIG_NTB is not set
+# CONFIG_VME_BUS is not set
+CONFIG_PWM=y
+CONFIG_PWM_SYSFS=y
+# CONFIG_PWM_DEBUG is not set
+# CONFIG_PWM_LPSS_PCI is not set
+# CONFIG_PWM_LPSS_PLATFORM is not set
+# CONFIG_PWM_PCA9685 is not set
+
+#
+# IRQ chip support
+#
+# end of IRQ chip support
+
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_BRCMSTB_RESCAL is not set
+# CONFIG_RESET_TI_SYSCON is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_USB_LGM_PHY is not set
+CONFIG_BCM_KONA_USB2_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_PHY_CPCAP_USB is not set
+# CONFIG_PHY_INTEL_LGM_EMMC is not set
+# end of PHY Subsystem
+
+CONFIG_POWERCAP=y
+CONFIG_INTEL_RAPL_CORE=y
+CONFIG_INTEL_RAPL=y
+# CONFIG_IDLE_INJECT is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# end of Performance monitor support
+
+CONFIG_RAS=y
+# CONFIG_RAS_CEC is not set
+# CONFIG_USB4 is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# end of Android
+
+# CONFIG_LIBNVDIMM is not set
+CONFIG_DAX=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SYSFS=y
+
+#
+# HW tracing support
+#
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+# end of HW tracing support
+
+# CONFIG_FPGA is not set
+# CONFIG_TEE is not set
+# CONFIG_UNISYS_VISORBUS is not set
+# CONFIG_SIOX is not set
+# CONFIG_SLIMBUS is not set
+# CONFIG_INTERCONNECT is not set
+# CONFIG_COUNTER is not set
+# CONFIG_MOST is not set
+# end of Device Drivers
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_VALIDATE_FS_PARSER is not set
+CONFIG_FS_IOMAP=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_DAX is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+CONFIG_FS_ENCRYPTION=y
+CONFIG_FS_ENCRYPTION_ALGS=y
+# CONFIG_FS_VERITY is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+# CONFIG_VIRTIO_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+# end of Caches
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+# end of CD-ROM/DVD Filesystems
+
+#
+# DOS/FAT/EXFAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_EXFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+# end of DOS/FAT/EXFAT/NT Filesystems
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_CHILDREN=y
+CONFIG_PROC_PID_ARCH_STATUS=y
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_TMPFS_INODE64 is not set
+# CONFIG_HUGETLBFS is not set
+CONFIG_MEMFD_CREATE=y
+CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
+CONFIG_CONFIGFS_FS=y
+# end of Pseudo filesystems
+
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_FILE_CACHE is not set
+CONFIG_SQUASHFS_FILE_DIRECT=y
+# CONFIG_SQUASHFS_DECOMP_SINGLE is not set
+# CONFIG_SQUASHFS_DECOMP_MULTI is not set
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_ZLIB=y
+# CONFIG_SQUASHFS_LZ4 is not set
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_ZSTD is not set
+# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_PSTORE=y
+CONFIG_PSTORE_DEFLATE_COMPRESS=y
+# CONFIG_PSTORE_LZO_COMPRESS is not set
+# CONFIG_PSTORE_LZ4_COMPRESS is not set
+# CONFIG_PSTORE_LZ4HC_COMPRESS is not set
+# CONFIG_PSTORE_842_COMPRESS is not set
+# CONFIG_PSTORE_ZSTD_COMPRESS is not set
+CONFIG_PSTORE_COMPRESS=y
+CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y
+CONFIG_PSTORE_COMPRESS_DEFAULT="deflate"
+# CONFIG_PSTORE_CONSOLE is not set
+# CONFIG_PSTORE_PMSG is not set
+# CONFIG_PSTORE_FTRACE is not set
+CONFIG_PSTORE_RAM=y
+# CONFIG_PSTORE_BLK is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_EROFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+# CONFIG_UNICODE is not set
+CONFIG_IO_WQ=y
+# end of File systems
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_REQUEST_CACHE is not set
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_TRUSTED_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+CONFIG_SECURITYFS=y
+CONFIG_PAGE_TABLE_ISOLATION=y
+# CONFIG_INTEL_TXT is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+# CONFIG_HARDENED_USERCOPY is not set
+# CONFIG_FORTIFY_SOURCE is not set
+# CONFIG_STATIC_USERMODEHELPER is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity,bpf"
+
+#
+# Kernel hardening options
+#
+
+#
+# Memory initialization
+#
+CONFIG_INIT_STACK_NONE=y
+# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
+# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
+# end of Memory initialization
+# end of Kernel hardening options
+# end of Security options
+
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SKCIPHER=y
+CONFIG_CRYPTO_SKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_AKCIPHER=y
+CONFIG_CRYPTO_KPP2=y
+CONFIG_CRYPTO_KPP=y
+CONFIG_CRYPTO_ACOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_PCRYPT=y
+CONFIG_CRYPTO_CRYPTD=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_SIMD=y
+CONFIG_CRYPTO_GLUE_HELPER_X86=y
+
+#
+# Public-key cryptography
+#
+CONFIG_CRYPTO_RSA=y
+CONFIG_CRYPTO_DH=y
+# CONFIG_CRYPTO_ECDH is not set
+# CONFIG_CRYPTO_ECRDSA is not set
+# CONFIG_CRYPTO_SM2 is not set
+# CONFIG_CRYPTO_CURVE25519 is not set
+# CONFIG_CRYPTO_CURVE25519_X86 is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_AEGIS128 is not set
+# CONFIG_CRYPTO_AEGIS128_AESNI_SSE2 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=y
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CFB is not set
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_CTS=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+# CONFIG_CRYPTO_OFB is not set
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_XTS=y
+# CONFIG_CRYPTO_KEYWRAP is not set
+# CONFIG_CRYPTO_NHPOLY1305_SSE2 is not set
+# CONFIG_CRYPTO_NHPOLY1305_AVX2 is not set
+# CONFIG_CRYPTO_ADIANTUM is not set
+CONFIG_CRYPTO_ESSIV=y
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_VMAC=y
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CRC32C_INTEL=y
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32_PCLMUL=y
+# CONFIG_CRYPTO_XXHASH is not set
+# CONFIG_CRYPTO_BLAKE2B is not set
+# CONFIG_CRYPTO_BLAKE2S is not set
+# CONFIG_CRYPTO_BLAKE2S_X86 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_CRCT10DIF_PCLMUL=y
+CONFIG_CRYPTO_GHASH=y
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_POLY1305_X86_64 is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=y
+CONFIG_CRYPTO_RMD160=y
+CONFIG_CRYPTO_RMD256=y
+CONFIG_CRYPTO_RMD320=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_SSSE3=y
+CONFIG_CRYPTO_SHA256_SSSE3=y
+CONFIG_CRYPTO_SHA512_SSSE3=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_SM3 is not set
+# CONFIG_CRYPTO_STREEBOG is not set
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=y
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_AES_TI is not set
+CONFIG_CRYPTO_AES_NI_INTEL=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_BLOWFISH_COMMON=y
+CONFIG_CRYPTO_BLOWFISH_X86_64=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_CAMELLIA_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=y
+CONFIG_CRYPTO_CAST_COMMON=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST5_AVX_X86_64=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_CAST6_AVX_X86_64=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_DES3_EDE_X86_64=y
+CONFIG_CRYPTO_FCRYPT=y
+CONFIG_CRYPTO_SALSA20=y
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_CHACHA20_X86_64 is not set
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_SERPENT_SSE2_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX2_X86_64=y
+# CONFIG_CRYPTO_SM4 is not set
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+CONFIG_CRYPTO_TWOFISH_X86_64=y
+CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=y
+CONFIG_CRYPTO_TWOFISH_AVX_X86_64=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+CONFIG_CRYPTO_LZ4=y
+CONFIG_CRYPTO_LZ4HC=y
+# CONFIG_CRYPTO_ZSTD is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_HASH=y
+CONFIG_CRYPTO_DRBG_CTR=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HASH_INFO=y
+
+#
+# Crypto library routines
+#
+CONFIG_CRYPTO_LIB_AES=y
+CONFIG_CRYPTO_LIB_ARC4=y
+# CONFIG_CRYPTO_LIB_BLAKE2S is not set
+# CONFIG_CRYPTO_LIB_CHACHA is not set
+# CONFIG_CRYPTO_LIB_CURVE25519 is not set
+CONFIG_CRYPTO_LIB_DES=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11
+# CONFIG_CRYPTO_LIB_POLY1305 is not set
+# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_LIB_SHA256=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=y
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=y
+# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set
+# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set
+CONFIG_CRYPTO_DEV_CCP=y
+CONFIG_CRYPTO_DEV_CCP_DD=y
+CONFIG_CRYPTO_DEV_SP_CCP=y
+CONFIG_CRYPTO_DEV_CCP_CRYPTO=y
+CONFIG_CRYPTO_DEV_SP_PSP=y
+# CONFIG_CRYPTO_DEV_CCP_DEBUGFS is not set
+CONFIG_CRYPTO_DEV_QAT=y
+CONFIG_CRYPTO_DEV_QAT_DH895xCC=y
+# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set
+# CONFIG_CRYPTO_DEV_QAT_C62X is not set
+# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set
+# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set
+# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set
+# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set
+# CONFIG_CRYPTO_DEV_SAFEXCEL is not set
+# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set
+CONFIG_ASYMMETRIC_KEY_TYPE=y
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_X509_CERTIFICATE_PARSER=y
+# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set
+CONFIG_PKCS7_MESSAGE_PARSER=y
+# CONFIG_PKCS7_TEST_KEY is not set
+# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set
+
+#
+# Certificates for signature checking
+#
+CONFIG_SYSTEM_TRUSTED_KEYRING=y
+CONFIG_SYSTEM_TRUSTED_KEYS=""
+# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
+# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
+# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
+# end of Certificates for signature checking
+
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_LINEAR_RANGES=y
+# CONFIG_PACKING is not set
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_CORDIC=y
+# CONFIG_PRIME_NUMBERS is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
+CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC64=y
+# CONFIG_CRC4 is not set
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_CRC8=y
+CONFIG_XXHASH=y
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4HC_COMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_XZ_DEC_TEST=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_INTERVAL_TREE=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DMA_OPS=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_SWIOTLB=y
+# CONFIG_DMA_CMA is not set
+# CONFIG_DMA_API_DEBUG is not set
+CONFIG_SGL_ALLOC=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_GLOB=y
+# CONFIG_GLOB_SELFTEST is not set
+CONFIG_NLATTR=y
+CONFIG_CLZ_TAB=y
+# CONFIG_IRQ_POLL is not set
+CONFIG_MPILIB=y
+CONFIG_OID_REGISTRY=y
+CONFIG_HAVE_GENERIC_VDSO=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_VDSO_TIME_NS=y
+CONFIG_FONT_SUPPORT=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_PMEM_API=y
+CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
+CONFIG_ARCH_HAS_COPY_MC=y
+CONFIG_ARCH_STACKWALK=y
+CONFIG_SBITMAP=y
+# CONFIG_STRING_SELFTEST is not set
+# end of Library routines
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+# CONFIG_PRINTK_CALLER is not set
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
+CONFIG_CONSOLE_LOGLEVEL_QUIET=4
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DYNAMIC_DEBUG_CORE=y
+CONFIG_SYMBOLIC_ERRNAME=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# end of printk and dmesg options
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_HEADERS_INSTALL is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_32B is not set
+CONFIG_STACK_VALIDATION=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# end of Compile-time checks and compiler options
+
+#
+# Generic Kernel Debugging Instruments
+#
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+CONFIG_MAGIC_SYSRQ_SERIAL=y
+CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_FS_ALLOW_ALL=y
+# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set
+# CONFIG_DEBUG_FS_ALLOW_NONE is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_KGDB=y
+CONFIG_KGDB_SERIAL_CONSOLE=y
+# CONFIG_KGDB_TESTS is not set
+CONFIG_KGDB_LOW_LEVEL_TRAP=y
+CONFIG_KGDB_KDB=y
+CONFIG_KDB_DEFAULT_ENABLE=0x1
+CONFIG_KDB_KEYBOARD=y
+CONFIG_KDB_CONTINUE_CATASTROPHIC=0
+CONFIG_ARCH_HAS_EARLY_DEBUG=y
+CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
+# CONFIG_UBSAN is not set
+CONFIG_HAVE_ARCH_KCSAN=y
+# end of Generic Kernel Debugging Instruments
+
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_MISC=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_PAGE_REF is not set
+# CONFIG_DEBUG_RODATA_TEST is not set
+CONFIG_ARCH_HAS_DEBUG_WX=y
+# CONFIG_DEBUG_WX is not set
+CONFIG_GENERIC_PTDUMP=y
+# CONFIG_PTDUMP_DEBUGFS is not set
+CONFIG_DEBUG_OBJECTS=y
+# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
+# CONFIG_DEBUG_OBJECTS_FREE is not set
+# CONFIG_DEBUG_OBJECTS_TIMERS is not set
+# CONFIG_DEBUG_OBJECTS_WORK is not set
+# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set
+# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set
+CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VM_PGTABLE is not set
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+CONFIG_HAVE_ARCH_KASAN=y
+CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
+CONFIG_CC_HAS_KASAN_GENERIC=y
+CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
+# CONFIG_KASAN is not set
+# end of Memory Debugging
+
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Oops, Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y
+CONFIG_HARDLOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_WQ_WATCHDOG is not set
+# end of Debug Oops, Lockups and Hangs
+
+#
+# Scheduler Debugging
+#
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHED_INFO=y
+CONFIG_SCHEDSTATS=y
+# end of Scheduler Debugging
+
+# CONFIG_DEBUG_TIMEKEEPING is not set
+CONFIG_DEBUG_PREEMPT=y
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_WW_MUTEX_SELFTEST is not set
+# CONFIG_SCF_TORTURE_TEST is not set
+# CONFIG_CSD_LOCK_WAIT_DEBUG is not set
+# end of Lock Debugging (spinlocks, mutexes, etc...)
+
+CONFIG_STACKTRACE=y
+# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
+# CONFIG_DEBUG_KOBJECT is not set
+
+#
+# Debug kernel data structures
+#
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PLIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BUG_ON_DATA_CORRUPTION is not set
+# end of Debug kernel data structures
+
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_RCU_SCALE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_REF_SCALE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# end of RCU Debugging
+
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_FENTRY=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_BOOTTIME_TRACING is not set
+CONFIG_FUNCTION_TRACER=y
+CONFIG_FUNCTION_GRAPH_TRACER=y
+CONFIG_DYNAMIC_FTRACE=y
+CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+CONFIG_SCHED_TRACER=y
+# CONFIG_HWLAT_TRACER is not set
+CONFIG_MMIOTRACE=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_TRACER_SNAPSHOT=y
+# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_UPROBE_EVENTS=y
+CONFIG_BPF_EVENTS=y
+CONFIG_DYNAMIC_EVENTS=y
+CONFIG_PROBE_EVENTS=y
+CONFIG_FTRACE_MCOUNT_RECORD=y
+# CONFIG_SYNTH_EVENTS is not set
+# CONFIG_HIST_TRIGGERS is not set
+# CONFIG_TRACE_EVENT_INJECT is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_TRACE_EVAL_MAP_FILE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_STARTUP_TEST is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_SAMPLES is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+
+#
+# x86 Debugging
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
+CONFIG_EARLY_PRINTK_USB=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_EARLY_PRINTK_DBGP=y
+# CONFIG_EARLY_PRINTK_USB_XDBC is not set
+# CONFIG_DEBUG_TLBFLUSH is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+# CONFIG_X86_DECODER_SELFTEST is not set
+# CONFIG_IO_DELAY_0X80 is not set
+CONFIG_IO_DELAY_0XED=y
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+# CONFIG_DEBUG_BOOT_PARAMS is not set
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_DEBUG_ENTRY is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+CONFIG_X86_DEBUG_FPU=y
+# CONFIG_PUNIT_ATOM_DEBUG is not set
+CONFIG_UNWINDER_ORC=y
+# CONFIG_UNWINDER_FRAME_POINTER is not set
+# CONFIG_UNWINDER_GUESS is not set
+# end of x86 Debugging
+
+#
+# Kernel Testing and Coverage
+#
+# CONFIG_KUNIT is not set
+CONFIG_NOTIFIER_ERROR_INJECTION=y
+CONFIG_PM_NOTIFIER_ERROR_INJECT=y
+# CONFIG_NETDEV_NOTIFIER_ERROR_INJECT is not set
+CONFIG_FAULT_INJECTION=y
+# CONFIG_FAILSLAB is not set
+# CONFIG_FAIL_PAGE_ALLOC is not set
+# CONFIG_FAULT_INJECTION_USERCOPY is not set
+# CONFIG_FAIL_MAKE_REQUEST is not set
+# CONFIG_FAIL_IO_TIMEOUT is not set
+# CONFIG_FAIL_FUTEX is not set
+# CONFIG_FAULT_INJECTION_DEBUG_FS is not set
+CONFIG_ARCH_HAS_KCOV=y
+CONFIG_CC_HAS_SANCOV_TRACE_PC=y
+# CONFIG_KCOV is not set
+CONFIG_RUNTIME_TESTING_MENU=y
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_TEST_MIN_HEAP is not set
+# CONFIG_TEST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_REED_SOLOMON_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_STRSCPY is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_XARRAY is not set
+# CONFIG_TEST_OVERFLOW is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_TEST_IDA is not set
+# CONFIG_FIND_BIT_BENCHMARK is not set
+CONFIG_TEST_FIRMWARE=y
+# CONFIG_TEST_SYSCTL is not set
+CONFIG_TEST_UDELAY=y
+# CONFIG_TEST_MEMCAT_P is not set
+# CONFIG_TEST_STACKINIT is not set
+# CONFIG_TEST_MEMINIT is not set
+# CONFIG_TEST_FREE_PAGES is not set
+# CONFIG_TEST_FPU is not set
+CONFIG_MEMTEST=y
+# end of Kernel Testing and Coverage
+# end of Kernel hacking
diff --git a/nichrome/Gopkg.lock b/nichrome/Gopkg.lock
new file mode 100644
index 000000000..b4645f5d2
--- /dev/null
+++ b/nichrome/Gopkg.lock
@@ -0,0 +1,196 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ branch = "2.x"
+ digest = "1:f198c9213547e59cb10260bf9c3c1bf6e760298ef5268e1f980d950e0d317880"
+ name = "github.com/Masterminds/semver"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "3c92f33da7a84de8314f3ff82e5f919b89fd1492"
+
+[[projects]]
+ digest = "1:5e4de188bac29c98e6d747ff06911d6ce515646c318f7d65f45ffe96c59dc0aa"
+ name = "github.com/Masterminds/vcs"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "f94282d8632a0620f79f0c6ff0e82604e8c5c85b"
+ version = "v1.13.1"
+
+[[projects]]
+ digest = "1:e5ca3dcabf1452b51be600af6e2ce0a93a94978ae231af802cf9736bdbd835cb"
+ name = "github.com/armon/go-radix"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "1a2de0c21c94309923825da3df33a4381872c795"
+ version = "v1.0.0"
+
+[[projects]]
+ digest = "1:a12d94258c5298ead75e142e8001224bf029f302fed9e96cd39c0eaf90f3954d"
+ name = "github.com/boltdb/bolt"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8"
+ version = "v1.3.1"
+
+[[projects]]
+ digest = "1:b7ffca49e9cfd3dfb04a8e0a59347708c6f78f68476a32c5e0a0edca5d1b258c"
+ name = "github.com/dustin/go-humanize"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "9f541cc9db5d55bce703bd99987c9d5cb8eea45e"
+ version = "v1.0.0"
+
+[[projects]]
+ digest = "1:ed1c52061aeabab2761bf8a1597f812a3161e04a6a2ea96bd2c5ae8f9096aee1"
+ name = "github.com/golang/dep"
+ packages = [
+ ".",
+ "cmd/dep",
+ "gps",
+ "gps/internal/pb",
+ "gps/paths",
+ "gps/pkgtree",
+ "gps/verify",
+ "internal/feedback",
+ "internal/fs",
+ "internal/importers",
+ "internal/importers/base",
+ "internal/importers/glide",
+ "internal/importers/glock",
+ "internal/importers/godep",
+ "internal/importers/govend",
+ "internal/importers/govendor",
+ "internal/importers/gvt",
+ "internal/importers/vndr",
+ ]
+ pruneopts = "NT"
+ revision = "1f7c19e5f52f49ffb9f956f64c010be14683468b"
+ version = "v0.5.4"
+
+[[projects]]
+ digest = "1:573ca21d3669500ff845bdebee890eb7fc7f0f50c59f2132f2a0c6b03d85086a"
+ name = "github.com/golang/protobuf"
+ packages = ["proto"]
+ pruneopts = "NUT"
+ revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7"
+ version = "v1.3.2"
+
+[[projects]]
+ digest = "1:3c8c26bb118e3f02230d4f5f30b972dbfe0c6b371acea8f190aa99ceaaae7028"
+ name = "github.com/gorilla/mux"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "00bdffe0f3c77e27d2cf6f5c70232a2d3e4d9c15"
+ version = "v1.7.3"
+
+[[projects]]
+ digest = "1:f5169729244becc423886eae4d72547e28ac3f13f861bed8a9d749bc7238a1c3"
+ name = "github.com/jmank88/nuts"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "8b28145dffc87104e66d074f62ea8080edfad7c8"
+ version = "v0.3.0"
+
+[[projects]]
+ branch = "master"
+ digest = "1:26217ee135b8157549e648efe97dff3282e4bd597a912d784db964df41067f29"
+ name = "github.com/nightlyone/lockfile"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "0ad87eef1443f64d3d8c50da647e2b1552851124"
+
+[[projects]]
+ digest = "1:4e9827f31d4fc1ddd732a0e3af4e863d281dd405adb2bfb96a25cc5346a77caf"
+ name = "github.com/pelletier/go-toml"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "728039f679cbcd4f6a54e080d2219a4c4928c546"
+ version = "v1.4.0"
+
+[[projects]]
+ digest = "1:14715f705ff5dfe0ffd6571d7d201dd8e921030f8070321a79380d8ca4ec1a24"
+ name = "github.com/pkg/errors"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
+ version = "v0.8.1"
+
+[[projects]]
+ branch = "master"
+ digest = "1:abb4b60c28323cde32c193ce6083bb600fac462d1780cf83461b4c23ed5ce904"
+ name = "github.com/sdboyer/constext"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "836a144573533ea4da4e6929c235fd348aed1c80"
+
+[[projects]]
+ digest = "1:9d8420bbf131d1618bde6530af37c3799340d3762cc47210c1d9532a4c3a2779"
+ name = "github.com/spf13/pflag"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
+ version = "v1.0.3"
+
+[[projects]]
+ digest = "1:1399e838d21e76f3b54883253f4c586f6b7bbde6b731b586e3ad879390b5b6cf"
+ name = "github.com/u-root/u-root"
+ packages = [
+ "pkg/cmdline",
+ "pkg/cpio",
+ "pkg/gpt",
+ "pkg/ls",
+ "pkg/ubinary",
+ "pkg/uio",
+ "pkg/uroot/util",
+ ]
+ pruneopts = "NUT"
+ revision = "26a90287872f42e357dc889f6918855fc0fde4dc"
+ version = "v6.0.0"
+
+[[projects]]
+ branch = "master"
+ digest = "1:f92f6956e4059f6a3efc14924d2dd58ba90da25cc57fe07ae3779ef2f5e0c5f2"
+ name = "golang.org/x/crypto"
+ packages = ["pbkdf2"]
+ pruneopts = "NUT"
+ revision = "4def268fd1a49955bfb3dda92fe3db4f924f2285"
+
+[[projects]]
+ branch = "master"
+ digest = "1:b521f10a2d8fa85c04a8ef4e62f2d1e14d303599a55d64dabf9f5a02f84d35eb"
+ name = "golang.org/x/sync"
+ packages = ["errgroup"]
+ pruneopts = "NUT"
+ revision = "112230192c580c3556b8cee6403af37a4fc5f28c"
+
+[[projects]]
+ branch = "master"
+ digest = "1:4296892af119aaeedd6437125dbe67686a9e3043a6e54956fb8425a61d93d764"
+ name = "golang.org/x/sys"
+ packages = ["unix"]
+ pruneopts = "NUT"
+ revision = "fde4db37ae7ad8191b03d30d27f258b5291ae4e3"
+
+[[projects]]
+ digest = "1:18108594151654e9e696b27b181b953f9a90b16bf14d253dd1b397b025a1487f"
+ name = "gopkg.in/yaml.v2"
+ packages = ["."]
+ pruneopts = "NUT"
+ revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
+ version = "v2.2.2"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ input-imports = [
+ "github.com/golang/dep/cmd/dep",
+ "github.com/gorilla/mux",
+ "github.com/spf13/pflag",
+ "github.com/u-root/u-root/pkg/cpio",
+ "github.com/u-root/u-root/pkg/gpt",
+ "github.com/u-root/u-root/pkg/uroot/util",
+ "golang.org/x/crypto/pbkdf2",
+ ]
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/nichrome/Gopkg.toml b/nichrome/Gopkg.toml
new file mode 100644
index 000000000..ccd1fd607
--- /dev/null
+++ b/nichrome/Gopkg.toml
@@ -0,0 +1,16 @@
+required = [
+ "github.com/golang/dep/cmd/dep"
+]
+
+[[constraint]]
+ version = "6.0.0"
+ name = "github.com/u-root/u-root"
+
+[prune]
+ non-go = true
+ go-tests = true
+ unused-packages = true
+
+ [[prune.project]]
+ name = "github.com/golang/dep"
+ unused-packages = false
diff --git a/nichrome/LICENSE b/nichrome/LICENSE
new file mode 100644
index 000000000..23cb79033
--- /dev/null
+++ b/nichrome/LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ {description}
+ Copyright (C) {year} {fullname}
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ {signature of Ty Coon}, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/nichrome/QRUN b/nichrome/QRUN
new file mode 100644
index 000000000..7e854ba11
--- /dev/null
+++ b/nichrome/QRUN
@@ -0,0 +1,21 @@
+# The file /tmp/t3 was produced as follows:
+# go run usb/*.go -dev=/tmp/t
+# /tmp/t2 and /tmp/t3 are created and you can use /tmp/t3
+# as hda as shown below.
+# -s is gdb
+# -monitor allows you to hit ^C in the term window you start
+# this from to kill QEMU
+qemu-system-x86_64 \
+-m 2048M \
+-cpu max \
+-machine pc-q35-zesty \
+-kernel linux-stable/arch/x86/boot/bzImage \
+-s \
+-monitor /dev/null \
+-serial stdio \
+-vga cirrus \
+-append 'nichromeroot=/dev/sda' \
+-drive id=disk,file=/tmp/t3,if=none \
+-device ich9-ahci,id=ahci \
+-device ide-drive,drive=disk,bus=ahci.0 \
+
diff --git a/nichrome/README.md b/nichrome/README.md
new file mode 100644
index 000000000..9798c7bfa
--- /dev/null
+++ b/nichrome/README.md
@@ -0,0 +1,30 @@
+NiChrome
+=======
+
+[![Build Status](https://travis-ci.org/u-root/NiChrome.svg?branch=master)](https://travis-ci.org/u-root/NiChrome) [![Go Report Card](https://goreportcard.com/badge/github.com/u-root/NiChrome)](https://goreportcard.com/report/github.com/u-root/NiChrome) [![GoDoc](https://godoc.org/github.com/u-root/NiChrome?status.svg)](https://godoc.org/github.com/u-root/NiChrome) [![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://github.com/u-root/NiChrome/blob/master/LICENSE)
+
+
+# Description
+Things we need for NiChrome.
+
+To test out USB stick creation, you will need a ChromeOS-formatted boot stick with the right partitions. We don't know how to create those yet. One way to get such an image is with the chromeos recovery tool, found here:
+https://chrome.google.com/webstore/detail/chromebook-recovery-utili/jndclpdbaamdhonoechobihbbiimdgai?hl=en
+
+You can pick any chromebook to get an image from, since the partition layout is the same on all of them, and the usb tool replaces the A image anyway.
+
+To get an image, for both KERN-[AB] and ROOT-[AB],
+
+Build the usb tool: (cd usb && go build .)
+
+Plug in the chromeos-formatted USB stick.
+
+./usb/usb --fetch=true --dev=/dev/your-usb-stick
+
+e.g.
+./usb/usb --fetch=true --dev=/dev/sdb
+
+usb will default to /dev/null, which makes it easy to test it. You can also run travis.sh to test.
+
+You can skip the -fetch=true on second or later runs of usb.
+
+This defaults to writing the A image (partitions 2 and 3). To use the B image, invoke usb with --useB=true
diff --git a/nichrome/RELEASES b/nichrome/RELEASES
new file mode 100644
index 000000000..9c3378d58
--- /dev/null
+++ b/nichrome/RELEASES
@@ -0,0 +1,13 @@
+# Releases
+
+A new release happens every 6 weeks:
+
+- 1st day on the first month of each quarter
+- 15th day of the second month of each quarter
+
+## v1.0.0 (2018-10-01)
+
+- Initial release
+- Tested with:
+ - Linux 4.12.7
+ - Golang 1.10.3
diff --git a/nichrome/StandardChromeGPT b/nichrome/StandardChromeGPT
new file mode 100644
index 000000000..628edb37e
--- /dev/null
+++ b/nichrome/StandardChromeGPT
@@ -0,0 +1,20774 @@
+[
+{
+ "Signature": 6075990659671082565,
+ "Revision": 65536,
+ "HeaderSize": 92,
+ "CRC": 2966418611,
+ "Reserved": 0,
+ "CurrentLBA": 1,
+ "BackupLBA": 4595647,
+ "FirstLBA": 34,
+ "LastLBA": 4595614,
+ "DiskGUID": "52502ffa-7482-4db3-a5a4-5eb5b65f894e",
+ "PartStart": 2,
+ "NPart": 128,
+ "PartSize": 128,
+ "PartCRC": 1883088094,
+ "Parts": [
+ {
+ "PartGUID": "a2a0d0eb-e5b9-3344-87c0-68b6b72699c7",
+ "UniqueGUID": "c802929e-327e-4202-b028-98af23c69f09",
+ "FirstLBA": 4534272,
+ "LastLBA": 4562943,
+ "Attribute": 0,
+ "Name": [
+ 83,
+ 0,
+ 84,
+ 0,
+ 65,
+ 0,
+ 84,
+ 0,
+ 69,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "5d2a3afe-324f-a741-b725-accc3285a309",
+ "UniqueGUID": "c2e853ba-949a-4852-bbff-41f0e030d2f3",
+ "FirstLBA": 20480,
+ "LastLBA": 53247,
+ "Attribute": 143833713099145216,
+ "Name": [
+ 75,
+ 0,
+ 69,
+ 0,
+ 82,
+ 0,
+ 78,
+ 0,
+ 45,
+ 0,
+ 65,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "02e2b83c-7e3b-dd47-8a3c-7ff2a13cfcec",
+ "UniqueGUID": "e08debd8-e1c2-4ef0-a718-1b43a978eea4",
+ "FirstLBA": 1892352,
+ "LastLBA": 4534271,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 79,
+ 0,
+ 79,
+ 0,
+ 84,
+ 0,
+ 45,
+ 0,
+ 65,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "5d2a3afe-324f-a741-b725-accc3285a309",
+ "UniqueGUID": "c76aab65-c31c-4452-b10e-00edfac4c904",
+ "FirstLBA": 53248,
+ "LastLBA": 86015,
+ "Attribute": 0,
+ "Name": [
+ 75,
+ 0,
+ 69,
+ 0,
+ 82,
+ 0,
+ 78,
+ 0,
+ 45,
+ 0,
+ 66,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "02e2b83c-7e3b-dd47-8a3c-7ff2a13cfcec",
+ "UniqueGUID": "16d7f95c-7f25-409b-a93b-1f845dfc4cf9",
+ "FirstLBA": 1888256,
+ "LastLBA": 1892351,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 79,
+ 0,
+ 79,
+ 0,
+ 84,
+ 0,
+ 45,
+ 0,
+ 66,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "5d2a3afe-324f-a741-b725-accc3285a309",
+ "UniqueGUID": "bbda8f49-d025-4c25-8ae7-cc957e74d56d",
+ "FirstLBA": 16448,
+ "LastLBA": 16448,
+ "Attribute": 0,
+ "Name": [
+ 75,
+ 0,
+ 69,
+ 0,
+ 82,
+ 0,
+ 78,
+ 0,
+ 45,
+ 0,
+ 67,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "02e2b83c-7e3b-dd47-8a3c-7ff2a13cfcec",
+ "UniqueGUID": "6ab1b454-ea05-45f8-bbc8-f02658001f0e",
+ "FirstLBA": 16449,
+ "LastLBA": 16449,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 79,
+ 0,
+ 79,
+ 0,
+ 84,
+ 0,
+ 45,
+ 0,
+ 67,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "a2a0d0eb-e5b9-3344-87c0-68b6b72699c7",
+ "UniqueGUID": "673c5166-5e71-46be-835e-254a4601c9d2",
+ "FirstLBA": 86016,
+ "LastLBA": 1724415,
+ "Attribute": 0,
+ "Name": [
+ 79,
+ 0,
+ 69,
+ 0,
+ 77,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "3d750a2e-489e-b043-8337-b15192cb1b5e",
+ "UniqueGUID": "9561fb22-8ffe-4eb4-ba96-cbb9ec3417d0",
+ "FirstLBA": 16450,
+ "LastLBA": 16450,
+ "Attribute": 0,
+ "Name": [
+ 114,
+ 0,
+ 101,
+ 0,
+ 115,
+ 0,
+ 101,
+ 0,
+ 114,
+ 0,
+ 118,
+ 0,
+ 101,
+ 0,
+ 100,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "3d750a2e-489e-b043-8337-b15192cb1b5e",
+ "UniqueGUID": "e84a7f5e-cc26-42ea-bb4e-f568d71f61ee",
+ "FirstLBA": 16451,
+ "LastLBA": 16451,
+ "Attribute": 0,
+ "Name": [
+ 114,
+ 0,
+ 101,
+ 0,
+ 115,
+ 0,
+ 101,
+ 0,
+ 114,
+ 0,
+ 118,
+ 0,
+ 101,
+ 0,
+ 100,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "8ee8b6ca-f3ab-0241-a07a-d4bb9be3c1d3",
+ "UniqueGUID": "ffeb4bb5-5a6c-4cf4-b36e-9e073a993088",
+ "FirstLBA": 64,
+ "LastLBA": 16447,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 87,
+ 0,
+ 70,
+ 0,
+ 87,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "28732ac1-1ff8-d211-ba4b-00a0c93ec93b",
+ "UniqueGUID": "56742ad8-1e43-4aa3-9345-3e7377be9e65",
+ "FirstLBA": 1855488,
+ "LastLBA": 1888255,
+ "Attribute": 0,
+ "Name": [
+ 69,
+ 0,
+ 70,
+ 0,
+ 73,
+ 0,
+ 45,
+ 0,
+ 83,
+ 0,
+ 89,
+ 0,
+ 83,
+ 0,
+ 84,
+ 0,
+ 69,
+ 0,
+ 77,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ ]
+},
+{
+ "Signature": 6075990659671082565,
+ "Revision": 65536,
+ "HeaderSize": 92,
+ "CRC": 3225090498,
+ "Reserved": 0,
+ "CurrentLBA": 4595647,
+ "BackupLBA": 1,
+ "FirstLBA": 34,
+ "LastLBA": 4595614,
+ "DiskGUID": "52502ffa-7482-4db3-a5a4-5eb5b65f894e",
+ "PartStart": 4595615,
+ "NPart": 128,
+ "PartSize": 128,
+ "PartCRC": 1883088094,
+ "Parts": [
+ {
+ "PartGUID": "a2a0d0eb-e5b9-3344-87c0-68b6b72699c7",
+ "UniqueGUID": "c802929e-327e-4202-b028-98af23c69f09",
+ "FirstLBA": 4534272,
+ "LastLBA": 4562943,
+ "Attribute": 0,
+ "Name": [
+ 83,
+ 0,
+ 84,
+ 0,
+ 65,
+ 0,
+ 84,
+ 0,
+ 69,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "5d2a3afe-324f-a741-b725-accc3285a309",
+ "UniqueGUID": "c2e853ba-949a-4852-bbff-41f0e030d2f3",
+ "FirstLBA": 20480,
+ "LastLBA": 53247,
+ "Attribute": 143833713099145216,
+ "Name": [
+ 75,
+ 0,
+ 69,
+ 0,
+ 82,
+ 0,
+ 78,
+ 0,
+ 45,
+ 0,
+ 65,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "02e2b83c-7e3b-dd47-8a3c-7ff2a13cfcec",
+ "UniqueGUID": "e08debd8-e1c2-4ef0-a718-1b43a978eea4",
+ "FirstLBA": 1892352,
+ "LastLBA": 4534271,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 79,
+ 0,
+ 79,
+ 0,
+ 84,
+ 0,
+ 45,
+ 0,
+ 65,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "5d2a3afe-324f-a741-b725-accc3285a309",
+ "UniqueGUID": "c76aab65-c31c-4452-b10e-00edfac4c904",
+ "FirstLBA": 53248,
+ "LastLBA": 86015,
+ "Attribute": 0,
+ "Name": [
+ 75,
+ 0,
+ 69,
+ 0,
+ 82,
+ 0,
+ 78,
+ 0,
+ 45,
+ 0,
+ 66,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "02e2b83c-7e3b-dd47-8a3c-7ff2a13cfcec",
+ "UniqueGUID": "16d7f95c-7f25-409b-a93b-1f845dfc4cf9",
+ "FirstLBA": 1888256,
+ "LastLBA": 1892351,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 79,
+ 0,
+ 79,
+ 0,
+ 84,
+ 0,
+ 45,
+ 0,
+ 66,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "5d2a3afe-324f-a741-b725-accc3285a309",
+ "UniqueGUID": "bbda8f49-d025-4c25-8ae7-cc957e74d56d",
+ "FirstLBA": 16448,
+ "LastLBA": 16448,
+ "Attribute": 0,
+ "Name": [
+ 75,
+ 0,
+ 69,
+ 0,
+ 82,
+ 0,
+ 78,
+ 0,
+ 45,
+ 0,
+ 67,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "02e2b83c-7e3b-dd47-8a3c-7ff2a13cfcec",
+ "UniqueGUID": "6ab1b454-ea05-45f8-bbc8-f02658001f0e",
+ "FirstLBA": 16449,
+ "LastLBA": 16449,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 79,
+ 0,
+ 79,
+ 0,
+ 84,
+ 0,
+ 45,
+ 0,
+ 67,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "a2a0d0eb-e5b9-3344-87c0-68b6b72699c7",
+ "UniqueGUID": "673c5166-5e71-46be-835e-254a4601c9d2",
+ "FirstLBA": 86016,
+ "LastLBA": 1724415,
+ "Attribute": 0,
+ "Name": [
+ 79,
+ 0,
+ 69,
+ 0,
+ 77,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "3d750a2e-489e-b043-8337-b15192cb1b5e",
+ "UniqueGUID": "9561fb22-8ffe-4eb4-ba96-cbb9ec3417d0",
+ "FirstLBA": 16450,
+ "LastLBA": 16450,
+ "Attribute": 0,
+ "Name": [
+ 114,
+ 0,
+ 101,
+ 0,
+ 115,
+ 0,
+ 101,
+ 0,
+ 114,
+ 0,
+ 118,
+ 0,
+ 101,
+ 0,
+ 100,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "3d750a2e-489e-b043-8337-b15192cb1b5e",
+ "UniqueGUID": "e84a7f5e-cc26-42ea-bb4e-f568d71f61ee",
+ "FirstLBA": 16451,
+ "LastLBA": 16451,
+ "Attribute": 0,
+ "Name": [
+ 114,
+ 0,
+ 101,
+ 0,
+ 115,
+ 0,
+ 101,
+ 0,
+ 114,
+ 0,
+ 118,
+ 0,
+ 101,
+ 0,
+ 100,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "8ee8b6ca-f3ab-0241-a07a-d4bb9be3c1d3",
+ "UniqueGUID": "ffeb4bb5-5a6c-4cf4-b36e-9e073a993088",
+ "FirstLBA": 64,
+ "LastLBA": 16447,
+ "Attribute": 0,
+ "Name": [
+ 82,
+ 0,
+ 87,
+ 0,
+ 70,
+ 0,
+ 87,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "28732ac1-1ff8-d211-ba4b-00a0c93ec93b",
+ "UniqueGUID": "56742ad8-1e43-4aa3-9345-3e7377be9e65",
+ "FirstLBA": 1855488,
+ "LastLBA": 1888255,
+ "Attribute": 0,
+ "Name": [
+ 69,
+ 0,
+ 70,
+ 0,
+ 73,
+ 0,
+ 45,
+ 0,
+ 83,
+ 0,
+ 89,
+ 0,
+ 83,
+ 0,
+ 84,
+ 0,
+ 69,
+ 0,
+ 77,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "PartGUID": "00000000-0000-0000-0000-000000000000",
+ "UniqueGUID": "00000000-0000-0000-0000-000000000000",
+ "FirstLBA": 0,
+ "LastLBA": 0,
+ "Attribute": 0,
+ "Name": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ ]
+}
+]
diff --git a/nichrome/azure-pipelines.yml b/nichrome/azure-pipelines.yml
new file mode 100644
index 000000000..71a521ce3
--- /dev/null
+++ b/nichrome/azure-pipelines.yml
@@ -0,0 +1,41 @@
+# Go
+# Build your Go project.
+# Add steps that test, save build artifacts, deploy, and more:
+# https://docs.microsoft.com/azure/devops/pipelines/languages/go
+
+trigger:
+- master
+
+pool:
+ vmImage: 'Ubuntu-16.04'
+
+variables:
+ GOBIN: '$(GOPATH)/bin' # Go binaries path
+ GOROOT: '/usr/local/go1.12' # Go installation path
+ GOPATH: '$(system.defaultWorkingDirectory)/gopath' # Go workspace path
+ modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code
+
+steps:
+- script: |
+ mkdir -p '$(GOBIN)'
+ mkdir -p '$(GOPATH)/pkg'
+ mkdir -p '$(modulePath)'
+ shopt -s extglob
+ mv !(gopath) '$(modulePath)'
+ echo '##vso[task.prependpath]$(GOBIN)'
+ echo '##vso[task.prependpath]$(GOROOT)/bin'
+ displayName: 'Set up the Go workspace'
+
+- script: |
+ go version
+ go get -v -t -d ./...
+ if [ -f Gopkg.toml ]; then
+ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
+ dep ensure
+ fi
+ pwd
+ echo $GOPATH
+ (cd usb && go build .)
+ ./usb/usb --apt=true --fetch=true --dev=/dev/null
+ workingDirectory: '$(modulePath)'
+ displayName: 'Get dependencies, then build'
diff --git a/nichrome/cmds/install/install.go b/nichrome/cmds/install/install.go
new file mode 100644
index 000000000..6dcae17a6
--- /dev/null
+++ b/nichrome/cmds/install/install.go
@@ -0,0 +1,172 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// install installs a NiChrome image from a USB stick onto the local drive.
+// It verifies, first, that it can enumerate the partitions correctly
+// on the destination. It uses guid_root to rewrite the GPT partition
+// guids for the target partition(s).
+// It defaults to only installing the B images, since we assume
+// for now we are still in hacker mode.
+
+// +build go1.11
+
+package main
+
+import (
+ "fmt"
+ flag "github.com/spf13/pflag"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "strings"
+
+ "github.com/u-root/u-root/pkg/cpio"
+ "github.com/u-root/u-root/pkg/mount/gpt"
+)
+
+var cmdline = make(map[string]string)
+
+func parseCmdline() {
+ b, err := ioutil.ReadFile("/proc/cmdline")
+ if err != nil {
+ log.Printf("Can't read command line: %v", err)
+ }
+ for _, s := range strings.Fields(string(b)) {
+ f := strings.SplitN(s, "=", 2)
+ if len(f) == 0 {
+ continue
+ }
+ if len(f) == 1 {
+ f = []string{f[0], "1"}
+ }
+ cmdline[f[0]] = f[1]
+ }
+}
+
+// Find the boot media containing the root GUID.
+func findKernDev(devs ...string) (string, gpt.GUID, error) {
+ rg, ok := cmdline["guid_root"]
+ if !ok {
+ return "", gpt.GUID{}, fmt.Errorf("No guid_root cmdline parameter")
+ }
+ for _, d := range devs {
+ fi, err := os.Stat(d)
+ if fi == nil || err != nil {
+ log.Print(err)
+ continue
+ }
+ if fi.Mode()&os.ModeType != os.ModeDevice {
+ log.Printf("%v is not a device", d)
+ continue
+ }
+ f, err := os.Open(d)
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+ pt, err := gpt.New(f)
+ f.Close()
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+ // install media is always KERN-A, second partition.
+ if pt.Primary.Parts[1].UniqueGUID.String() == rg {
+ log.Printf("%v: GUID %s matches for partition 2\n", d, rg)
+ return fmt.Sprintf("%s", d), pt.Primary.Parts[1].UniqueGUID, nil
+ }
+ }
+ return "", gpt.GUID{}, fmt.Errorf("A device with that GUID was not found")
+}
+
+func main() {
+ flag.Parse()
+ if len(flag.Args()) < 1 {
+ flag.Usage()
+ log.Fatalf("install [options] dest-device")
+ }
+
+ parseCmdline()
+
+ d, u, err := findKernDev("/dev/sda", "/dev/sdb")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // For now we always go with the B side. This means we need to change the
+ // GUID in the GPT for partition 4.
+ log.Printf("Install Media is on %s", d)
+
+ // We're going to be a bit paranoid in the order in which we do things.
+ // open the device and read the GPT.
+ // open both output partitions writeable to make sure that works.
+ // open input partitions.
+ // write the unchanged GPT back to the target as a test.
+ // write KERN-B
+ // write ROOT-B
+ // write the changed GPT with the new KERN-B UniqueGUID
+ // With luck, if there's a problem, we hit it long before
+ // we doing anything irreversible.
+
+ dest := flag.Args()[0]
+ destDev, err := os.OpenFile(dest, os.O_RDWR, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ pt, err := gpt.New(destDev)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // What a hack. mmc doesn't follow the venerable
+ // naming conventions.
+ var hack string
+ if strings.HasPrefix(dest, "/dev/mmc") {
+ log.Printf("It's mmc, add hack")
+ hack = "p"
+ }
+ log.Printf("Installing on %s%s{4,5}", dest, hack)
+ destKern, err := os.OpenFile(dest+hack+"4", os.O_RDWR, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ destRoot, err := os.OpenFile(dest+hack+"5", os.O_RDWR, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ kern, err := os.Open(d + "2")
+ if err != nil {
+ log.Fatal(err)
+ }
+ root, err := os.Open(d + "3")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Point of no return. Fix the GUID on the device.
+ // Write the old GPT back first to see if writes even work.
+ if err := gpt.Write(destDev, pt); err != nil {
+ log.Fatal(err)
+ }
+ if _, err := io.Copy(destKern, kern); err != nil {
+ log.Fatal(err)
+ }
+
+ archiver, err := cpio.Format("newc")
+ if err != nil {
+ log.Fatalf("newc not supported: %v", err)
+ }
+
+ r := archiver.Reader(root)
+ w := archiver.Writer(destRoot)
+ if err := cpio.Passthrough(r, w); err != nil {
+ log.Fatal(err)
+ }
+ pt.Primary.Parts[3].UniqueGUID = u
+ pt.Backup.Parts[3].UniqueGUID = u
+ if err := gpt.Write(destDev, pt); err != nil {
+ log.Fatal(err)
+ }
+ log.Printf("All done. restart in chromeos and cgpt add -i 4 -P 2 -S 0 -T 1 %v", dest)
+}
diff --git a/nichrome/cmds/sos/sos.go b/nichrome/cmds/sos/sos.go
new file mode 100644
index 000000000..b60921c60
--- /dev/null
+++ b/nichrome/cmds/sos/sos.go
@@ -0,0 +1,22 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "log"
+ "os/exec"
+
+ "github.com/u-root/NiChrome/pkg/sos"
+)
+
+var htmlRoot = flag.String("html", "/etc/sos/html", "Path for root of SOS html files")
+
+func main() {
+ if o, err := exec.Command("ip", "link", "set", "dev", "lo", "up").CombinedOutput(); err != nil {
+ log.Fatalf("ip link set dev lo: %v (%v)", string(o), err)
+ }
+ sos.StartServer(sos.NewSosService())
+}
diff --git a/nichrome/cmds/timesos/server.go b/nichrome/cmds/timesos/server.go
new file mode 100644
index 000000000..6ed2a5fb8
--- /dev/null
+++ b/nichrome/cmds/timesos/server.go
@@ -0,0 +1,189 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "io/ioutil"
+ "log"
+ "net/http"
+
+ "github.com/gorilla/mux"
+ "github.com/u-root/NiChrome/pkg/sos"
+)
+
+const (
+ DefHtmlPage = `
+
+
+
+
+
+ System Time Settings
+
+
+ `
+)
+
+type TimeServer struct {
+ service *TimeService
+}
+
+var (
+ Port uint
+)
+
+func (ts *TimeServer) displayStateHandle(w http.ResponseWriter, r *http.Request) {
+ ts.service.Update()
+ timeData := struct {
+ Date string
+ Time string
+ Port uint
+ }{ts.service.Date, ts.service.Time, Port}
+ var tmpl *template.Template
+ file, err := ioutil.ReadFile(sos.HTMLPath("time.html"))
+ if err == nil {
+ html := string(file)
+ tmpl = template.Must(template.New("SoS").Parse(html))
+ } else {
+ tmpl = template.Must(template.New("SoS").Parse(DefHtmlPage))
+ }
+ tmpl.Execute(w, timeData)
+}
+
+func (ts *TimeServer) autoHandle(w http.ResponseWriter, r *http.Request) {
+ if err := ts.service.AutoSetTime(); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{fmt.Sprintf("Unable to set time. Are you online?")})
+ return
+ }
+ json.NewEncoder(w).Encode(nil)
+}
+
+type TimeJsonMsg struct {
+ Date string
+ Time string
+}
+
+func (ts *TimeServer) manHandle(w http.ResponseWriter, r *http.Request) {
+ var msg TimeJsonMsg
+ decoder := json.NewDecoder(r.Body)
+ defer r.Body.Close()
+ if err := decoder.Decode(&msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ if err := ts.service.ManSetTime(msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ json.NewEncoder(w).Encode(nil)
+}
+
+func (ts *TimeServer) buildRouter() *mux.Router {
+ r := mux.NewRouter()
+ r.HandleFunc("/", ts.displayStateHandle).Methods("GET")
+ r.HandleFunc("/auto", ts.autoHandle).Methods("POST")
+ r.HandleFunc("/manual", ts.manHandle).Methods("POST")
+ r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(sos.HTMLPath("css")))))
+ return r
+}
+
+// Start opens the server at localhost:{port}, where port is provided automatically
+// by the SoS.
+func (ts *TimeServer) Start() {
+ listener, port, err := sos.GetListener()
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ Port = port
+ fmt.Println(sos.StartServiceServer(ts.buildRouter(), "time", listener, Port))
+}
+
+// NewTimeServer creates a server with the given TimeService.
+func NewTimeServer(service *TimeService) *TimeServer {
+ return &TimeServer{
+ service: service,
+ }
+}
diff --git a/nichrome/cmds/timesos/service.go b/nichrome/cmds/timesos/service.go
new file mode 100644
index 000000000..a496955bc
--- /dev/null
+++ b/nichrome/cmds/timesos/service.go
@@ -0,0 +1,68 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "os/exec"
+ "strconv"
+ "syscall"
+ "time"
+)
+
+type TimeService struct {
+ Date string
+ Time string
+}
+
+func getCurrentDate() string {
+ return time.Now().Format("2006-01-02")
+}
+
+func getCurrentTime() string {
+ return time.Now().Format("15:04")
+}
+
+func parseDate(d TimeJsonMsg) time.Time {
+ // split date message into integers for each field
+ YYYY, _ := strconv.Atoi(d.Date[:4])
+ MM, _ := strconv.Atoi(d.Date[5:7])
+ DD, _ := strconv.Atoi(d.Date[8:])
+
+ hh, _ := strconv.Atoi(d.Time[:2])
+ mm, _ := strconv.Atoi(d.Time[3:])
+
+ return time.Date(YYYY, time.Month(MM), DD, hh, mm, 0, 0, time.UTC)
+}
+
+// Update sets the TimeService fields to the current system time
+func (ts *TimeService) Update() {
+ ts.Date = getCurrentDate()
+ ts.Time = getCurrentTime()
+}
+
+// AutoSetTime calls the ntpdate u-root command to get
+// the current date from time.google.com
+func (ts TimeService) AutoSetTime() error {
+ return exec.Command("ntpdate").Run()
+}
+
+// ManSetTime sets the system time similarly to u-root's "date" command with
+// user-entered fields
+func (ts TimeService) ManSetTime(new TimeJsonMsg) error {
+ userTime := parseDate(new)
+ tv := syscall.NsecToTimeval(userTime.UnixNano())
+ if err := syscall.Settimeofday(&tv); err != nil {
+ return err
+ }
+ return nil
+}
+
+// NewTimeService builds a TimeService with the current system date and time
+func NewTimeService() (*TimeService, error) {
+ return &TimeService{
+ Date: getCurrentDate(),
+ Time: getCurrentTime(),
+ }, nil
+}
diff --git a/nichrome/cmds/timesos/time_sos.go b/nichrome/cmds/timesos/time_sos.go
new file mode 100644
index 000000000..1ee57ff5b
--- /dev/null
+++ b/nichrome/cmds/timesos/time_sos.go
@@ -0,0 +1,17 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "log"
+)
+
+func main() {
+ service, err := NewTimeService()
+ if err != nil {
+ log.Fatal(err)
+ }
+ NewTimeServer(service).Start()
+}
diff --git a/nichrome/cmds/uinit/uinit.go b/nichrome/cmds/uinit/uinit.go
new file mode 100644
index 000000000..433d799d3
--- /dev/null
+++ b/nichrome/cmds/uinit/uinit.go
@@ -0,0 +1,481 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is the basic chromebook uinit.
+
+// +build go1.11
+
+package main
+
+import (
+ "fmt"
+ flag "github.com/spf13/pflag"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/u-root/u-root/pkg/cpio"
+ "github.com/u-root/u-root/pkg/mount/gpt"
+ "github.com/u-root/u-root/pkg/uroot/util"
+)
+
+// For now we are going to stick with a single
+// version of tcz packages. It's not possible
+// with their design to mix versions.
+const (
+ tczs = "/tcz/8.x/*/tcz/*.tcz"
+ homeEnv = "/home/user"
+ userEnv = "user"
+ passwd = "root:x:0:0:root:/:/bin/bash\nuser:x:1000:1000:" + userEnv + ":" + homeEnv + ":/bin/bash\n"
+ hosts = "127.0.0.1 localhost\n"
+)
+
+var (
+ rootStartCmds = []string{"sos", "wifi", "timesos"}
+ userStartCmds = []string{"wingo", "AppChrome", "upspinsos", "chrome"}
+ cmdline = make(map[string]string)
+ debug = func(string, ...interface{}) {}
+ usernamespace = flag.Bool("usernamespace", false, "Set up user namespaces and spawn login")
+ user = flag.Bool("user", false, "Ru as a user")
+ login = flag.Bool("login", false, "Login as a user")
+ verbose bool
+)
+
+func tczSetup() error {
+ g, err := filepath.Glob(tczs)
+ if err != nil {
+ log.Printf("Glob of %v: %v", tczs, err)
+ }
+ debug("Tcz file list: %v", g)
+ // Now get the basenames, and then install them.
+ // TODO: fix up tcz to take a path name?
+ // The glob ensured they all end in .tcz.
+ // We can just take all but the last 4 chars of the name.
+ var tczlist []string
+ for _, p := range g {
+ b := filepath.Base(p)
+ tczlist = append(tczlist, b[:len(b)-4])
+ }
+
+ log.Printf("Installing %d tinycore packages...", len(tczlist))
+ cmd := exec.Command("tcz", append([]string{"-v", "8.x"}, tczlist...)...)
+ log.Print("Done")
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ return cmd.Run()
+}
+
+func parseCmdline() {
+ b, err := ioutil.ReadFile("/proc/cmdline")
+ if err != nil {
+ log.Printf("Can't read command line: %v", err)
+ }
+ for _, s := range strings.Fields(string(b)) {
+ f := strings.SplitN(s, "=", 2)
+ if len(f) == 0 {
+ continue
+ }
+ if len(f) == 1 {
+ f = []string{f[0], "1"}
+ }
+ cmdline[f[0]] = f[1]
+ }
+}
+
+// Find the root GUID.
+func findRoot(devs ...string) (string, error) {
+ rg, ok := cmdline["guid_root"]
+ if !ok {
+ return "", fmt.Errorf("No root_guid cmdline parameter")
+ }
+ for _, d := range devs {
+ fi, err := os.Stat(d)
+ if fi == nil || err != nil {
+ log.Print(err)
+ continue
+ }
+ if fi.Mode()&os.ModeType != os.ModeDevice {
+ log.Printf("%v is not a device", d)
+ continue
+ }
+ f, err := os.Open(d)
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+ pt, err := gpt.New(f)
+ f.Close()
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+ for i, p := range pt.Primary.Parts {
+ var zero gpt.GUID
+ if p.UniqueGUID == zero {
+ continue
+ }
+ if p.UniqueGUID.String() == rg {
+ log.Printf("%v: GUID %s matches for partition %d (map to %d)\n", d, rg, i, i+2)
+ // non standard naming. Grumble.
+ var hack string
+ if strings.HasPrefix(d, "/dev/mmc") {
+ hack = "p"
+ }
+ return fmt.Sprintf("%s%s%d", d, hack, i+2), nil
+ }
+ log.Printf("%v: part %d, Device GUID %v, GUID %s no match", d, i, p.UniqueGUID.String(), rg)
+ }
+ }
+ return "", fmt.Errorf("A device with that GUID was not found")
+}
+
+func x11(n string, args ...string) error {
+ out := os.Stdout
+ f, err := ioutil.TempFile("", filepath.Base(n))
+ if err != nil {
+ log.Print(err)
+ } else {
+ out = f
+ }
+ cmd := exec.Command(n, args...)
+ cmd.Env = append(os.Environ(), "DISPLAY=:0")
+ cmd.Stdout, cmd.Stderr = out, out
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("X11 start %v %v: %v", n, args, err)
+ }
+ return nil
+}
+
+// When we make the transition to a new user we need to set up a new namespace for that user.
+// So far the only thing we know we need to do is remount ubin, tmp, env, and go/pkg
+// The tmp is particularly useful as it avoids races between root-owned files and files
+// for this user.
+var (
+ namespace = []util.Creator{
+ util.Mount{Source: "tmpfs", Target: "/go/pkg/linux_amd64", FSType: "tmpfs"},
+ util.Mount{Source: "tmpfs", Target: "/dev/shm", FSType: "tmpfs"},
+ util.Mount{Source: "tmpfs", Target: "/ubin", FSType: "tmpfs"},
+ util.Mount{Source: "tmpfs", Target: "/pkg", FSType: "tmpfs"},
+ }
+ rootFileSystem = []util.Creator{
+ util.Dir{Name: "/go/pkg/linux_amd64", Mode: 0777},
+ util.Dir{Name: "/dev/shm", Mode: 0777},
+ util.Dir{Name: "/pkg", Mode: 0777},
+ util.Dir{Name: "/ubin", Mode: 0777},
+ // fusermount requires this. When we write our own we can remove this.
+ util.Symlink{NewPath: "/etc/mtab", Target: "/proc/mounts"},
+ // Sigh.
+ util.Symlink{NewPath: "/bin/sh", Target: "/bin/bash"},
+ // Resolve localhost name
+ util.File{Name: "/etc/hosts", Contents: "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\n", Mode: 0644},
+ }
+)
+
+func xrun() error {
+ // At this point we are still root.
+ if err := os.Symlink("/usr/local/bin/bash", "/bin/bash"); err != nil {
+ return err
+ }
+ if err := os.Symlink("/lib/ld-linux-x86-64.so.2", "/lib64/ld-linux-x86-64.so.2"); err != nil {
+ return err
+ }
+ go func() {
+ cmd := exec.Command("Xfbdev")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ log.Fatalf("X11 startup: %v", err)
+ }
+ }()
+ for {
+ s, err := filepath.Glob("/tmp/.X*/X?")
+ if err != nil {
+ return err
+ }
+ if len(s) > 0 {
+ break
+ }
+ time.Sleep(time.Second)
+ }
+ return nil
+}
+
+func dousernamespace() error {
+ // start us as a child again with a private name space.
+ // Limitations of the Go runtime mandate doing it this way.
+
+ // due to limits of Go runtime we have to run ourselves again with -login
+ // and build a namespace.
+ cmd := exec.Command("/bbin/uinit", "--login")
+ cmd.SysProcAttr = &syscall.SysProcAttr{Unshareflags: syscall.CLONE_NEWNS}
+ cmd.Env = append(os.Environ(), fmt.Sprintf("USER=%v", userEnv), fmt.Sprintf("HOME=%v", homeEnv))
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ if err := cmd.Start(); err != nil {
+ return fmt.Errorf("donamespace: %v", err)
+ }
+ return nil
+}
+
+func dologin() error {
+ // Here we need to create the new namespace and then start our children.
+ var err error
+ for _, c := range namespace {
+ if err = c.Create(); err != nil {
+ return fmt.Errorf("Error creating %s: %vi; not starting user x11 programs", c, err)
+ }
+ }
+
+ if err == nil {
+ // due to limits of Go runtime we have to run ourselves again with -user.
+ cmd := exec.Command("/bbin/uinit", "--user")
+ cmd.SysProcAttr = &syscall.SysProcAttr{Credential: &syscall.Credential{Uid: 1000, Gid: 1000, NoSetGroups: true}}
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("X11 user startup: %v", err)
+ }
+ }
+ return nil
+}
+
+func homedir() error {
+ f, err := os.Open("/usr/user.cpio")
+ if err != nil {
+ return err
+ }
+ archiver, err := cpio.Format("newc")
+ if err != nil {
+ return err
+ }
+ rr := archiver.Reader(f)
+ for {
+ rec, err := rr.ReadRecord()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return fmt.Errorf("error reading records: %v", err)
+ }
+ debug("Creating %s\n", rec)
+ if err := cpio.CreateFile(rec); err != nil {
+ log.Printf("Creating %q failed: %v", rec.Name, err)
+ }
+ }
+ return nil
+}
+
+func xrunuser() error {
+ for _, f := range userStartCmds {
+ log.Printf("Run %v", f)
+ go x11(f)
+ }
+
+ // we block on the aterm. When the aterm exits, we do too.
+ return x11("/usr/local/bin/aterm")
+}
+
+func cpioRoot(r string) error {
+ var err error
+ log.Printf("Try device %v", r)
+ cmd := exec.Command("cpio", "i")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ if cmd.Stdin, err = os.Open(r); err != nil {
+ return fmt.Errorf("%v", err)
+ }
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("cpio of tcz failed %v", err)
+ }
+ return nil
+}
+
+// This is a best effort. It does not return an error because
+// an error may not really be an error; we may be intentionally
+// running without a root.
+func guidRoot() {
+ // USB sucks.
+ // We've tried a few variants of this loop so far trying for
+ // 10 seconds and waiting for 1 second each time has been the best.
+ for i := 0; i < 10; i++ {
+ r, err := findRoot("/dev/sda", "/dev/sdb", "/dev/mmcblk0", "/dev/mmcblk1")
+ if err != nil {
+ log.Printf("Could not find root: %v", err)
+ } else {
+ if err := cpioRoot(r); err == nil {
+ break
+ }
+ }
+ time.Sleep(time.Second)
+ }
+}
+
+func main() {
+ // nasty, but I'm sick of losing boot messages.
+ f, err := os.OpenFile("/log", os.O_RDWR|os.O_CREATE, 0755)
+ if err == nil {
+ fd := int(f.Fd())
+ if err := syscall.Dup2(fd, 1); err != nil {
+ log.Printf("Could not dup %v over 1: %v", fd, err)
+ }
+ if err := syscall.Dup2(fd, 2); err != nil {
+ log.Printf("Could not dup %v over 2: %v", fd, err)
+ }
+ } else {
+ log.Printf("Can't open /log: %v", err)
+ }
+ log.Print("Welcome to NiChrome!")
+ flag.Parse()
+ if *usernamespace {
+ if err := dousernamespace(); err != nil {
+ log.Fatal(err)
+ }
+ os.Exit(0)
+ }
+
+ if *login {
+ if err := dologin(); err != nil {
+ log.Fatal(err)
+ }
+ os.Exit(0)
+ }
+
+ if *user {
+ log.Print("Starting up user mode processes")
+ if err := homedir(); err != nil {
+ log.Printf("Could not populate %v, err %v: continuing anyway", homeEnv, err)
+ }
+ if err := xrunuser(); err != nil {
+ log.Fatalf("x11 user failed: %v", err)
+ }
+ os.Exit(0)
+ }
+
+ parseCmdline()
+
+ if _, ok := cmdline["uinitdebug"]; ok {
+ debug = log.Printf
+ verbose = true
+ }
+
+ if d, ok := cmdline["nichromeroot"]; ok {
+ cpioRoot(d)
+ } else {
+ guidRoot()
+ }
+
+ if err := tczSetup(); err != nil {
+ log.Printf("tczSetup: %v", err)
+ }
+
+ // buildbin was not populated, potentially, so we have to do it again.
+ c, err := filepath.Glob("/src/github.com/u-root/*/cmds/*/[a-z]*")
+ if err != nil || len(c) == 0 {
+ log.Printf("In a break with tradition, you seem to have NO u-root commands: %v", err)
+ }
+ o, err := filepath.Glob("/src/*/*/*")
+ if err != nil {
+ log.Printf("Your filepath glob for other commands seems busted: %v", err)
+ }
+ c = append(c, o...)
+ for _, v := range c {
+ name := filepath.Base(v)
+ if name == "installcommand" || name == "init" {
+ continue
+ } else {
+ destPath := filepath.Join("/buildbin", name)
+ source := "/buildbin/installcommand"
+ if err := os.Symlink(source, destPath); err != nil {
+ log.Printf("Symlink %v -> %v failed; %v", source, destPath, err)
+ }
+ }
+ }
+
+ a := []string{"build"}
+ envs := os.Environ()
+ debug("envs %v", envs)
+ //os.Setenv("GOBIN", "/buildbin")
+ // util.CmdsPath vanished
+ //a = append(a, "-o", "/buildbin/installcommand", filepath.Join(util.CmdsPath, "installcommand"))
+ a = append(a, "-o", "/buildbin/installcommand", "github.com/u-root/u-root/cmds/core/installcommand")
+ icmd := exec.Command("go", a...)
+ installenvs := envs
+ installenvs = append(envs, "GOBIN=/buildbin")
+ icmd.Env = installenvs
+ icmd.Dir = "/"
+
+ icmd.Stdin = os.Stdin
+ icmd.Stderr = os.Stderr
+ icmd.Stdout = os.Stdout
+ debug("Run %v", icmd)
+ if err := icmd.Run(); err != nil {
+ log.Printf("%v\n", err)
+ }
+
+ cmd := exec.Command("ip", "addr", "add", "127.0.0.1/24", "lo")
+ if o, err := cmd.CombinedOutput(); err != nil {
+ log.Printf("ip link failed(%v, %v); continuing", string(o), err)
+ }
+ cmd = exec.Command("ip", "link", "set", "dev", "lo", "up")
+ if o, err := cmd.CombinedOutput(); err != nil {
+ log.Printf("ip link up failed(%v, %v); continuing", string(o), err)
+ }
+
+ for _, c := range rootFileSystem {
+ if err = c.Create(); err != nil {
+ log.Printf("Error creating %s: %vi; not starting user x11 programs", c, err)
+ }
+ }
+
+ // AppImages need /dev/fuse to be 0666, even though they also use the
+ // suid fusermount, which does not need /dev/fuse to be 0666. Oh well.
+ if err := os.Chmod("/dev/fuse", 0666); err != nil {
+ log.Printf("chmod of /dev/fuse to 0666 failed: %v", err)
+ }
+
+ // If they did not supply a password file, we have to supply a simple
+ // one or tools like fusermount will fail. We hope soon to have a
+ // u-root implementation of fusermount that's not so particular.
+ if _, err := os.Stat("/etc/passwd"); err != nil {
+ if err := ioutil.WriteFile("/etc/passwd", []byte(passwd), os.FileMode(0644)); err != nil {
+ log.Printf("Error creating /etc/passwd: %v", err)
+ }
+ }
+ // If they did not supply a hosts file, we need one for localhost.
+ if _, err := os.Stat("/etc/hosts"); err != nil {
+ if err := ioutil.WriteFile("/etc/hosts", []byte(hosts), os.FileMode(0644)); err != nil {
+ log.Printf("Error creating /etc/hosts: %v", err)
+ }
+ }
+ if err := xrun(); err != nil {
+ log.Fatalf("xrun failed %v:", err)
+ }
+
+ // HACK.
+ // u-root is setting bogus modes on /. fix it.
+ // hack for new u-root cpio bug.
+ // We may just leave this here forever, since the failure is so hard
+ // to diagnose.
+ if err := os.Chmod("/", 0777); err != nil {
+ log.Print(err)
+ }
+
+ for _, f := range rootStartCmds {
+ log.Printf("Run %v", f)
+ go x11(f)
+ // we have to give it a little time until we make it smarter
+ time.Sleep(2 * time.Second)
+ }
+
+ if err := dousernamespace(); err != nil {
+ log.Printf("dousernamespace: %v", err)
+ }
+
+ // kick off one user shell so they can do what needs to be done.
+ // When this ends we exit everything.
+ if err := x11("/usr/local/bin/aterm"); err != nil {
+ log.Printf("Starting root aterm: %v", err)
+ }
+}
diff --git a/nichrome/cmds/upspinsos/server.go b/nichrome/cmds/upspinsos/server.go
new file mode 100644
index 000000000..ec23eb1da
--- /dev/null
+++ b/nichrome/cmds/upspinsos/server.go
@@ -0,0 +1,223 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "io/ioutil"
+ "log"
+ "net/http"
+
+ "github.com/gorilla/mux"
+ "github.com/u-root/NiChrome/pkg/sos"
+)
+
+const (
+ DefHtmlPage = `
+
+
+
+
+
+
+ {{$user := .User}}
+ {{$dir := .Dir}}
+ {{$store := .Store}}
+ {{$seed := .Seed}}
+ Upspin
+
+
+`
+)
+
+type UpspinServer struct {
+ service *UpspinService
+}
+
+var (
+ Port uint
+)
+
+func (us *UpspinServer) editHandle(w http.ResponseWriter, r *http.Request) {
+ us.service.ToggleFlag()
+ json.NewEncoder(w).Encode(nil)
+}
+
+type UpspinAcctJsonMsg struct {
+ User string
+ Dir string
+ Store string
+ Seed string
+}
+
+func (us *UpspinServer) submitHandle(w http.ResponseWriter, r *http.Request) {
+ us.service.ToggleFlag()
+ var msg UpspinAcctJsonMsg
+ decoder := json.NewDecoder(r.Body)
+ defer r.Body.Close()
+ if err := decoder.Decode(&msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ if err := us.service.SetConfig(msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ json.NewEncoder(w).Encode(nil)
+}
+
+func (us *UpspinServer) displayStateHandle(w http.ResponseWriter, r *http.Request) {
+ us.service.Update()
+ upspinData := struct {
+ Configured bool
+ User string
+ Dir string
+ Store string
+ Seed string
+ Port uint
+ }{us.service.Configured, us.service.User, us.service.Dir, us.service.Store, us.service.Seed, Port}
+ var tmpl *template.Template
+ file, err := ioutil.ReadFile(sos.HTMLPath("upspin.html"))
+ if err == nil {
+ html := string(file)
+ tmpl = template.Must(template.New("SoS").Parse(html))
+ } else {
+ tmpl = template.Must(template.New("SoS").Parse(DefHtmlPage))
+ }
+ tmpl.Execute(w, upspinData)
+}
+
+func (us *UpspinServer) buildRouter() *mux.Router {
+ r := mux.NewRouter()
+ r.HandleFunc("/", us.displayStateHandle).Methods("GET")
+ r.HandleFunc("/edit", us.editHandle).Methods("POST")
+ r.HandleFunc("/submit", us.submitHandle).Methods("POST")
+ r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(sos.HTMLPath("css")))))
+ return r
+}
+
+func (us *UpspinServer) Start() {
+ listener, port, err := sos.GetListener()
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ Port = port
+ fmt.Println(sos.StartServiceServer(us.buildRouter(), "upspin", listener, Port))
+}
+
+func NewUpspinServer(service *UpspinService) *UpspinServer {
+ return &UpspinServer{
+ service: service,
+ }
+}
diff --git a/nichrome/cmds/upspinsos/service.go b/nichrome/cmds/upspinsos/service.go
new file mode 100644
index 000000000..36836172b
--- /dev/null
+++ b/nichrome/cmds/upspinsos/service.go
@@ -0,0 +1,139 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+var (
+ upspinConfigDir = flag.String("configdir", filepath.Join(os.Getenv("HOME"), "upspin"), "path for Upspin config file")
+ upspinKeyDir = flag.String("keydir", filepath.Join(os.Getenv("HOME"), ".ssh"), "path for username directory to hold key files")
+)
+
+type UpspinService struct {
+ Configured bool
+ User string
+ Dir string
+ Store string
+ Seed string
+}
+
+func makeUserDirectories(dir string) error {
+ if _, err := os.Stat(dir); os.IsNotExist(err) {
+ if err := os.MkdirAll(dir, 0777); err != nil {
+ return err
+ }
+ return filepath.Walk(dir, func(name string, info os.FileInfo, err error) error {
+ if err == nil {
+ err = os.Chown(name, 1000, 1000)
+ }
+ return err
+ })
+ }
+ return nil
+}
+
+func getFileData(path string) map[string]string {
+ userData := make(map[string]string)
+ b, err := ioutil.ReadFile(path)
+ if err != nil {
+ // start in unconfigured mode using empty map
+ return userData
+ }
+ // regex for finding key-val separator ": [remote,]" and port ":443"
+ splitpoint := regexp.MustCompile("(: )(.*,|)")
+ port := regexp.MustCompile("(:443)")
+ for _, s := range strings.Split(string(b), "\n") {
+ s := port.ReplaceAllString(s, "")
+ keyval := splitpoint.Split(s, -1)
+ if len(keyval) == 2 {
+ userData[keyval[0]] = keyval[1]
+ }
+ }
+ return userData
+}
+
+func (us UpspinService) setFileData(path string) error {
+ f, err := os.Create(path)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ f.WriteString(fmt.Sprintf("username: %v\n", us.User))
+ // hardcoded default server prefix and suffix
+ f.WriteString(fmt.Sprintf("dirserver: remote,%v:443\n", us.Dir))
+ f.WriteString(fmt.Sprintf("storeserver: remote,%v:443\n", us.Store))
+ f.WriteString("packing: ee\n")
+ return nil
+}
+
+func (us UpspinService) setKeys(path string) error {
+ // check if keys are set already
+ f, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ args := []string{"keygen", fmt.Sprintf("-secretseed=%v", us.Seed)}
+ // if the directory is populated, rotate the keys instead of generating new ones
+ // this method of appending args is ugly, but they have to be in this specific order:
+ // upspin keygen <-rotate> -secretseed= path
+ if _, err = f.Readdir(1); err == nil {
+ args = append(args, "-rotate")
+ }
+
+ return exec.Command("upspin", append(args, path)...).Run()
+}
+
+func (us *UpspinService) Update() {
+ data := getFileData(filepath.Join(*upspinConfigDir, "config"))
+ us.User = data["username"]
+ us.Dir = data["dirserver"]
+ us.Store = data["storeserver"]
+}
+
+func (us *UpspinService) ToggleFlag() {
+ us.Configured = !us.Configured
+}
+
+func (us *UpspinService) SetConfig(new UpspinAcctJsonMsg) error {
+ us.User = new.User
+ us.Dir = new.Dir
+ us.Store = new.Store
+ us.Seed = new.Seed
+ makeUserDirectories(*upspinConfigDir)
+ if err := us.setFileData(filepath.Join(*upspinConfigDir, "config")); err != nil {
+ return err
+ }
+ fullKeyPath := filepath.Join(*upspinKeyDir, us.User)
+ makeUserDirectories(fullKeyPath)
+ if err := us.setKeys(fullKeyPath); err != nil {
+ return err
+ }
+ return nil
+}
+
+func NewUpspinService() (*UpspinService, error) {
+ data := getFileData(filepath.Join(*upspinConfigDir, "config"))
+ config := false
+ if len(data) > 0 {
+ config = true
+ }
+ return &UpspinService{
+ Configured: config,
+ User: data["username"],
+ Dir: data["dirserver"],
+ Store: data["storeserver"],
+ Seed: "",
+ }, nil
+}
diff --git a/nichrome/cmds/upspinsos/upspin_sos.go b/nichrome/cmds/upspinsos/upspin_sos.go
new file mode 100644
index 000000000..e8cf3575b
--- /dev/null
+++ b/nichrome/cmds/upspinsos/upspin_sos.go
@@ -0,0 +1,17 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "log"
+)
+
+func main() {
+ service, err := NewUpspinService()
+ if err != nil {
+ log.Fatal(err)
+ }
+ NewUpspinServer(service).Start()
+}
diff --git a/nichrome/cmds/wifi/server.go b/nichrome/cmds/wifi/server.go
new file mode 100644
index 000000000..423e53047
--- /dev/null
+++ b/nichrome/cmds/wifi/server.go
@@ -0,0 +1,295 @@
+// Copyright 2017 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+
+ "github.com/gorilla/mux"
+ "github.com/u-root/NiChrome/pkg/sos"
+ "github.com/u-root/NiChrome/pkg/wifi"
+)
+
+const (
+ DefHtmlPage = `
+
+
+
+
+
+{{$NoEnc := 0}}
+{{$WpaPsk := 1}}
+{{$WpaEap := 2}}
+{{$connectedEssid := .ConnectedEssid}}
+{{$connectingEssid := .ConnectingEssid}}
+Please choose your Wifi
+
+
+{{if and (ne $connectingEssid "") (ne $connectingEssid $connectedEssid) }}
+
+{{end}}
+
+`
+)
+
+var (
+ Port uint
+)
+
+type WifiServer struct {
+ service *WifiService
+}
+
+func userInputValidation(essid, pass, id string) ([]string, error) {
+ switch {
+ case essid != "" && pass != "" && id != "":
+ return []string{essid, pass, id}, nil
+ case essid != "" && pass != "" && id == "":
+ return []string{essid, pass}, nil
+ case essid != "" && pass == "" && id == "":
+ return []string{essid}, nil
+ default:
+ return nil, fmt.Errorf("Invalid user input")
+ }
+}
+
+func (ws WifiServer) refreshHandle(w http.ResponseWriter, r *http.Request) {
+ if err := ws.service.Refresh(); err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ json.NewEncoder(w).Encode(nil)
+}
+
+type ConnectJsonMsg struct {
+ Essid string
+ Pass string
+ Id string
+}
+
+func (ws WifiServer) connectHandle(w http.ResponseWriter, r *http.Request) {
+ var msg ConnectJsonMsg
+ decoder := json.NewDecoder(r.Body)
+ defer r.Body.Close()
+ if err := decoder.Decode(&msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ a, err := userInputValidation(msg.Essid, msg.Pass, msg.Id)
+ if err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+
+ if err := ws.service.Connect(a); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ // Connect Successful
+ json.NewEncoder(w).Encode(nil)
+}
+
+func (ws WifiServer) displayStateHandle(w http.ResponseWriter, r *http.Request) {
+ s := ws.service.GetState()
+ displayWifi(w, s.NearbyWifis, s.CurEssid, s.ConnectingEssid)
+}
+
+func (ws WifiServer) buildRouter() *mux.Router {
+ r := mux.NewRouter()
+ r.HandleFunc("/", ws.displayStateHandle).Methods("GET")
+ r.HandleFunc("/refresh", ws.refreshHandle).Methods("POST")
+ r.HandleFunc("/connect", ws.connectHandle).Methods("POST")
+ r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(sos.HTMLPath("css")))))
+ return r
+}
+
+func (ws WifiServer) Start() {
+ defer ws.service.Shutdown()
+ listener, port, err := sos.GetListener()
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ Port = port
+ fmt.Println(sos.StartServiceServer(ws.buildRouter(), "wifi", listener, Port))
+}
+
+func displayWifi(wr io.Writer, wifiOpts []wifi.Option, connectedEssid, connectingEssid string) error {
+ wifiData := struct {
+ WifiOpts []wifi.Option
+ ConnectedEssid string
+ ConnectingEssid string
+ Port uint
+ }{wifiOpts, connectedEssid, connectingEssid, Port}
+
+ var tmpl *template.Template
+ file, err := ioutil.ReadFile(sos.HTMLPath("wifi.html"))
+ if err == nil {
+ html := string(file)
+ tmpl = template.Must(template.New("name").Parse(html))
+ } else {
+ tmpl = template.Must(template.New("name").Parse(DefHtmlPage))
+ }
+ return tmpl.Execute(wr, wifiData)
+}
+
+func NewWifiServer(service *WifiService) *WifiServer {
+ return &WifiServer{
+ service: service,
+ }
+}
diff --git a/nichrome/cmds/wifi/server_test.go b/nichrome/cmds/wifi/server_test.go
new file mode 100644
index 000000000..5bc6436b7
--- /dev/null
+++ b/nichrome/cmds/wifi/server_test.go
@@ -0,0 +1,298 @@
+// Copyright 2017 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "math/rand"
+ "net/http"
+ "net/http/httptest"
+ "reflect"
+ "sync"
+ "testing"
+)
+
+type UserInputValidationTestcase struct {
+ name string
+ essid string
+ pass string
+ id string
+ exp []string
+ err error
+}
+
+var (
+ EssidStub = "stub"
+ IdStub = "stub"
+ PassStub = "123456789"
+
+ userInputValidationTestcases = []UserInputValidationTestcase{
+ {
+ name: "Essid, passphrase, Id",
+ essid: EssidStub,
+ pass: PassStub,
+ id: IdStub,
+ exp: []string{EssidStub, PassStub, IdStub},
+ err: nil,
+ },
+ {
+ name: "Essid, passphrase",
+ essid: EssidStub,
+ pass: PassStub,
+ id: "",
+ exp: []string{EssidStub, PassStub},
+ err: nil,
+ },
+ {
+ name: "Essid",
+ essid: EssidStub,
+ pass: "",
+ id: "",
+ exp: []string{EssidStub},
+ err: nil,
+ },
+ {
+ name: "No Essid",
+ essid: "",
+ pass: PassStub,
+ id: IdStub,
+ exp: nil,
+ err: fmt.Errorf("Invalid user input"),
+ },
+ {
+ name: "Essid, Id",
+ essid: EssidStub,
+ pass: "",
+ id: IdStub,
+ exp: nil,
+ err: fmt.Errorf("Invalid user input"),
+ },
+ }
+)
+
+func TestUserInputValidation(t *testing.T) {
+ for _, test := range userInputValidationTestcases {
+ out, err := userInputValidation(test.essid, test.pass, test.id)
+ if !reflect.DeepEqual(err, test.err) || !reflect.DeepEqual(out, test.exp) {
+ t.Logf("TEST %v", test.name)
+ fncCall := fmt.Sprintf("userInputValidation(%v, %v, %v)", test.essid, test.pass, test.id)
+ t.Errorf("%s\ngot:[%v, %v]\nwant:[%v, %v]", fncCall, out, err, test.exp, test.err)
+ }
+ }
+}
+
+func setupStubServer() (*WifiServer, error) {
+ service, err := setupStubService()
+ if err != nil {
+ return nil, err
+ }
+ service.Start()
+ return NewWifiServer(service), nil
+}
+
+func TestConnectHandlerSuccess(t *testing.T) {
+ // Set Up
+ server, err := setupStubServer()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer server.service.Shutdown()
+ router := server.buildRouter()
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+ m := ConnectJsonMsg{EssidStub, PassStub, IdStub}
+ b, err := json.Marshal(m)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ req, err := http.NewRequest("POST", ts.URL+"/connect", bytes.NewBuffer(b))
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Execute
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ // Assert
+ decoder := json.NewDecoder(res.Body)
+ defer res.Body.Close()
+ var retMsg struct{ Error string }
+ if err := decoder.Decode(&retMsg); err != nil {
+ t.Errorf("Error Decode JSON Response")
+ return
+ }
+ // nil in response
+ if retMsg != struct{ Error string }{} {
+ t.Errorf("\ngot:%v\nwant:%v", retMsg, struct{ Error string }{})
+ return
+ }
+ // Check for State change
+ state := server.service.GetState()
+ if state.CurEssid != EssidStub {
+ t.Errorf("\ngot:%v\nwant:%v", state.CurEssid, EssidStub)
+ }
+}
+
+func TestConnectHandlerFail(t *testing.T) {
+ // Set Up
+ server, err := setupStubServer()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer server.service.Shutdown()
+ router := server.buildRouter()
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+ m := ConnectJsonMsg{EssidStub, "", IdStub}
+ b, err := json.Marshal(m)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ req, err := http.NewRequest("POST", ts.URL+"/connect", bytes.NewBuffer(b))
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Execute
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ // Assert
+ decoder := json.NewDecoder(res.Body)
+ defer res.Body.Close()
+ var retMsg struct{ Error string }
+ if err := decoder.Decode(&retMsg); err != nil {
+ t.Errorf("Error Decode JSON Response")
+ return
+ }
+ // Error message in response
+ if retMsg != struct{ Error string }{"Invalid user input"} {
+ t.Errorf("\ngot:%v\nwant:%v", retMsg, struct{ Error string }{})
+ return
+ }
+}
+
+func TestRefreshHandler(t *testing.T) {
+ // Set Up
+ server, err := setupStubServer()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer server.service.Shutdown()
+ router := server.buildRouter()
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+ req, err := http.NewRequest("POST", ts.URL+"/refresh", nil)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Execute
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Assert
+ decoder := json.NewDecoder(res.Body)
+ defer res.Body.Close()
+ var retMsg struct{ Error string }
+ if err := decoder.Decode(&retMsg); err != nil {
+ t.Errorf("Error Decode JSON Response")
+ return
+ }
+ // nil in response
+ if retMsg != struct{ Error string }{} {
+ t.Errorf("\ngot:%v\nwant:%v", retMsg, struct{ Error string }{})
+ return
+ }
+}
+
+func TestHandlersRace(t *testing.T) {
+ // Set Up
+ numConnectRoutines, numRefreshGoRoutines, numReadGoRoutines := 10, 10, 100
+ server, err := setupStubServer()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer server.service.Shutdown()
+ router := server.buildRouter()
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+
+ essidChoices := []string{"stub1", "stub2", "stub3"}
+
+ // Execute
+ var wg sync.WaitGroup
+
+ for i := 0; i < numConnectRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ idx := rand.Intn(len(essidChoices))
+ m := ConnectJsonMsg{essidChoices[idx], "", ""}
+ b, err := json.Marshal(m)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ req, err := http.NewRequest("POST", ts.URL+"/connect", bytes.NewBuffer(b))
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ if _, err = http.DefaultClient.Do(req); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ }()
+ }
+
+ for i := 0; i < numRefreshGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ req, err := http.NewRequest("POST", ts.URL+"/refresh", nil)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ if _, err = http.DefaultClient.Do(req); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ }()
+ }
+
+ for i := 0; i < numReadGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ req, err := http.NewRequest("GET", ts.URL+"/", nil)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ if _, err = http.DefaultClient.Do(req); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ }()
+ }
+ wg.Wait()
+}
diff --git a/nichrome/cmds/wifi/service.go b/nichrome/cmds/wifi/service.go
new file mode 100644
index 000000000..6d543c21e
--- /dev/null
+++ b/nichrome/cmds/wifi/service.go
@@ -0,0 +1,224 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+
+ "github.com/u-root/NiChrome/pkg/wifi"
+)
+
+// Exported Constants
+
+var (
+ DefaultBufferSize = 4
+)
+
+// Exported Types
+
+type State struct {
+ CurEssid string
+ ConnectingEssid string
+ Refreshing bool
+ NearbyWifis []wifi.Option
+}
+
+type ConnectReqMsg struct {
+ // private channel that the requesting routine is listening on
+ c chan (error)
+ args []string
+}
+
+type RefreshReqMsg chan error
+
+type StateReqMsg chan State
+
+type WifiService struct {
+ // Share Resource between goroutines
+ wifiWorker wifi.WiFi
+
+ // Communicating Channels between internal goroutines
+ connectArbitratorQuit chan bool
+ refreshPoolerQuit chan bool
+ stateTrackerQuit chan bool
+ stateUpdateChan chan stateUpdateMsg
+
+ // Communicating Channels with Server goroutines
+ connectReqChan chan ConnectReqMsg
+ refreshReqChan chan RefreshReqMsg
+ stateReqChan chan StateReqMsg
+}
+
+// Internal type
+
+type stateComponent int
+
+const (
+ curEssidComp stateComponent = iota
+ connectingEssidComp
+ refreshingComp
+ nearbyWifisComp
+)
+
+type stateUpdateMsg struct {
+ key stateComponent
+ val interface{}
+ doneUpdate chan bool // Used when need to ensure happening before relationship
+
+}
+
+func (ws WifiService) startConnectWifiArbitrator() {
+ curEssid, connectingEssid := "", ""
+ workDone := make(chan error, 1)
+ var winningChan chan error
+ for {
+ select {
+ case req := <-ws.connectReqChan:
+ if connectingEssid == "" {
+ // The requesting routine wins
+ connectingEssid = req.args[0]
+ ws.stateUpdateChan <- stateUpdateMsg{connectingEssidComp, connectingEssid, nil}
+ winningChan = req.c
+ // Starts connection
+ go func(args ...string) {
+ workDone <- ws.wifiWorker.Connect(args...)
+ }(req.args...)
+ } else {
+ // The requesting routine loses
+ req.c <- fmt.Errorf("Service is trying to connect to %s", connectingEssid)
+ }
+ case err := <-workDone:
+ // Update states
+ if err != nil {
+ curEssid, _ = ws.wifiWorker.GetID()
+ } else {
+ curEssid = connectingEssid
+ }
+ doneUpdate := make(chan bool, 2)
+ ws.stateUpdateChan <- stateUpdateMsg{curEssidComp, curEssid, doneUpdate}
+ connectingEssid = ""
+ ws.stateUpdateChan <- stateUpdateMsg{connectingEssidComp, connectingEssid, doneUpdate}
+ <-doneUpdate
+ <-doneUpdate
+ winningChan <- err
+ case <-ws.connectArbitratorQuit:
+ return
+ }
+ }
+}
+
+func (ws WifiService) startRefreshPooler() {
+ workDone := make(chan bool, 1)
+ pool := make(chan RefreshReqMsg, DefaultBufferSize)
+ refreshing := false
+ // Pooler
+ for {
+ select {
+ case req := <-ws.refreshReqChan:
+ if !refreshing {
+ refreshing = true
+ ws.stateUpdateChan <- stateUpdateMsg{refreshingComp, refreshing, nil}
+
+ // Notifier
+ go func(p chan RefreshReqMsg) {
+ o, err := ws.wifiWorker.Scan()
+ doneUpdate := make(chan bool, 1)
+ ws.stateUpdateChan <- stateUpdateMsg{nearbyWifisComp, o, doneUpdate}
+ <-doneUpdate
+ workDone <- true
+ for ch := range p {
+ ch <- err
+ }
+ }(pool)
+ }
+ pool <- req
+ case <-workDone:
+ close(pool)
+ refreshing = false
+ ws.stateUpdateChan <- stateUpdateMsg{refreshingComp, refreshing, nil}
+ pool = make(chan RefreshReqMsg, DefaultBufferSize)
+ case <-ws.refreshPoolerQuit:
+ return
+ }
+ }
+}
+
+func (ws WifiService) startStateTracker() {
+ state := State{
+ CurEssid: "",
+ ConnectingEssid: "",
+ Refreshing: false,
+ NearbyWifis: nil,
+ }
+ for {
+ select {
+ case r := <-ws.stateReqChan:
+ r <- state
+ case updateMsg := <-ws.stateUpdateChan:
+ updateState(&state, updateMsg)
+ if updateMsg.doneUpdate != nil {
+ updateMsg.doneUpdate <- true
+ }
+ case <-ws.stateTrackerQuit:
+ return
+ }
+ }
+}
+
+func updateState(state *State, update stateUpdateMsg) {
+ switch update.key {
+ case curEssidComp:
+ state.CurEssid = update.val.(string)
+ case connectingEssidComp:
+ state.ConnectingEssid = update.val.(string)
+ case refreshingComp:
+ state.Refreshing = update.val.(bool)
+ case nearbyWifisComp:
+ state.NearbyWifis = update.val.([]wifi.Option)
+ }
+}
+
+func NewWifiService(w wifi.WiFi) (*WifiService, error) {
+ return &WifiService{
+ wifiWorker: w,
+ connectArbitratorQuit: make(chan bool, 1),
+ refreshPoolerQuit: make(chan bool, 1),
+ stateTrackerQuit: make(chan bool, 1),
+ stateUpdateChan: make(chan stateUpdateMsg, 4),
+ connectReqChan: make(chan ConnectReqMsg, DefaultBufferSize),
+ refreshReqChan: make(chan RefreshReqMsg, DefaultBufferSize),
+ stateReqChan: make(chan StateReqMsg, DefaultBufferSize),
+ }, nil
+}
+
+func (ws WifiService) Start() {
+ go ws.startConnectWifiArbitrator()
+ go ws.startRefreshPooler()
+ go ws.startStateTracker()
+}
+
+func (ws WifiService) Shutdown() {
+ ws.connectArbitratorQuit <- true
+ ws.refreshPoolerQuit <- true
+ ws.stateTrackerQuit <- true
+}
+
+func (ws WifiService) GetState() State {
+ c := make(chan State, 1)
+ ws.stateReqChan <- (c)
+ return <-c
+}
+
+func (ws WifiService) Connect(args []string) error {
+ c := make(chan error, 1)
+ ws.connectReqChan <- ConnectReqMsg{c, args}
+ return <-c
+}
+
+func (ws WifiService) Refresh() error {
+ c := make(chan error, 1)
+ ws.refreshReqChan <- (c)
+ return <-c
+}
diff --git a/nichrome/cmds/wifi/service_test.go b/nichrome/cmds/wifi/service_test.go
new file mode 100644
index 000000000..7d6757da8
--- /dev/null
+++ b/nichrome/cmds/wifi/service_test.go
@@ -0,0 +1,208 @@
+// Copyright 2017 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "math/rand"
+ "reflect"
+ "sync"
+ "testing"
+
+ "github.com/u-root/NiChrome/pkg/wifi"
+)
+
+func setupStubService() (*WifiService, error) {
+ wifiWorker, err := wifi.NewStubWorker("", NearbyWifisStub...)
+ if err != nil {
+ return nil, err
+ }
+ return NewWifiService(wifiWorker)
+}
+
+func TestGetState(t *testing.T) {
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+ service.Start()
+ defer service.Shutdown()
+
+ expectedInitialState := State{
+ CurEssid: "",
+ ConnectingEssid: "",
+ Refreshing: false,
+ NearbyWifis: nil,
+ }
+ state := service.GetState()
+ if !reflect.DeepEqual(expectedInitialState, state) {
+ t.Errorf("\ngot:%v\nwant:%v\n", state, expectedInitialState)
+ }
+}
+
+func TestRaceGetState(t *testing.T) {
+ // Set Up
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+ service.Start()
+ defer service.Shutdown()
+ numGoRoutines := 100
+
+ var wg sync.WaitGroup
+ for i := 0; i < numGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ service.GetState()
+ }()
+ }
+ wg.Wait()
+}
+
+func TestConnect(t *testing.T) {
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+ service.Start()
+ defer service.Shutdown()
+
+ if err := service.Connect([]string{EssidStub}); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ s := service.GetState()
+ if s.CurEssid != EssidStub {
+ t.Errorf("\ngot:%v\nwant:%v\n", s.CurEssid, EssidStub)
+ }
+}
+
+func TestRaceConnect(t *testing.T) {
+ //Set Up
+ numGoRoutines := 100
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ service.Start()
+ defer service.Shutdown()
+
+ var wg sync.WaitGroup
+ for i := 0; i < numGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ service.Connect([]string{EssidStub})
+ }()
+ }
+ wg.Wait()
+}
+
+func TestRefresh(t *testing.T) {
+ //Set Up
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+ service.Start()
+ defer service.Shutdown()
+
+ if err := service.Refresh(); err != nil {
+ t.Fatalf("Refresh: error: %v", err)
+ }
+ s := service.GetState()
+ if !reflect.DeepEqual(s.NearbyWifis, NearbyWifisStub) {
+ t.Errorf("\ngot:%v\nwant:%v\n", s.NearbyWifis, NearbyWifisStub)
+ }
+}
+
+func TestRaceRefreshWithinDefaultBufferSize(t *testing.T) {
+ //Set Up
+ numGoRoutines := DefaultBufferSize
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ service.Start()
+ defer service.Shutdown()
+
+ var wg sync.WaitGroup
+ for i := 0; i < numGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ service.Refresh()
+ }()
+ }
+ wg.Wait()
+}
+
+func TestRaceRefreshOverDefaultBufferSize(t *testing.T) {
+ // Set Up
+ numGoRoutines := DefaultBufferSize * 2
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ service.Start()
+ defer service.Shutdown()
+
+ var wg sync.WaitGroup
+ for i := 0; i < numGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ service.Refresh()
+ }()
+ }
+ wg.Wait()
+}
+
+func TestRaceCond(t *testing.T) {
+ // Set Up
+ numConnectRoutines, numRefreshGoRoutines, numReadGoRoutines := 10, 10, 100
+ service, err := setupStubService()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ service.Start()
+ defer service.Shutdown()
+
+ essidChoices := []string{"stub1", "stub2", "stub3"}
+
+ var wg sync.WaitGroup
+
+ for i := 0; i < numConnectRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ idx := rand.Intn(len(essidChoices))
+ service.Connect([]string{essidChoices[idx]})
+ }()
+ }
+
+ for i := 0; i < numRefreshGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ service.Refresh()
+ }()
+ }
+
+ for i := 0; i < numReadGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ service.GetState()
+ }()
+ }
+
+ wg.Wait()
+}
diff --git a/nichrome/cmds/wifi/wifi.go b/nichrome/cmds/wifi/wifi.go
new file mode 100644
index 000000000..0bedecf03
--- /dev/null
+++ b/nichrome/cmds/wifi/wifi.go
@@ -0,0 +1,146 @@
+// Copyright 2017 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "regexp"
+ "strings"
+
+ "github.com/u-root/NiChrome/pkg/wifi"
+)
+
+const (
+ cmd = "wifi [options] essid [passphrase] [identity]"
+)
+
+var (
+ // flags
+ iface = flag.String("i", "wlan0", "interface to use")
+ list = flag.Bool("l", false, "list all nearby WiFi")
+ show = flag.Bool("s", false, "list interfaces allowed with WiFi extension")
+ test = flag.Bool("test", false, "set up a test server")
+ wType = flag.String("worker", "iwl", "What kind of wireless layer to use")
+
+ // RegEx for parsing iwconfig output
+ iwconfigRE = regexp.MustCompile("(?m)^[a-zA-Z0-9]+\\s*IEEE 802.11.*$")
+
+ // Stub data for simple end-to-end interaction test
+ NearbyWifisStub = []wifi.Option{
+ {"Stub1", wifi.NoEnc},
+ {"Stub2", wifi.WpaPsk},
+ {"Stub3", wifi.WpaEap},
+ {"Stub4", wifi.NotSupportedProto},
+ }
+ workers = map[string]func(string) (wifi.WiFi, error){
+ "iwl": wifi.NewIWLWorker,
+ "native": wifi.NewNativeWorker,
+ }
+)
+
+func parseIwconfig(o []byte) (res []string) {
+ interfaces := iwconfigRE.FindAll(o, -1)
+ for _, i := range interfaces {
+ res = append(res, strings.Split(string(i), " ")[0])
+ }
+ return
+}
+
+func init() {
+ defUsage := flag.Usage
+ flag.Usage = func() {
+ os.Args[0] = cmd
+ defUsage()
+ }
+}
+
+func main() {
+ flag.Parse()
+
+ // Start a Server with Stub data
+ // for manual end-to-end testing
+ // This is probably in need of a change.
+ if *test {
+ worker, err := wifi.NewStubWorker("", NearbyWifisStub...)
+ if err != nil {
+ log.Fatal(err)
+ }
+ service, err := NewWifiService(worker)
+ if err != nil {
+ log.Fatal(err)
+ }
+ service.Start()
+ NewWifiServer(service).Start() // this function shutdown service upon return
+ return
+ }
+
+ if *show {
+ o, err := exec.Command("iwconfig").CombinedOutput()
+ if err != nil {
+ log.Fatalf("iwconfig: %v (%v)", string(o), err)
+ }
+ for _, i := range parseIwconfig(o) {
+ fmt.Println(i)
+ }
+ return
+ }
+
+ f, ok := workers[*wType]
+ if !ok {
+ log.Fatalf("%v: not in %v", *wType, workers)
+ }
+ worker, err := f(*iface)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if *list {
+ wifiOpts, err := worker.Scan()
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ for _, wifiOpt := range wifiOpts {
+ switch wifiOpt.AuthSuite {
+ case wifi.NoEnc:
+ fmt.Printf("%s: No Passphrase\n", wifiOpt.Essid)
+ case wifi.WpaPsk:
+ fmt.Printf("%s: WPA-PSK (only passphrase)\n", wifiOpt.Essid)
+ case wifi.WpaEap:
+ fmt.Printf("%s: WPA-EAP (passphrase and identity)\n", wifiOpt.Essid)
+ case wifi.NotSupportedProto:
+ fmt.Printf("%s: Not a supported protocol\n", wifiOpt.Essid)
+ }
+ }
+ return
+ }
+
+ a := flag.Args()
+ if len(a) > 3 {
+ flag.Usage()
+ os.Exit(1)
+ }
+
+ // Experimental Part
+ if len(a) == 0 {
+ if o, err := exec.Command("ip", "link", "set", "dev", "lo", "up").CombinedOutput(); err != nil {
+ log.Fatalf("ip link set dev lo: %v (%v)", string(o), err)
+ }
+ service, err := NewWifiService(worker)
+ if err != nil {
+ log.Fatal(err)
+ }
+ service.Start()
+ go service.Refresh()
+ NewWifiServer(service).Start() // this function shutdown service upon return
+ return
+ }
+
+ if err := worker.Connect(a...); err != nil {
+ log.Fatalf("error: %v", err)
+ }
+}
diff --git a/nichrome/cmds/wifi/wifi_test.go b/nichrome/cmds/wifi/wifi_test.go
new file mode 100644
index 000000000..4e2bc9e4d
--- /dev/null
+++ b/nichrome/cmds/wifi/wifi_test.go
@@ -0,0 +1,109 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestIwconfigRE(t *testing.T) {
+ testcases := []struct {
+ s string
+ exp bool
+ }{
+ {"blahblahblah\nlo no wireless extensions.\n", false},
+ {"blahblahblah\nwlp4s0 IEEE 802.11 ESSID:\"stub\"", true},
+ {"blahblahblah\n Mode:Managed Frequency:5.58 GHz Access Point: 00:00:00:00:00:00\n", false},
+ }
+ for _, test := range testcases {
+ if out := iwconfigRE.MatchString(test.s); out != test.exp {
+ t.Errorf("%s\ngot:%v\nwant:%v", test.s, out, test.exp)
+ }
+ }
+}
+
+func TestParseIwconfig(t *testing.T) {
+ testcases := []struct {
+ name string
+ o []byte
+ exp []string
+ }{
+ {
+ name: "nil input",
+ o: nil,
+ exp: nil,
+ },
+ {
+ name: "empty string input",
+ o: []byte(""),
+ exp: nil,
+ },
+ {
+ name: "No Wireless in input",
+ o: []byte(`
+lo no wireless extensions.
+
+eno1 no wireless extensions.
+
+`),
+ exp: nil,
+ },
+ {
+ name: "One (1) Wireless extension",
+ o: []byte(`
+wlp4s0 IEEE 802.11 ESSID:"stub"
+ Mode:Managed Frequency:5.58 GHz Access Point: 00:00:00:00:00:00
+ Bit Rate=22 Mb/s Tx-Power=22 dBm
+ Retry short limit:7 RTS thr:off Fragment thr:off
+ Power Management:on
+ Link Quality=27/70 Signal level=-53 dBm
+ Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
+ Tx excessive retries:0 Invalid misc:0 Missed beacon:0
+
+lo no wireless extensions.
+
+enp0s31f6 no wireless extensions.
+
+`),
+ exp: []string{"wlp4s0"},
+ },
+ {
+ name: "Two (2) Wireless extensions",
+ o: []byte(`
+wlp4s0 IEEE 802.11 ESSID:"stub"
+ Mode:Managed Frequency:5.58 GHz Access Point: 00:00:00:00:00:00
+ Bit Rate=22 Mb/s Tx-Power=22 dBm
+ Retry short limit:7 RTS thr:off Fragment thr:off
+ Power Management:on
+ Link Quality=27/70 Signal level=-53 dBm
+ Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
+ Tx excessive retries:0 Invalid misc:0 Missed beacon:0
+
+wlp4s1 IEEE 802.11 ESSID:"stub"
+ Mode:Managed Frequency:5.58 GHz Access Point: 00:00:00:00:00:00
+ Bit Rate=22 Mb/s Tx-Power=22 dBm
+ Retry short limit:7 RTS thr:off Fragment thr:off
+ Power Management:on
+ Link Quality=27/70 Signal level=-53 dBm
+ Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
+ Tx excessive retries:0 Invalid misc:0 Missed beacon:0
+
+lo no wireless extensions.
+
+enp0s31f6 no wireless extensions.
+
+`),
+ exp: []string{"wlp4s0", "wlp4s1"},
+ },
+ }
+
+ for _, test := range testcases {
+ out := parseIwconfig(test.o)
+ if !reflect.DeepEqual(out, test.exp) {
+ t.Errorf("%v\ngot:%v\nwant:%v", test.name, out, test.exp)
+ }
+ }
+}
diff --git a/nichrome/cmds/xinit/xinit.go b/nichrome/cmds/xinit/xinit.go
new file mode 100644
index 000000000..d30e78baf
--- /dev/null
+++ b/nichrome/cmds/xinit/xinit.go
@@ -0,0 +1,63 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "time"
+)
+
+func x11(n string, args ...string) error {
+ cmd := exec.Command(n, args...)
+ cmd.Env = append(os.Environ(), "DISPLAY=:0")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("X11 start %v %v: %v", n, args, err)
+ }
+ return nil
+}
+
+func setup() error {
+ if err := os.Symlink("/usr/local/bin/bash", "/bin/bash"); err != nil {
+ return err
+ }
+ if err := os.Symlink("/lib/ld-linux-x86-64.so.2", "/lib64/ld-linux-x86-64.so.2"); err != nil {
+ return err
+ }
+ go func() {
+ cmd := exec.Command("Xfbdev")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ log.Fatalf("X11 startup: %v", err)
+ }
+ }()
+ for {
+ s, err := filepath.Glob("/tmp/.X*/X?")
+ if err != nil {
+ return err
+ }
+ if len(s) > 0 {
+ break
+ }
+ time.Sleep(time.Second)
+ }
+ for _, f := range []string{"wingo", "flwm", "chrome"} {
+ log.Printf("Run %v", f)
+ go x11(f)
+ }
+
+ // we block on the aterm. When the aterm exits, we do too.
+ return x11("aterm")
+}
+
+func main() {
+ if err := setup(); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/nichrome/examples/sos/README.md b/nichrome/examples/sos/README.md
new file mode 100644
index 000000000..fa6aed29a
--- /dev/null
+++ b/nichrome/examples/sos/README.md
@@ -0,0 +1,31 @@
+# Example Service for Service of Services
+
+the Service of Services (SoS) is a web-based UI for configuring system settings, on localhost:8000. There are a number of services in u-root by default, but you can easily build your own.
+
+An SoS service consists of a number of files:
+* `your_sos.go` contains main() and starts your service, in `cmds/your_sos`
+* `service.go` contains all the functionality of your service, in `cmds/your_sos`
+* `server.go` routes data between the webpage and the service, in `cmds/your_sos`
+* `your_sos.html`, the HTML and Javascript frontend, placed in `pkg/sos/html`
+
+The logic in service.go is heavily dependent on what you are trying to implement, but everything else follows this general pattern:
+1. main constructs a new service, passes it to a new server, and starts the server.
+2. the server gets a port from the SoS, builds its router, and adds itself to the SoS table.
+3. the server's router maps URLs to user-defined Go functions.
+4. the server's displayStateHandle function updates the service and renders the webpage with service data.
+5. the webpage contains input fields, which are sent back as JSON through URLs defined in the router.
+6. The server's router passes the JSON to a Go function, which it decodes and sends to a service method.
+7. The service method operates on this input, updating its fields once it's done.
+8. The webpage reloads on completion, rerendering with the updated service data.
+
+the example Service in this dir is heavily commented with more details.
+
+To start a service on startup, call it in your uinit.
+
+To test services on your build machine:
+1. navigate to `cmds/sos`, run `go build .`, then `sudo ./sos`
+2. navigate to your service, `cmds/your_sos`, run `go build .`, then `./your_sos`
+
+You can then open the SoS table in a browser at localhost:8000 and access your service.
+This will use the builtin HTML string, not your HTML file, due to path issues. Until we
+implement a flag, you can manually change `htmlRoot` in `pkg/sos/server.go` and rebuild sos.
diff --git a/nichrome/examples/sos/example_sos.go b/nichrome/examples/sos/example_sos.go
new file mode 100644
index 000000000..7ba8c30a9
--- /dev/null
+++ b/nichrome/examples/sos/example_sos.go
@@ -0,0 +1,19 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "log"
+)
+
+func main() {
+ // Build a new example service
+ service, err := NewExampleService()
+ if err != nil {
+ log.Fatal(err)
+ }
+ // Build a new example server with this service, then start it
+ NewExampleServer(service).Start()
+}
diff --git a/nichrome/examples/sos/example_sos.html b/nichrome/examples/sos/example_sos.html
new file mode 100644
index 000000000..045c9212c
--- /dev/null
+++ b/nichrome/examples/sos/example_sos.html
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+ {{$example := .Example}}
+ Example
+
+
+
+
diff --git a/nichrome/examples/sos/server.go b/nichrome/examples/sos/server.go
new file mode 100644
index 000000000..3b4246a63
--- /dev/null
+++ b/nichrome/examples/sos/server.go
@@ -0,0 +1,202 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "encoding/json"
+ "html/template"
+ "io/ioutil"
+ "log"
+ "net/http"
+
+ "github.com/gorilla/mux"
+ "github.com/u-root/NiChrome/pkg/sos"
+)
+
+const (
+ // it's ugly, but we have to define a basic HTML string to fall back on if our .html is
+ // missing. If you are implementing a simple service, you may be able to get away with
+ // only this. example_sos.html is exactly the same as this string, except we use divs
+ // and the CSS stylesheet instead of tables, with more documentation.
+ DefHtmlPage = `
+
+
+
+
+
+ {{$example := .Example}}
+ Example
+
+
+ `
+)
+
+var Port uint
+
+// our server contains an instance of our service.
+type ExampleServer struct {
+ service *ExampleService
+}
+
+// displayStateHandle renders our webpage with the data from our service
+// * update your service (if required).
+// * copy your service's fields to a data struct, with the port we got from SoS.
+// * load the HTML file. If it doesn't exist, use the HTML string defined above.
+// * Render the HTML with our data.
+func (es *ExampleServer) displayStateHandle(w http.ResponseWriter, r *http.Request) {
+ // if your service has an update function, call it here to refresh its fields.
+ // es.service.Update()
+ exampleData := struct {
+ Example string
+ Port uint
+ }{es.service.Example, Port}
+ var tmpl *template.Template
+ file, err := ioutil.ReadFile(sos.HTMLPath("example.html"))
+ if err == nil {
+ html := string(file)
+ tmpl = template.Must(template.New("SoS").Parse(html))
+ } else {
+ tmpl = template.Must(template.New("SoS").Parse(DefHtmlPage))
+ }
+ tmpl.Execute(w, exampleData)
+}
+
+// define a JsonMsg struct for easily passing around our data. Though it isn't
+// necessary in this example, once you have multiple values associated with your
+// service it makes things much easier. This JSON must be defined exactly as it is
+// in the HTML file.
+type ExampleJsonMsg struct {
+ Example string
+}
+
+// this is a basic JSON handler function, dealing with string passed back as JSON.
+// * decode the returned JSON message and store the fields in our JsonMsg struct,
+// with proper error checking.
+// * call the associated service function, passing in this JsonMsg, with proper error checking.
+func (es *ExampleServer) yourHandleFunc1(w http.ResponseWriter, r *http.Request) {
+ var msg ExampleJsonMsg
+ decoder := json.NewDecoder(r.Body)
+ defer r.Body.Close()
+ if err := decoder.Decode(&msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ if err := es.service.ExampleServiceFunc1(msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ json.NewEncoder(w).Encode(nil)
+}
+
+// if your service function doesn't require input, i.e. a button press, you can omit the
+// JSON decoding step.
+func (es *ExampleServer) yourHandleFunc2(w http.ResponseWriter, r *http.Request) {
+ if err := es.service.ExampleServiceFunc2(); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ json.NewEncoder(w).Encode(nil)
+}
+
+// define our router
+// * the "/" handler is required, as it is what updates our service and renders the webpage.
+// * if you plan on using the Material Design CSS in pkg/sos/html/css, you need to define
+// the pathPrefix for it.
+// * All other handlers are user-defined.
+func (es *ExampleServer) buildRouter() *mux.Router {
+ r := mux.NewRouter()
+ r.HandleFunc("/", es.displayStateHandle).Methods("GET")
+ r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(sos.HTMLPath("css")))))
+ r.HandleFunc("/your_url_here_1", es.yourHandleFunc1).Methods("POST")
+ r.HandleFunc("/your_url_here_2", es.yourHandleFunc2).Methods("POST")
+ return r
+}
+
+// start our server
+// * get a listener and an open port from the SoS
+// * build our router (see above) and add our service to the SoS table, with the label "example"
+func (es *ExampleServer) Start() {
+ listener, port, err := sos.GetListener()
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ Port = port
+ sos.StartServiceServer(es.buildRouter(), "example", listener, Port)
+}
+
+// build a new server with the service passed in.
+func NewExampleServer(service *ExampleService) *ExampleServer {
+ return &ExampleServer{
+ service: service,
+ }
+}
diff --git a/nichrome/examples/sos/service.go b/nichrome/examples/sos/service.go
new file mode 100644
index 000000000..db5709f2d
--- /dev/null
+++ b/nichrome/examples/sos/service.go
@@ -0,0 +1,41 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// Your service.go file will be heavily tailored for the problem you are trying to solve.
+// a type representing your service and a constructor for that service are all that is
+// specifically required. If you are depending on something outside of the program, such
+// as text files or system settings, add an update function which loads that data into your
+// service struct.
+
+// the one field in our example service is a string, set by the user.
+type ExampleService struct {
+ Example string
+}
+
+// here is where you'd define an update function. Since this demo does not depend on any
+// system settings, I have omitted it.
+
+// define any service functionality here.
+// ExampleServiceFunc1: Set service variable to input
+func (es *ExampleService) ExampleServiceFunc1(input ExampleJsonMsg) error {
+ es.Example = input.Example
+ return nil
+}
+
+// ExampleServiceFunc2: Reset service variable to empty string
+func (es *ExampleService) ExampleServiceFunc2() error {
+ es.Example = ""
+ return nil
+}
+
+// NewExampleService: construct a new service
+// If your service controls system settings, make a getCurrentSetting() function to
+// initialize your service.
+func NewExampleService() (*ExampleService, error) {
+ return &ExampleService{
+ Example: "",
+ }, nil
+}
diff --git a/nichrome/go.mod b/nichrome/go.mod
new file mode 100644
index 000000000..556f9a6da
--- /dev/null
+++ b/nichrome/go.mod
@@ -0,0 +1,18 @@
+module github.com/u-root/NiChrome
+
+go 1.17
+
+require (
+ github.com/gorilla/mux v1.8.0
+ github.com/spf13/pflag v1.0.5
+ github.com/u-root/u-root v0.0.0-00010101000000-000000000000
+ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
+)
+
+require (
+ github.com/dustin/go-humanize v1.0.0 // indirect
+ github.com/pierrec/lz4/v4 v4.1.11 // indirect
+ golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 // indirect
+)
+
+replace github.com/u-root/u-root => ../u-root
diff --git a/nichrome/go.sum b/nichrome/go.sum
new file mode 100644
index 000000000..c65aa2318
--- /dev/null
+++ b/nichrome/go.sum
@@ -0,0 +1,276 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
+github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/beevik/ntp v0.3.0 h1:xzVrPrE4ziasFXgBVBZJDP0Wg/KpMwk2KHJ4Ba8GrDw=
+github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/cenkalti/backoff/v4 v4.0.2 h1:JIufpQLbh4DkbQoii76ItQIUFzevQSqOLZca4eamEDs=
+github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
+github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
+github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/gliderlabs/ssh v0.1.2-0.20181113160402-cbabf5414432 h1:DGWE1Z/9om1Ny/BvHHIQB81DOzm95VUkTzwmtGtVzK0=
+github.com/gliderlabs/ssh v0.1.2-0.20181113160402-cbabf5414432/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gojuno/minimock/v3 v3.0.4/go.mod h1:HqeqnwV8mAABn3pO5hqF+RE7gjA0jsN8cbbSogoGrzI=
+github.com/gojuno/minimock/v3 v3.0.8/go.mod h1:TPKxc8tiB8O83YH2//pOzxvEjaI3TMhd6ev/GmlMiYA=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
+github.com/google/go-tpm v0.2.1-0.20200615092505-5d8a91de9ae3 h1:aAaYhJmscls+Mps41+Be4fI9ID4siVn5gVFDRDXPJMo=
+github.com/google/go-tpm v0.2.1-0.20200615092505-5d8a91de9ae3/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
+github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0=
+github.com/google/goexpect v0.0.0-20191001010744-5b6988669ffa/go.mod h1:qtE5aAEkt0vOSA84DBh8aJsz6riL8ONfqfULY7lBjqc=
+github.com/google/goterm v0.0.0-20200907032337-555d40f16ae2/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hexdigest/gowrap v1.1.7/go.mod h1:Z+nBFUDLa01iaNM+/jzoOA1JJ7sm51rnYFauKFUB5fs=
+github.com/hexdigest/gowrap v1.1.8/go.mod h1:H/JiFmQMp//tedlV8qt2xBdGzmne6bpbaSuiHmygnMw=
+github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e h1:IQpunlq7T+NiJJMO7ODYV2YWBiv/KnObR3gofX0mWOo=
+github.com/insomniacslk/dhcp v0.0.0-20211209223715-7d93572ebe8e/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
+github.com/intel-go/cpuid v0.0.0-20200819041909-2aa72927c3e2 h1:h+RKaNPjka7LRJGoeub/IQBdXSoEaJjfADkBq02hvjw=
+github.com/intel-go/cpuid v0.0.0-20200819041909-2aa72927c3e2/go.mod h1:RmeVYf9XrPRbRc3XIx0gLYA8qOFvNoPOfaEZduRlEp4=
+github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
+github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
+github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
+github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c h1:7cpGGTQO6+OuYQWkueqeXuErSjs1NZtpALpv1x7Mq4g=
+github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kaey/framebuffer v0.0.0-20140402104929-7b385489a1ff/go.mod h1:tS4qtlcKqtt3tCIHUflVSqeP3CLH5Qtv2szX9X2SyhU=
+github.com/klauspost/compress v1.10.6 h1:SP6zavvTG3YjOosWePXFDlExpKIWMTO4SE/Y8MZB2vI=
+github.com/klauspost/compress v1.10.6/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/pgzip v1.2.4 h1:TQ7CNpYKovDOmqzRHKxJh0BeaBI7UdQZYc6p7pMQh1A=
+github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
+github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
+github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
+github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
+github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
+github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
+github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
+github.com/mdlayher/netlink v1.1.1 h1:VqG+Voq9V4uZ+04vjIrcSCWDpf91B1xxbP4QBUmUJE8=
+github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
+github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
+github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 h1:aFkJ6lx4FPip+S+Uw4aTegFMct9shDvP+79PsSxpm3w=
+github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/orangecms/go-framebuffer v0.0.0-20200613202404-a0700d90c330 h1:zJBTzBuTR7EdFzmCGx0xp0pbOOb82sAh0+YUK4JTDEI=
+github.com/orangecms/go-framebuffer v0.0.0-20200613202404-a0700d90c330/go.mod h1:3Myb/UszJY32F2G7yGkUtcW/ejHpjlGfYLim7cv2uKA=
+github.com/pborman/getopt/v2 v2.1.0 h1:eNfR+r+dWLdWmV8g5OlpyrTYHkhVNxHBdN2cCrJmOEA=
+github.com/pborman/getopt/v2 v2.1.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pierrec/lz4/v4 v4.1.11 h1:LVs17FAZJFOjgmJXl9Tf13WfLUvZq7/RjfEJrnwZ9OE=
+github.com/pierrec/lz4/v4 v4.1.11/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/rck/unit v0.0.3 h1:q3/Ui9gcrFKpEneZXw2gNmNEbzv5jLrZnH6qhX1ypZ0=
+github.com/rck/unit v0.0.3/go.mod h1:jTOnzP4s1OjIP1vdxb4n76b23QPKS4EurYg7sYMr2DM=
+github.com/rekby/gpt v0.0.0-20200219180433-a930afbc6edc h1:goZGTwEEn8mWLcY012VouWZWkJ8GrXm9tS3VORMxT90=
+github.com/rekby/gpt v0.0.0-20200219180433-a930afbc6edc/go.mod h1:scrOqOnnHVKCHENvFw8k9ajCb88uqLQDA4BvuJNJ2ew=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/twitchtv/twirp v5.8.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
+github.com/u-root/gobusybox/src v0.0.0-20210529132627-adc854ea4425/go.mod h1:GlxAKinWMNShbNp8BI+zRr/hUdwNogaNWrnpbh1mOuI=
+github.com/u-root/iscsinl v0.1.1-0.20210528121423-84c32645822a h1:A0sK7WEodak7eVd21MOEatnh2pfAAwZaEPSIEEsjctQ=
+github.com/u-root/iscsinl v0.1.1-0.20210528121423-84c32645822a/go.mod h1:RWIgJWqm9/0gjBZ0Hl8iR6MVGzZ+yAda2uqqLmetE2I=
+github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
+github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7 h1:XMAtQHwKjWHIRwg+8Nj/rzUomQY1q6cM3ncA0wP8GU4=
+github.com/u-root/uio v0.0.0-20210528151154-e40b768296a7/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
+github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
+github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
+github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 h1:8mhqcHPqTMhSPoslhGYihEgSfc77+7La1P6kiB6+9So=
+github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
+github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
+github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
+github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810 h1:X6ps8XHfpQjw8dUStzlMi2ybiKQ2Fmdw7UM+TinwvyM=
+github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810/go.mod h1:dF0BBJ2YrV1+2eAIyEI+KeSidgA6HqoIP1u5XTlMq/o=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200121082415-34d275377bf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4=
+golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 h1:EC6+IGYTjPpRfv9a2b/6Puw0W+hLtAhkV1tPsXhutqs=
+golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+pack.ag/tftp v1.0.1-0.20181129014014-07909dfbde3c h1:4DHuGX0VtxRIyjXlVpcjSGEmZ7OnIK7Hvo+INnxI8yk=
+pack.ag/tftp v1.0.1-0.20181129014014-07909dfbde3c/go.mod h1:N1Pyo5YG+K90XHoR2vfLPhpRuE8ziqbgMn/r/SghZas=
+src.elv.sh v0.16.3 h1:VNTUa0BNNUMtKzd8vpIPK3I8+iEOsyWD2yZvhJMpl/s=
+src.elv.sh v0.16.3/go.mod h1:WxJAMoN8uQcg1ZwRvtjmbYAo6uKeJ8F7b25etVZ743w=
diff --git a/nichrome/home/user/.config/google-chrome/Consent To Send Stats b/nichrome/home/user/.config/google-chrome/Consent To Send Stats
new file mode 100644
index 000000000..9ea7c6f7e
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Consent To Send Stats
@@ -0,0 +1 @@
+e663dba7-466a-43d0-8a03-826b03f69486
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Cookies b/nichrome/home/user/.config/google-chrome/Default/Cookies
new file mode 100644
index 000000000..401f09539
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Cookies differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Cookies-journal b/nichrome/home/user/.config/google-chrome/Default/Cookies-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Current Session b/nichrome/home/user/.config/google-chrome/Default/Current Session
new file mode 100644
index 000000000..e53f9ed78
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Current Session differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Current Tabs b/nichrome/home/user/.config/google-chrome/Default/Current Tabs
new file mode 100644
index 000000000..0627f2659
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Current Tabs differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extension State/000003.log b/nichrome/home/user/.config/google-chrome/Default/Extension State/000003.log
new file mode 100644
index 000000000..5c4f697d0
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Extension State/000003.log differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extension State/CURRENT b/nichrome/home/user/.config/google-chrome/Default/Extension State/CURRENT
new file mode 100644
index 000000000..7ed683d17
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extension State/CURRENT
@@ -0,0 +1 @@
+MANIFEST-000001
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extension State/LOCK b/nichrome/home/user/.config/google-chrome/Default/Extension State/LOCK
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extension State/LOG b/nichrome/home/user/.config/google-chrome/Default/Extension State/LOG
new file mode 100644
index 000000000..c20058da2
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extension State/LOG
@@ -0,0 +1,3 @@
+2018/07/20-17:25:36.214 2887 Reusing MANIFEST /home/user/.config/google-chrome/Default/Extension State/MANIFEST-000001
+2018/07/20-17:25:36.214 2887 Recovering log #3
+2018/07/20-17:25:36.214 2887 Reusing old log /home/user/.config/google-chrome/Default/Extension State/000003.log
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extension State/LOG.old b/nichrome/home/user/.config/google-chrome/Default/Extension State/LOG.old
new file mode 100644
index 000000000..265acbc7b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extension State/LOG.old
@@ -0,0 +1 @@
+2018/07/20-17:13:48.848 2566 Reusing MANIFEST /home/user/.config/google-chrome/Default/Extension State/MANIFEST-000001
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extension State/MANIFEST-000001 b/nichrome/home/user/.config/google-chrome/Default/Extension State/MANIFEST-000001
new file mode 100644
index 000000000..18e5cab72
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Extension State/MANIFEST-000001 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/icon_128.png b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/icon_128.png
new file mode 100644
index 000000000..fefcf61a3
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/icon_128.png differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/icon_16.png b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/icon_16.png
new file mode 100644
index 000000000..443c7125f
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/icon_16.png differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/main.html b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/main.html
new file mode 100644
index 000000000..1d0a501f1
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/main.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/main.js b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/main.js
new file mode 100644
index 000000000..0b1b4944c
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/main.js
@@ -0,0 +1 @@
+document.location.href = "https://docs.google.com/document/create?chromeApp=1";
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/manifest.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/manifest.json
new file mode 100644
index 000000000..76e4e579a
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/aohghmighlieiainnegkcijnfilokake/0.0.0.6_0/manifest.json
@@ -0,0 +1,18 @@
+{
+ "app": {
+ "launch": {
+ "local_path": "main.html"
+ }
+ },
+ "description": "Create, share, and access your Google Docs from anywhere.",
+ "icons": {
+ "128": "icon_128.png",
+ "16": "icon_16.png"
+ },
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJhLK6fk/BWTEvJhywpk7jDe4A2r0bGXGOLZW4/AdBp3IiD9o9nx4YjLAtv0tIPxi7MvFd/GUUbQBwHT5wQWONJj1z/0Rc2qBkiJA0yqXh42p0snuA8dCfdlhOLsp7/XTMEwAVasjV5hC4awl78eKfJYlZ+8fM/UldLWJ/51iBQwIDAQAB",
+ "manifest_version": 2,
+ "name": "Docs",
+ "offline_enabled": true,
+ "update_url": "http://clients2.google.com/service/update2/crx",
+ "version": "0.0.0.6"
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/128.png b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/128.png
new file mode 100644
index 000000000..d2496fbea
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/128.png differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ar/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ar/messages.json
new file mode 100644
index 000000000..e9e3db6e1
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ar/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: إنشاء ومشاركة وحفظ جميع أشيائك في مكان واحد."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/bg/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/bg/messages.json
new file mode 100644
index 000000000..cffb8adfd
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/bg/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Диск: създавайте, споделяйте и пазете всичките си неща на едно място."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Диск"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ca/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ca/messages.json
new file mode 100644
index 000000000..1c91aac22
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ca/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: creeu, compartiu i manteniu totes les vostres coses en un sol lloc."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/cs/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/cs/messages.json
new file mode 100644
index 000000000..6bc05da54
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/cs/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Disk Google: vytvářejte, sdílejte a ukládejte soubory na jednom místě."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Disk Google"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/da/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/da/messages.json
new file mode 100644
index 000000000..4f9716935
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/da/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drev: Opret, del, og gem alle dine ting på ét sted."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drev"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/de/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/de/messages.json
new file mode 100644
index 000000000..469489464
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/de/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: Alle Inhalte an einem Ort erstellen, teilen und speichern."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/el/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/el/messages.json
new file mode 100644
index 000000000..b193b11aa
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/el/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: δημιουργήστε, μοιραστείτε και διατηρήστε όλο το υλικό σας σε ένα μέρος."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive "
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/en_GB/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/en_GB/messages.json
new file mode 100644
index 000000000..5173f7576
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/en_GB/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: create, share and keep all your stuff in one place."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/en_US/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/en_US/messages.json
new file mode 100644
index 000000000..5173f7576
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/en_US/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: create, share and keep all your stuff in one place."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/es/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/es/messages.json
new file mode 100644
index 000000000..6e14e026b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/es/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: crea, comparte y almacena todo tu contenido en un solo lugar."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/es_419/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/es_419/messages.json
new file mode 100644
index 000000000..6e14e026b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/es_419/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: crea, comparte y almacena todo tu contenido en un solo lugar."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/et/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/et/messages.json
new file mode 100644
index 000000000..d028e1e36
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/et/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: looge, jagage ja hoidke kõiki oma faile ühes kohas."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/eu/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/eu/messages.json
new file mode 100644
index 000000000..9eca7bc73
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/eu/messages.json
@@ -0,0 +1,10 @@
+{
+ "appName": {
+ "message": "Google Drive",
+ "description": "App name."
+ },
+ "appDesc": {
+ "message": "Google Drive: sortu, partekatu eta mantendu zure fitxategi guztiak toki berean.",
+ "description":"App description."
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fi/messages.json
new file mode 100644
index 000000000..7d0f0e717
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: luo, jaa ja säilytä kaikki sisältösi yhdessä paikassa."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fil/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fil/messages.json
new file mode 100644
index 000000000..57b07b0e8
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fil/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: lumikha, magbahagi at itago lahat ng gamit mo sa isang lugar. "
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fr/messages.json
new file mode 100644
index 000000000..040bfe6c4
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/fr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive : votre nouvel espace pour créer, stocker et partager"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/he/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/he/messages.json
new file mode 100644
index 000000000..4da8fab1d
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/he/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "כונן Google: צור, שתף ושמור את כל הדברים שלך במקום אחד."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "כונן Google"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hi/messages.json
new file mode 100644
index 000000000..fe8744f63
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google डिस्क: बनाएं, साझा करें और अपनी सारी सामग्री एक जगह रखें"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google डिस्क"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hr/messages.json
new file mode 100644
index 000000000..9bfc7c948
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google disk: stvarajte, dijelite i spremite sve svoje datoteke na jednom mjestu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google disk"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hu/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hu/messages.json
new file mode 100644
index 000000000..ce02b9a79
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/hu/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: minden dolgot egy helyen hozhat létre, oszthat meg és tárolhat."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/id/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/id/messages.json
new file mode 100644
index 000000000..69ca3dfb4
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/id/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: buat, bagikan, dan simpan semua dokumen Anda dalam satu tempat."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/it/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/it/messages.json
new file mode 100644
index 000000000..564d93a2f
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/it/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: crea, condividi e conserva tutti i tuoi file in unico posto."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ja/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ja/messages.json
new file mode 100644
index 000000000..73c7f44a1
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ja/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google ドライブ: あらゆるファイルの作成、共有、保存を 1 か所で行えます。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google ドライブ"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ko/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ko/messages.json
new file mode 100644
index 000000000..5332bf380
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ko/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google 드라이브: 모든 콘텐츠를 한 곳에서 작성, 공유 및 보관하세요."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google 드라이브"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/lt/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/lt/messages.json
new file mode 100644
index 000000000..59fb67741
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/lt/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "„Google“ diskas: kurkite, bendrinkite ir saugokite visą savo medžiagą vienoje vietoje."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "„Google“ diskas "
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/lv/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/lv/messages.json
new file mode 100644
index 000000000..dc916f5ec
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/lv/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google disks: veidojiet, koplietojiet un glabājiet visu saturu vienuviet."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google disks"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ms/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ms/messages.json
new file mode 100644
index 000000000..b510c8b8e
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ms/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: buat, kongsi dan simpan semua bahan anda di satu tempat."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/nl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/nl/messages.json
new file mode 100644
index 000000000..96c7f8f19
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/nl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: alles op één plek maken, delen en bewaren."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/no/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/no/messages.json
new file mode 100644
index 000000000..8a0fb20da
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/no/messages.json
@@ -0,0 +1,10 @@
+{
+ "appName": {
+ "message": "Google Disk",
+ "description": "App name."
+ },
+ "appDesc": {
+ "message": "Google Disk: opprett, del og oppbevar alt på ett sted.",
+ "description":"App description."
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pl/messages.json
new file mode 100644
index 000000000..08ecaa7a4
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Dysk Google: zapisuj, udostępniaj i przechowuj wszystko w jednym miejscu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Dysk Google"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pt_BR/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pt_BR/messages.json
new file mode 100644
index 000000000..69d468d8a
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pt_BR/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: crie, compartilhe e guarde tudo em um só lugar."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pt_PT/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pt_PT/messages.json
new file mode 100644
index 000000000..57bef27f4
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/pt_PT/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: crie, partilhe e guarde todos os seus conteúdos num único local."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ro/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ro/messages.json
new file mode 100644
index 000000000..78700c7b0
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ro/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Disc Google: creaţi, permiteţi accesul şi păstraţi-vă toate documentele într-un singur loc."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Disc Google"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ru/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ru/messages.json
new file mode 100644
index 000000000..ea2ff30d2
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/ru/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Диск Google: создавайте, публикуйте и храните все свои файлы с помощью одного сервиса."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Диск Google"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sk/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sk/messages.json
new file mode 100644
index 000000000..fc61d49f0
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sk/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Disk Google – vytvárajte, zdieľajte a ukladajte všetky svoje súbory na jednom mieste."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Disk Google"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sl/messages.json
new file mode 100644
index 000000000..4c54115b3
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: ustvarjanje, skupna raba in shranjevanje vseh elementov na enem mestu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sr/messages.json
new file mode 100644
index 000000000..8765e2a8b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google диск: правите, делите и чувајте све на једном месту."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google диск"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sv/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sv/messages.json
new file mode 100644
index 000000000..aafd05c97
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/sv/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: skapa, dela och spara alla dina grejer på ett ställe."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/th/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/th/messages.json
new file mode 100644
index 000000000..359c87d4e
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/th/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google ไดรฟ์: สร้าง แบ่งปัน และเก็บข้อมูลทั้งหมดไว้ในที่เดียว "
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google ไดรฟ์"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/tr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/tr/messages.json
new file mode 100644
index 000000000..90b4ca80d
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/tr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: Tüm dosyalarınızı tek bir yerde oluşturun, paylaşın ve saklayın."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/uk/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/uk/messages.json
new file mode 100644
index 000000000..967823d5c
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/uk/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Диск Google: створюйте, зберігайте всі ваші файли та діліться ними за допомогою однієї служби."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Диск Google"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/vi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/vi/messages.json
new file mode 100644
index 000000000..cda96888d
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/vi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google Drive: tạo, chia sẻ và lưu giữ tất cả nội dung của bạn ở một nơi."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Drive"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/zh_CN/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/zh_CN/messages.json
new file mode 100644
index 000000000..a4476d2d1
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/zh_CN/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google 云端硬盘:在一个位置创建、共享和存储您的所有资料。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google 云端硬盘"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/zh_TW/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/zh_TW/messages.json
new file mode 100644
index 000000000..59847a89e
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/_locales/zh_TW/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Google 雲端硬碟:檔案製作、分享、存放,全部集中一處。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google 雲端硬碟"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/manifest.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/manifest.json
new file mode 100644
index 000000000..6c7383292
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/apdfllckaahabafndbhieahigkjlhalf/6.2_0/manifest.json
@@ -0,0 +1,24 @@
+{
+ "app": {
+ "launch": {
+ "web_url": "https://drive.google.com/"
+ },
+ "urls": [ "http://docs.google.com/", "http://drive.google.com/", "https://docs.google.com/", "https://drive.google.com/" ]
+ },
+ "background": {
+ "allow_js_access": false
+ },
+ "default_locale": "en_US",
+ "description": "__MSG_appDesc__",
+ "icons": {
+ "128": "128.png"
+ },
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIl5KlKwL2TSkntkpY3naLLz5jsN0YwjhZyObcTOK6Nda4Ie21KRqZau9lx5SHcLh7pE2/S9OiArb+na2dn7YK5EvH+aRXS1ec3uxVlBhqLdnleVgwgwlg5fH95I52IeHcoeK6pR4hW/Nv39GNlI/Uqk6O6GBCCsAxYrdxww9BiQIDAQAB",
+ "manifest_version": 2,
+ "name": "__MSG_appName__",
+ "offline_enabled": true,
+ "options_page": "https://drive.google.com/settings",
+ "permissions": [ "background", "clipboardRead", "clipboardWrite", "notifications", "unlimitedStorage" ],
+ "update_url": "http://clients2.google.com/service/update2/crx",
+ "version": "6.2"
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/128.png b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/128.png
new file mode 100644
index 000000000..5c0d6b37e
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/128.png differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ar/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ar/messages.json
new file mode 100644
index 000000000..5f68bb58f
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ar/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "منتدى الفيديو الأكثر شيوعًَا على الإنترنت."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Youtube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/bg/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/bg/messages.json
new file mode 100644
index 000000000..002715599
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/bg/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Най-популярната общност за онлайн видео в света."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ca/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ca/messages.json
new file mode 100644
index 000000000..075fe5911
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ca/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "La comunitat de vídeo en línia més popular del món."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/cs/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/cs/messages.json
new file mode 100644
index 000000000..e9f54d1dc
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/cs/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Nejoblíbenější komunita online videa na světě."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/da/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/da/messages.json
new file mode 100644
index 000000000..af5e5205c
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/da/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Verdens mest populære videofællesskab på nettet."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/de/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/de/messages.json
new file mode 100644
index 000000000..ccb997769
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/de/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Die beliebteste Online-Video-Community der Welt"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/el/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/el/messages.json
new file mode 100644
index 000000000..bca048824
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/el/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Η πιο δημοφιλής διαδικτυακή κοινότητα βίντεο στον κόσμο."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/en/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/en/messages.json
new file mode 100644
index 000000000..e35605271
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/en/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "The world's most popular online video community."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/es/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/es/messages.json
new file mode 100644
index 000000000..0c4b006ff
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/es/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "La comunidad de vídeos online más popular del mundo"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fi/messages.json
new file mode 100644
index 000000000..494ce616a
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Maailman suosituin verkkovideoyhteisö."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fil/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fil/messages.json
new file mode 100644
index 000000000..4b57d7ac6
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fil/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Ang pinakasikat na online na komunidad ng video sa mundo."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fr/messages.json
new file mode 100644
index 000000000..443a69cc4
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/fr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "La communauté de vidéos en ligne la plus populaire au monde."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/he/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/he/messages.json
new file mode 100644
index 000000000..017b2b246
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/he/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "קהילת הסרטונים המקוונת הפופולרית ביותר בעולם."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hi/messages.json
new file mode 100644
index 000000000..8c1af1122
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "विश्व का सबसे लोकप्रिय ऑनलाइन वीडियो समुदाय."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hr/messages.json
new file mode 100644
index 000000000..80941db1e
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Najpopularnija videozajednica na svijetu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hu/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hu/messages.json
new file mode 100644
index 000000000..03ffe239f
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/hu/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "A világ legnépszerűbb online videoközössége."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/id/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/id/messages.json
new file mode 100644
index 000000000..11b798eb5
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/id/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Komunitas video daring yang paling populer di dunia."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/it/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/it/messages.json
new file mode 100644
index 000000000..2407cfe25
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/it/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "La più famosa community di video online."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ja/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ja/messages.json
new file mode 100644
index 000000000..b0f71f4a1
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ja/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "YouTube は世界で最も人気のあるオンライン動画コミュニティです。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ko/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ko/messages.json
new file mode 100644
index 000000000..2f128ec4d
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ko/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "세계에서 가장 인기있는 온라인 동영상 커뮤니티입니다."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/lt/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/lt/messages.json
new file mode 100644
index 000000000..cb7781210
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/lt/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Populiariausia pasaulyje internetinė vaizdo įrašų bendruomenė."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/lv/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/lv/messages.json
new file mode 100644
index 000000000..37950b8a4
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/lv/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Pasaules populārākā tiešsaistes video kopiena."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/nl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/nl/messages.json
new file mode 100644
index 000000000..2c345d2ed
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/nl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "'s Werelds populairste online video community."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/no/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/no/messages.json
new file mode 100644
index 000000000..8b6c2665b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/no/messages.json
@@ -0,0 +1,10 @@
+{
+ "appName": {
+ "message": "YouTube",
+ "description": "App name."
+ },
+ "appDesc": {
+ "message": "Verdens mest populære videofellesskap på nett.",
+ "description":"App description."
+ }
+}
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pl/messages.json
new file mode 100644
index 000000000..126cd5239
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Najpopularniejsza społeczność odbiorców filmów online na świecie."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pt_BR/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pt_BR/messages.json
new file mode 100644
index 000000000..91fb37993
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pt_BR/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "A comunidade de vídeos on-line mais popular do mundo."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pt_PT/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pt_PT/messages.json
new file mode 100644
index 000000000..ea022864b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/pt_PT/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "A comunidade de vídeo on-line mais popular do mundo."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ro/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ro/messages.json
new file mode 100644
index 000000000..41b7d238a
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ro/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Cea mai populară comunitate video online din întreaga lume."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ru/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ru/messages.json
new file mode 100644
index 000000000..7b39443da
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/ru/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Самое популярное в мире видеосообщество."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sk/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sk/messages.json
new file mode 100644
index 000000000..70d63ae64
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sk/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Najobľúbenejšia komunita videa online na svete."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sl/messages.json
new file mode 100644
index 000000000..763bb5d90
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Najbolj priljubljena spletna skupnost za izmenjavo videoposnetkov."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sr/messages.json
new file mode 100644
index 000000000..da9fae39d
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Најпопуларнија светска видео заједница на мрежи."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sv/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sv/messages.json
new file mode 100644
index 000000000..6cebf32c5
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/sv/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Världens populäraste videomötesplats online."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/th/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/th/messages.json
new file mode 100644
index 000000000..7a549e1d5
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/th/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "ชุมชนวิดีโอออนไลน์ยอดนิยมของโลก"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/tr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/tr/messages.json
new file mode 100644
index 000000000..57c77aab0
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/tr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Dünyanın en popüler çevrimiçi video topluluğu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/uk/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/uk/messages.json
new file mode 100644
index 000000000..15b7917e0
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/uk/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Найпопулярніша онлайнова відеоспільнота у світі."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/vi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/vi/messages.json
new file mode 100644
index 000000000..77bf16391
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/vi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Cộng đồng video trực tuyến được ưa chuộng nhất trên thế giới."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/zh_CN/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/zh_CN/messages.json
new file mode 100644
index 000000000..afe9c06f0
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/zh_CN/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "全球最热门的在线视频社区。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/zh_TW/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/zh_TW/messages.json
new file mode 100644
index 000000000..aeafc0043
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/_locales/zh_TW/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "全世界最受歡迎的線上影片社群。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "YouTube"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/manifest.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/manifest.json
new file mode 100644
index 000000000..ad840b2be
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0/manifest.json
@@ -0,0 +1,22 @@
+{
+ "app": {
+ "launch": {
+ "container": "tab",
+ "web_url": "http://www.youtube.com/"
+ },
+ "web_content": {
+ "enabled": true,
+ "origin": "http://www.youtube.com"
+ }
+ },
+ "default_locale": "en",
+ "description": "__MSG_appDesc__",
+ "icons": {
+ "128": "128.png"
+ },
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC/HotmFlyuz5FaHaIbVBhhL4BwbcUtsfWwzgUMpZt5ZsLB2nW/Y5xwNkkPANYGdVsJkT2GPpRRIKBO5QiJ7jPMa3EZtcZHpkygBlQLSjMhdrAKevpKgIl6YTkwzNvExY6rzVDzeE9zqnIs33eppY4S5QcoALMxuSWlMKqgFQjHQIDAQAB",
+ "name": "__MSG_appName__",
+ "permissions": [ "appNotifications" ],
+ "update_url": "http://clients2.google.com/service/update2/crx",
+ "version": "4.2.5"
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/128.png b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/128.png
new file mode 100644
index 000000000..617317e0d
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/128.png differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ar/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ar/messages.json
new file mode 100644
index 000000000..12a26a9bf
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ar/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "بريد إلكتروني يوفر إمكانية البحث مع مقدار أقل من الرسائل غير المرغوب فيها."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/bg/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/bg/messages.json
new file mode 100644
index 000000000..f8c25f30b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/bg/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Бърза електронна поща, в която може да се търси, с по-малко спам."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ca/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ca/messages.json
new file mode 100644
index 000000000..65cc8596a
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ca/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Correu electrònic ràpid i on es poden fer cerques, amb menys correu brossa."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/cs/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/cs/messages.json
new file mode 100644
index 000000000..e73970cf4
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/cs/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Rychlý e-mail s možností vyhledávání a menším množstvím spamu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/da/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/da/messages.json
new file mode 100644
index 000000000..cc2302e37
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/da/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Hurtig e-mail, hvor der kan søges, og som har mindre spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/de/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/de/messages.json
new file mode 100644
index 000000000..ce22c6f47
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/de/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Schneller E-Mail-Dienst mit Suchfunktion und wenig Spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Google Mail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/el/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/el/messages.json
new file mode 100644
index 000000000..55398f4ec
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/el/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Γρήγορο ηλεκτρονικό ταχυδρομείο με δυνατότητα αναζήτησης και λιγότερα ανεπιθύμητα."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/en/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/en/messages.json
new file mode 100644
index 000000000..e799ca1dc
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/en/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Fast, searchable email with less spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/es/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/es/messages.json
new file mode 100644
index 000000000..f21d322d6
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/es/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Un servicio de correo electrónico rápido con menos spam y que permite realizar búsquedas."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fi/messages.json
new file mode 100644
index 000000000..c1f2818b5
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Nopea, vähemmän roskapostia sisältävä sähköpostipalvelu hakutoiminnolla."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fil/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fil/messages.json
new file mode 100644
index 000000000..a695a7799
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fil/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "\r\nMabilis, nahahanap na email na may mas kaunting spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fr/messages.json
new file mode 100644
index 000000000..bfeb25f7c
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/fr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Profitez d'une messagerie rapide, avec moins de spam et dotée d'une fonction de recherche."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hi/messages.json
new file mode 100644
index 000000000..5b46da035
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "कम स्पैम के साथ तेज़ और खोज करने योग्य ईमेल."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hr/messages.json
new file mode 100644
index 000000000..665458b33
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Brza, pretraživa e-pošta s manje neželjene pošte."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hu/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hu/messages.json
new file mode 100644
index 000000000..fdcb16adc
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/hu/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Gyors, kereshető e-mail fiók, kevesebb spammel."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/id/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/id/messages.json
new file mode 100644
index 000000000..9752200ca
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/id/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Email yang cepat dan dapat ditelusuri dengan lebih sedikit spam. "
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/it/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/it/messages.json
new file mode 100644
index 000000000..7fce1763e
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/it/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Servizio di posta veloce in cui è possibile cercare i messaggi, con meno spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ja/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ja/messages.json
new file mode 100644
index 000000000..7eec01120
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ja/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "高速で検索機能に優れた、迷惑メールの少ないメール システムです。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ko/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ko/messages.json
new file mode 100644
index 000000000..904416deb
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ko/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "빠르고 검색 가능하며 스팸은 줄어든 이메일 서비스입니다."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/lt/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/lt/messages.json
new file mode 100644
index 000000000..357457dfe
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/lt/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Greitas el. paštas, kuriame galima ieškoti ir pateikiama mažiau slamšto."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/lv/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/lv/messages.json
new file mode 100644
index 000000000..b4c49d643
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/lv/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Ātrs un pārlūkojams e-pasts ar mazāku mēstuļu daudzumu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/nl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/nl/messages.json
new file mode 100644
index 000000000..a1c005677
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/nl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Een snelle, doorzoekbare e-mailfunctie met minder spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/no/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/no/messages.json
new file mode 100644
index 000000000..8ed177f72
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/no/messages.json
@@ -0,0 +1,10 @@
+{
+ "appName": {
+ "message": "Gmail",
+ "description": "App name."
+ },
+ "appDesc": {
+ "message": "Rask, søkbar e-post med mindre nettsøppel.",
+ "description":"App description."
+ }
+}
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pl/messages.json
new file mode 100644
index 000000000..ebbff20b3
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Szybka usługa poczty e-mail z możliwością wyszukiwania i mniejszą ilością spamu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pt_BR/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pt_BR/messages.json
new file mode 100644
index 000000000..2f8943e3b
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pt_BR/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "E-mail rápido e pesquisável com menos spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pt_PT/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pt_PT/messages.json
new file mode 100644
index 000000000..71b3a3931
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/pt_PT/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "E-mail rápido e pesquisável, com menos spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ro/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ro/messages.json
new file mode 100644
index 000000000..add4a9e74
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ro/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Serviciu de e-mail rapid, în care se pot efectua căutări, cu mai puţine mesaje spam."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ru/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ru/messages.json
new file mode 100644
index 000000000..414769ab6
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/ru/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Быстрая почта без спама, в которой легко найти любое письмо."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/se/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/se/messages.json
new file mode 100644
index 000000000..880b991e3
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/se/messages.json
@@ -0,0 +1,10 @@
+{
+ "appName": {
+ "message": "Gmail",
+ "description": "App name."
+ },
+ "appDesc": {
+ "message": "Snabb, sökbar e-post med mindre skräppost.",
+ "description":"App description."
+ }
+}
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sk/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sk/messages.json
new file mode 100644
index 000000000..0c178c68d
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sk/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Rýchly e-mail s vyhľadávaním a bez spamu."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sl/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sl/messages.json
new file mode 100644
index 000000000..b850e9525
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sl/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Hitra in organizirana e-pošta – manj neželene pošte."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sr/messages.json
new file mode 100644
index 000000000..5feff2a42
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/sr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Брза е-пошта са мање непожељних порука и функцијом претраживања."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/th/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/th/messages.json
new file mode 100644
index 000000000..88b9ad6d6
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/th/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "บริการอีเมลที่รวดเร็วและค้นหาได้โดยมีสแปมน้อยกว่า"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/tr/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/tr/messages.json
new file mode 100644
index 000000000..1f83e9b63
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/tr/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Daha az spam içeren hızlı, arama yapılabilir e-posta."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/uk/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/uk/messages.json
new file mode 100644
index 000000000..e2c5a1cc5
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/uk/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Швидка, доступна для пошуку електронна пошта з меншим напливом спаму."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/vi/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/vi/messages.json
new file mode 100644
index 000000000..d3ab2620a
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/vi/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "Email nhanh, có thể tìm kiếm với ít spam hơn."
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/zh_CN/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/zh_CN/messages.json
new file mode 100644
index 000000000..def62e1ff
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/zh_CN/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "快捷的电子邮件服务,可以搜索邮件且有效减少了垃圾邮件。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/zh_TW/messages.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/zh_TW/messages.json
new file mode 100644
index 000000000..006e42f90
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/_locales/zh_TW/messages.json
@@ -0,0 +1,10 @@
+{
+ "appDesc": {
+ "description": "App description.",
+ "message": "垃圾郵件更少、迅速,並且可供搜尋的電子郵件服務。"
+ },
+ "appName": {
+ "description": "App name.",
+ "message": "Gmail"
+ }
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/manifest.json b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/manifest.json
new file mode 100644
index 000000000..15102ba20
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Extensions/pjkljhegncpnkpknbcohdijeoejaedia/7_0/manifest.json
@@ -0,0 +1,20 @@
+{
+ "app": {
+ "launch": {
+ "container": "tab",
+ "web_url": "https://mail.google.com/mail/ca"
+ },
+ "urls": [ "*://mail.google.com/mail/ca" ]
+ },
+ "default_locale": "en",
+ "description": "__MSG_appDesc__",
+ "icons": {
+ "128": "128.png"
+ },
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCuGglK43iAz3J9BEYK/Mz6ZhloIMMDqQSAaf3vJt4eHbTbSDsu4WdQ9dQDRcKlg8nwQdePBt0C3PSUBtiSNSS37Z3qEGfS7LCju3h6pI1Yr9MQtxw+jUa7kXXIS09VV73pEFUT/F7c6Qe8L5ZxgAcBvXBh1Fie63qb02I9XQ/CQIDAQAB",
+ "name": "__MSG_appName__",
+ "options_page": "https://mail.google.com/mail/ca/#settings",
+ "permissions": [ "notifications" ],
+ "update_url": "http://clients2.google.com/service/update2/crx",
+ "version": "7"
+}
diff --git a/nichrome/home/user/.config/google-chrome/Default/Favicons b/nichrome/home/user/.config/google-chrome/Default/Favicons
new file mode 100644
index 000000000..1abc0e5f7
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Favicons differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Favicons-journal b/nichrome/home/user/.config/google-chrome/Default/Favicons-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_0 b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_0
new file mode 100644
index 000000000..d76fb77e9
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_0 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_1 b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_1
new file mode 100644
index 000000000..dcaafa974
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_1 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_2 b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_2
new file mode 100644
index 000000000..c7e2eb9ad
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_2 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_3 b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_3
new file mode 100644
index 000000000..5eec97358
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/GPUCache/data_3 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/GPUCache/index b/nichrome/home/user/.config/google-chrome/Default/GPUCache/index
new file mode 100644
index 000000000..85b9d75bd
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/GPUCache/index differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/History b/nichrome/home/user/.config/google-chrome/Default/History
new file mode 100644
index 000000000..b15afd739
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/History differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/History Provider Cache b/nichrome/home/user/.config/google-chrome/Default/History Provider Cache
new file mode 100644
index 000000000..68a83b164
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/History Provider Cache differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/History-journal b/nichrome/home/user/.config/google-chrome/Default/History-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Last Session b/nichrome/home/user/.config/google-chrome/Default/Last Session
new file mode 100644
index 000000000..024990d0d
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Last Session differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Last Tabs b/nichrome/home/user/.config/google-chrome/Default/Last Tabs
new file mode 100644
index 000000000..71e38e0ce
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Last Tabs differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/000003.log b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/000003.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/CURRENT b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/CURRENT
new file mode 100644
index 000000000..7ed683d17
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/CURRENT
@@ -0,0 +1 @@
+MANIFEST-000001
diff --git a/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/LOCK b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/LOCK
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/LOG b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/LOG
new file mode 100644
index 000000000..f8a786df1
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/LOG
@@ -0,0 +1 @@
+2018/07/20-17:14:36.354 2566 Reusing MANIFEST leveldb/MANIFEST-000001
diff --git a/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/MANIFEST-000001 b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/MANIFEST-000001
new file mode 100644
index 000000000..18e5cab72
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Local Storage/leveldb/MANIFEST-000001 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Login Data b/nichrome/home/user/.config/google-chrome/Default/Login Data
new file mode 100644
index 000000000..0baca2d7a
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Login Data differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Login Data-journal b/nichrome/home/user/.config/google-chrome/Default/Login Data-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Network Action Predictor b/nichrome/home/user/.config/google-chrome/Default/Network Action Predictor
new file mode 100644
index 000000000..d51d91ac0
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Network Action Predictor differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Network Action Predictor-journal b/nichrome/home/user/.config/google-chrome/Default/Network Action Predictor-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Origin Bound Certs b/nichrome/home/user/.config/google-chrome/Default/Origin Bound Certs
new file mode 100644
index 000000000..4adbd3374
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Origin Bound Certs differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Origin Bound Certs-journal b/nichrome/home/user/.config/google-chrome/Default/Origin Bound Certs-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Preferences b/nichrome/home/user/.config/google-chrome/Default/Preferences
new file mode 100644
index 000000000..09be8554e
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Preferences
@@ -0,0 +1 @@
+{"account_id_migration_state":2,"account_tracker_service_last_update":"13176580426263893","browser":{"has_seen_welcome_page":true,"window_placement":{"bottom":764,"left":687,"maximized":false,"right":1362,"top":388,"work_area_bottom":768,"work_area_left":0,"work_area_right":1366,"work_area_top":0}},"countryid_at_install":-1,"data_reduction":{"daily_original_length":[],"daily_original_length_application":"0","daily_original_length_unknown":"0","daily_original_length_via_data_reduction_proxy":[],"daily_original_length_via_data_reduction_proxy_application":"0","daily_original_length_via_data_reduction_proxy_unknown":"0","daily_original_length_via_data_reduction_proxy_video":"0","daily_original_length_video":"0","daily_original_length_with_data_reduction_proxy_enabled":[],"daily_original_length_with_data_reduction_proxy_enabled_application":"0","daily_original_length_with_data_reduction_proxy_enabled_unknown":"0","daily_original_length_with_data_reduction_proxy_enabled_video":"0","daily_received_length":[],"daily_received_length_application":"0","daily_received_length_https_with_data_reduction_proxy_enabled":[],"daily_received_length_long_bypass_with_data_reduction_proxy_enabled":[],"daily_received_length_short_bypass_with_data_reduction_proxy_enabled":[],"daily_received_length_unknown":"0","daily_received_length_unknown_with_data_reduction_proxy_enabled":[],"daily_received_length_via_data_reduction_proxy":[],"daily_received_length_via_data_reduction_proxy_application":"0","daily_received_length_via_data_reduction_proxy_unknown":"0","daily_received_length_via_data_reduction_proxy_video":"0","daily_received_length_video":"0","daily_received_length_with_data_reduction_proxy_enabled":[],"daily_received_length_with_data_reduction_proxy_enabled_application":"0","daily_received_length_with_data_reduction_proxy_enabled_unknown":"0","daily_received_length_with_data_reduction_proxy_enabled_video":"0","last_update_date":"0"},"data_reduction_lo_fi":{"load_images_requests_per_session":0,"load_images_snackbars_shown_per_session":0,"was_used_this_session":false},"default_apps_install_state":3,"dns_prefetching":{"host_referral_list":[2],"startup_list":[1,"http://localhost:8000/","https://www.google.com/","https://www.googleapis.com/"]},"download":{"directory_upgrade":true},"extensions":{"alerts":{"initialized":true},"autoupdate":{"next_check":"13176584164948483"},"chrome_url_overrides":{"bookmarks":[{"active":true,"entry":"chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html"}]},"last_chrome_version":"61.0.3163.100","settings":{"ahfgeienlihckogmohjhadlkjgocpleb":{"active_permissions":{"api":["management","system.display","system.storage","webstorePrivate","system.cpu","system.memory","system.network"],"manifest_permissions":[]},"app_launcher_ordinal":"t","commands":{},"content_settings":[],"creation_flags":1,"events":[],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"install_time":"13176580426197283","location":5,"manifest":{"app":{"launch":{"web_url":"https://chrome.google.com/webstore"},"urls":["https://chrome.google.com/webstore"]},"description":"Discover great apps, games, extensions and themes for Google Chrome.","icons":{"128":"webstore_icon_128.png","16":"webstore_icon_16.png"},"key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtl3tO0osjuzRsf6xtD2SKxPlTfuoy7AWoObysitBPvH5fE1NaAA1/2JkPWkVDhdLBWLaIBPYeXbzlHp3y4Vv/4XG+aN5qFE3z+1RU/NqkzVYHtIpVScf3DjTYtKVL66mzVGijSoAIwbFCC3LpGdaoe6Q1rSRDp76wR6jjFzsYwQIDAQAB","name":"Web Store","permissions":["webstorePrivate","management","system.cpu","system.display","system.memory","system.network","system.storage"],"version":"0.2"},"never_activated_since_loaded":true,"page_ordinal":"n","path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/web_store","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"aohghmighlieiainnegkcijnfilokake":{"ack_external":true,"active_permissions":{"api":[],"manifest_permissions":[]},"app_launcher_ordinal":"x","commands":{},"content_settings":[],"creation_flags":137,"events":[],"from_bookmark":false,"from_webstore":true,"granted_permissions":{"api":[],"manifest_permissions":[]},"incognito_content_settings":[],"incognito_preferences":{},"initial_keybindings_set":true,"install_time":"13176580428704276","location":1,"manifest":{"app":{"launch":{"local_path":"main.html"}},"description":"Create, share, and access your Google Docs from anywhere.","icons":{"128":"icon_128.png","16":"icon_16.png"},"key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJhLK6fk/BWTEvJhywpk7jDe4A2r0bGXGOLZW4/AdBp3IiD9o9nx4YjLAtv0tIPxi7MvFd/GUUbQBwHT5wQWONJj1z/0Rc2qBkiJA0yqXh42p0snuA8dCfdlhOLsp7/XTMEwAVasjV5hC4awl78eKfJYlZ+8fM/UldLWJ/51iBQwIDAQAB","manifest_version":2,"name":"Docs","offline_enabled":true,"update_url":"http://clients2.google.com/service/update2/crx","version":"0.0.0.6"},"never_activated_since_loaded":true,"page_ordinal":"n","path":"aohghmighlieiainnegkcijnfilokake/0.0.0.6_0","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":true,"was_installed_by_oem":false},"apdfllckaahabafndbhieahigkjlhalf":{"ack_external":true,"active_permissions":{"api":["background","clipboardRead","clipboardWrite","notifications","unlimitedStorage"],"manifest_permissions":[]},"app_launcher_ordinal":"w","commands":{},"content_settings":[],"creation_flags":137,"events":[],"from_bookmark":false,"from_webstore":true,"granted_permissions":{"api":["background","clipboardRead","clipboardWrite","notifications","unlimitedStorage"],"manifest_permissions":[]},"incognito_content_settings":[],"incognito_preferences":{},"install_time":"13176580428607199","location":1,"manifest":{"app":{"launch":{"web_url":"https://drive.google.com/"},"urls":["http://docs.google.com/","http://drive.google.com/","https://docs.google.com/","https://drive.google.com/"]},"background":{"allow_js_access":false},"current_locale":"en_US","default_locale":"en_US","description":"Google Drive: create, share and keep all your stuff in one place.","icons":{"128":"128.png"},"key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIl5KlKwL2TSkntkpY3naLLz5jsN0YwjhZyObcTOK6Nda4Ie21KRqZau9lx5SHcLh7pE2/S9OiArb+na2dn7YK5EvH+aRXS1ec3uxVlBhqLdnleVgwgwlg5fH95I52IeHcoeK6pR4hW/Nv39GNlI/Uqk6O6GBCCsAxYrdxww9BiQIDAQAB","manifest_version":2,"name":"Google Drive","offline_enabled":true,"options_page":"https://drive.google.com/settings","permissions":["background","clipboardRead","clipboardWrite","notifications","unlimitedStorage"],"update_url":"http://clients2.google.com/service/update2/crx","version":"6.2"},"never_activated_since_loaded":true,"page_ordinal":"n","path":"apdfllckaahabafndbhieahigkjlhalf/6.2_0","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":true,"was_installed_by_oem":false},"bepbmhgboaologfdajaanbcjmnhjmhfn":{"disable_reasons":1,"state":0},"blpcfgokakmgnkcojhhkbfbldkacnbeo":{"ack_external":true,"active_permissions":{"api":[],"manifest_permissions":[]},"app_launcher_ordinal":"yn","commands":{},"content_settings":[],"creation_flags":153,"events":[],"from_bookmark":true,"from_webstore":true,"granted_permissions":{"api":[],"manifest_permissions":[]},"incognito_content_settings":[],"incognito_preferences":{},"install_time":"13176580428806137","location":1,"manifest":{"app":{"launch":{"container":"tab","web_url":"http://www.youtube.com/"},"web_content":{"enabled":true,"origin":"http://www.youtube.com"}},"current_locale":"en_US","default_locale":"en","description":"The world's most popular online video community.","icons":{"128":"128.png"},"key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC/HotmFlyuz5FaHaIbVBhhL4BwbcUtsfWwzgUMpZt5ZsLB2nW/Y5xwNkkPANYGdVsJkT2GPpRRIKBO5QiJ7jPMa3EZtcZHpkygBlQLSjMhdrAKevpKgIl6YTkwzNvExY6rzVDzeE9zqnIs33eppY4S5QcoALMxuSWlMKqgFQjHQIDAQAB","name":"YouTube","permissions":["appNotifications"],"update_url":"http://clients2.google.com/service/update2/crx","version":"4.2.5"},"never_activated_since_loaded":true,"page_ordinal":"n","path":"blpcfgokakmgnkcojhhkbfbldkacnbeo/4.2.5_0","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":true,"was_installed_by_oem":false},"eemcgdkfndhakfknompkggombfjjjeno":{"active_permissions":{"api":["bookmarks","bookmarkManagerPrivate","metricsPrivate","systemPrivate","tabs"],"explicit_host":["chrome://favicon/*","chrome://resources/*"],"manifest_permissions":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":[],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"initial_keybindings_set":true,"install_time":"13176580426186521","location":5,"manifest":{"chrome_url_overrides":{"bookmarks":"main.html"},"content_security_policy":"object-src 'none'; script-src chrome://resources 'self' blob: filesystem:","description":"Bookmark Manager","icons":{},"incognito":"split","key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQcByy+eN9jzazWF/DPn7NW47sW7lgmpk6eKc0BQM18q8hvEM3zNm2n7HkJv/R6fU+X5mtqkDuKvq5skF6qqUF4oEyaleWDFhd1xFwV7JV+/DU7bZ00w2+6gzqsabkerFpoP33ZRIw7OviJenP0c0uWqDWF8EGSyMhB3txqhOtiQIDAQAB","manifest_version":2,"name":"Bookmark Manager","permissions":["bookmarks","bookmarkManagerPrivate","metricsPrivate","systemPrivate","tabs","chrome://favicon/","chrome://resources/"],"version":"0.1"},"never_activated_since_loaded":true,"path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/bookmark_manager","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"gfdkimpbcpahaombhbimeihdjnejgicl":{"active_permissions":{"api":["feedbackPrivate"],"explicit_host":["chrome://resources/*"],"manifest_permissions":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":["feedbackPrivate.onFeedbackRequested","runtime.onMessageExternal"],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"initial_keybindings_set":true,"install_time":"13176580426198677","location":5,"manifest":{"app":{"background":{"scripts":["js/event_handler.js"]},"content_security_policy":"default-src 'none'; script-src 'self' blob: filesystem: chrome://resources; style-src 'unsafe-inline' blob: chrome: file: filesystem: data: *; img-src * blob: chrome: file: filesystem: data:; media-src 'self' blob: filesystem:"},"description":"User feedback extension","display_in_launcher":false,"display_in_new_tab_page":false,"icons":{"32":"images/icon32.png","64":"images/icon64.png"},"incognito":"split","key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMZElzFX2J1g1nRQ/8S3rg/1CjFyDltWOxQg+9M8aVgNVxbutEWFQz+oQzIP9BB67mJifULgiv12ToFKsae4NpEUR8sPZjiKDIHumc6pUdixOm8SJ5Rs16SMR6+VYxFUjlVW+5CA3IILptmNBxgpfyqoK0qRpBDIhGk1KDEZ4zqQIDAQAB","manifest_version":2,"name":"Feedback","permissions":["feedbackPrivate","chrome://resources/"],"version":"1.0"},"never_activated_since_loaded":true,"path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/feedback","preferences":{},"regular_only_preferences":{},"running":false,"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"kmendfapggjehodndflmmgagdbamhnfd":{"active_permissions":{"api":["cryptotokenPrivate","externally_connectable.all_urls","hid","tabs","u2fDevices","usb",{"usbDevices":[{"interfaceClass":-1,"interfaceId":-1,"productId":529,"vendorId":4176}]},"webConnectable"],"explicit_host":["http://*/*","https://*/*"],"manifest_permissions":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":["runtime.onConnectExternal","runtime.onMessageExternal"],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"initial_keybindings_set":true,"install_time":"13176580426204529","location":5,"manifest":{"background":{"persistent":false,"scripts":["util.js","b64.js","sha256.js","timer.js","countdown.js","countdowntimer.js","devicestatuscodes.js","approvedorigins.js","errorcodes.js","webrequest.js","messagetypes.js","factoryregistry.js","closeable.js","requesthelper.js","enroller.js","requestqueue.js","signer.js","origincheck.js","textfetcher.js","appid.js","watchdog.js","logging.js","webrequestsender.js","window-timer.js","cryptotokenorigincheck.js","cryptotokenapprovedorigins.js","gnubbydevice.js","hidgnubbydevice.js","usbgnubbydevice.js","gnubbies.js","gnubby.js","gnubby-u2f.js","gnubbyfactory.js","singlesigner.js","multiplesigner.js","generichelper.js","inherits.js","individualattest.js","devicefactoryregistry.js","usbhelper.js","usbenrollhandler.js","usbsignhandler.js","usbgnubbyfactory.js","googlecorpindividualattest.js","cryptotokenbackground.js"]},"description":"CryptoToken Component Extension","externally_connectable":{"accepts_tls_channel_id":true,"ids":["fjajfjhkeibgmiggdfehjplbhmfkialk"],"matches":["\u003Call_urls>"]},"incognito":"split","key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq7zRobvA+AVlvNqkHSSVhh1sEWsHSqz4oR/XptkDe/Cz3+gW9ZGumZ20NCHjaac8j1iiesdigp8B1LJsd/2WWv2Dbnto4f8GrQ5MVphKyQ9WJHwejEHN2K4vzrTcwaXqv5BSTXwxlxS/mXCmXskTfryKTLuYrcHEWK8fCHb+0gvr8b/kvsi75A1aMmb6nUnFJvETmCkOCPNX5CHTdy634Ts/x0fLhRuPlahk63rdf7agxQv5viVjQFk+tbgv6aa9kdSd11Js/RZ9yZjrFgHOBWgP4jTBqud4+HUglrzu8qynFipyNRLCZsaxhm+NItTyNgesxLdxZcwOz56KD1Q4IQIDAQAB","manifest_version":2,"name":"CryptoTokenExtension","permissions":["hid","u2fDevices","usb","cryptotokenPrivate","externally_connectable.all_urls","tabs","https://*/*","http://*/*",{"usbDevices":[{"productId":529,"vendorId":4176}]}],"version":"0.9.46"},"never_activated_since_loaded":true,"path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/cryptotoken","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"mfehgcgbbipciphmccgaenjidiccnmng":{"active_permissions":{"api":["cloudPrintPrivate"],"manifest_permissions":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":[],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"install_time":"13176580426196595","location":5,"manifest":{"app":{"launch":{"web_url":"https://www.google.com/cloudprint"},"urls":["https://www.google.com/cloudprint/enable_chrome_connector"]},"description":"Cloud Print","display_in_launcher":false,"icons":{},"key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDqOhnwk4+HXVfGyaNsAQdU/js1Na56diW08oF1MhZiwzSnJsEaeuMN9od9q9N4ZdK3o1xXOSARrYdE+syV7Dl31nf6qz3A6K+D5NHe6sSB9yvYlIiN37jdWdrfxxE0pRYEVYZNTe3bzq3NkcYJlOdt1UPcpJB+isXpAGUKUvt7EQIDAQAB","name":"Cloud Print","permissions":["cloudPrintPrivate"],"version":"0.1"},"never_activated_since_loaded":true,"path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/cloud_print","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"mhjfbmdgcfjbbpaeojofohoefgiehjai":{"active_permissions":{"api":["resourcesPrivate"],"explicit_host":["\u003Call_urls>","chrome://favicon/*"],"manifest_permissions":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":[],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"initial_keybindings_set":true,"install_time":"13176580426206349","location":5,"manifest":{"content_security_policy":"script-src 'self' blob: filesystem: chrome://resources; object-src * blob: externalfile: file: filesystem: data:; plugin-types application/x-google-chrome-pdf","description":"","incognito":"split","key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDN6hM0rsDYGbzQPQfOygqlRtQgKUXMfnSjhIBL7LnReAVBEd7ZmKtyN2qmSasMl4HZpMhVe2rPWVVwBDl6iyNE/Kok6E6v6V3vCLGsOpQAuuNVye/3QxzIldzG/jQAdWZiyXReRVapOhZtLjGfywCvlWq7Sl/e3sbc0vWybSDI2QIDAQAB","manifest_version":2,"mime_types":["application/pdf"],"mime_types_handler":"index.html","name":"Chrome PDF Viewer","offline_enabled":true,"permissions":["\u003Call_urls>","resourcesPrivate"],"version":"1","web_accessible_resources":["*.js","*.html","*.css","*.png"]},"never_activated_since_loaded":true,"path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/pdf","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"neajdppkdcdipfabeoofebfddakdcjhd":{"active_permissions":{"api":["systemPrivate","ttsEngine"],"explicit_host":["https://www.google.com/*"],"manifest_permissions":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":["ttsEngine.onPause","ttsEngine.onResume","ttsEngine.onSpeak","ttsEngine.onStop"],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"initial_keybindings_set":true,"install_time":"13176580426203666","location":5,"manifest":{"background":{"persistent":false,"scripts":["tts_extension.js"]},"description":"Component extension providing speech via the Google network text-to-speech service.","key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8GSbNUMGygqQTNDMFGIjZNcwXsHLzkNkHjWbuY37PbNdSDZ4VqlVjzbWqODSe+MjELdv5Keb51IdytnoGYXBMyqKmWpUrg+RnKvQ5ibWr4MW9pyIceOIdp9GrzC1WZGgTmZismYR3AjaIpufZ7xDdQQv+XrghPWCkdVqLN+qZDA1HU+DURznkMICiDDSH2sU0egm9UbWfS218bZqzKeQDiC3OnTPlaxcbJtKUuupIm5knjze3Wo9Ae9poTDMzKgchg0VlFCv3uqox+wlD8sjXBoyBCCK9HpImdVAF1a7jpdgiUHpPeV/26oYzM9/grltwNR3bzECQgSpyXp0eyoegwIDAQAB","manifest_version":2,"name":"Google Network Speech","permissions":["systemPrivate","ttsEngine","https://www.google.com/"],"tts_engine":{"voices":[{"event_types":["start","end","error"],"gender":"female","lang":"de-DE","remote":true,"voice_name":"Google Deutsch"},{"event_types":["start","end","error"],"gender":"female","lang":"en-US","remote":true,"voice_name":"Google US English"},{"event_types":["start","end","error"],"gender":"female","lang":"en-GB","remote":true,"voice_name":"Google UK English Female"},{"event_types":["start","end","error"],"gender":"male","lang":"en-GB","remote":true,"voice_name":"Google UK English Male"},{"event_types":["start","end","error"],"gender":"female","lang":"es-ES","remote":true,"voice_name":"Google español"},{"event_types":["start","end","error"],"gender":"female","lang":"es-US","remote":true,"voice_name":"Google español de Estados Unidos"},{"event_types":["start","end","error"],"gender":"female","lang":"fr-FR","remote":true,"voice_name":"Google français"},{"event_types":["start","end","error"],"gender":"female","lang":"hi-IN","remote":true,"voice_name":"Google हिन्दी"},{"event_types":["start","end","error"],"gender":"female","lang":"id-ID","remote":true,"voice_name":"Google Bahasa Indonesia"},{"event_types":["start","end","error"],"gender":"female","lang":"it-IT","remote":true,"voice_name":"Google italiano"},{"event_types":["start","end","error"],"gender":"female","lang":"ja-JP","remote":true,"voice_name":"Google 日本語"},{"event_types":["start","end","error"],"gender":"female","lang":"ko-KR","remote":true,"voice_name":"Google 한국의"},{"event_types":["start","end","error"],"gender":"female","lang":"nl-NL","remote":true,"voice_name":"Google Nederlands"},{"event_types":["start","end","error"],"gender":"female","lang":"pl-PL","remote":true,"voice_name":"Google polski"},{"event_types":["start","end","error"],"gender":"female","lang":"pt-BR","remote":true,"voice_name":"Google português do Brasil"},{"event_types":["start","end","error"],"gender":"female","lang":"ru-RU","remote":true,"voice_name":"Google русский"},{"event_types":["start","end","error"],"gender":"female","lang":"zh-CN","remote":true,"voice_name":"Google 普通话(中国大陆)"},{"event_types":["start","end","error"],"gender":"female","lang":"zh-HK","remote":true,"voice_name":"Google 粤語(香港)"},{"event_types":["start","end","error"],"gender":"female","lang":"zh-TW","remote":true,"voice_name":"Google 國語(臺灣)"}]},"version":"1.0"},"never_activated_since_loaded":true,"path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/network_speech_synthesis","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"nkeimhogjdpnpccoofpliimaahmaaome":{"active_permissions":{"api":["desktopCapture","processes","webConnectable","webrtcAudioPrivate","webrtcDesktopCapturePrivate","webrtcLoggingPrivate","system.cpu"],"manifest_permissions":[]},"commands":{},"content_settings":[],"creation_flags":1,"events":["runtime.onConnectExternal","runtime.onMessageExternal"],"from_bookmark":false,"from_webstore":false,"incognito_content_settings":[],"incognito_preferences":{},"initial_keybindings_set":true,"install_time":"13176580426198008","location":5,"manifest":{"background":{"page":"background.html","persistent":false},"externally_connectable":{"matches":["https://*.google.com/*","*://localhost/*"]},"incognito":"split","key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAQt2ZDdPfoSe/JI6ID5bgLHRCnCu9T36aYczmhw/tnv6QZB2I6WnOCMZXJZlRdqWc7w9jo4BWhYS50Vb4weMfh/I0On7VcRwJUgfAxW2cHB+EkmtI1v4v/OU24OqIa1Nmv9uRVeX0GjhQukdLNhAE6ACWooaf5kqKlCeK+1GOkQIDAQAB","manifest_version":2,"name":"Google Hangouts","permissions":["desktopCapture","processes","system.cpu","webrtcAudioPrivate","webrtcDesktopCapturePrivate","webrtcLoggingPrivate"],"version":"1.3.4"},"never_activated_since_loaded":true,"path":"/tmp/.mount_chromerNG7Rq/opt/google/chrome/resources/hangout_services","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":false,"was_installed_by_oem":false},"pjkljhegncpnkpknbcohdijeoejaedia":{"ack_external":true,"active_permissions":{"api":["notifications"],"manifest_permissions":[]},"app_launcher_ordinal":"y","commands":{},"content_settings":[],"creation_flags":137,"events":[],"from_bookmark":false,"from_webstore":true,"granted_permissions":{"api":["notifications"],"manifest_permissions":[]},"incognito_content_settings":[],"incognito_preferences":{},"install_time":"13176580428773173","location":1,"manifest":{"app":{"launch":{"container":"tab","web_url":"https://mail.google.com/mail/ca"},"urls":["*://mail.google.com/mail/ca"]},"current_locale":"en_US","default_locale":"en","description":"Fast, searchable email with less spam.","icons":{"128":"128.png"},"key":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCuGglK43iAz3J9BEYK/Mz6ZhloIMMDqQSAaf3vJt4eHbTbSDsu4WdQ9dQDRcKlg8nwQdePBt0C3PSUBtiSNSS37Z3qEGfS7LCju3h6pI1Yr9MQtxw+jUa7kXXIS09VV73pEFUT/F7c6Qe8L5ZxgAcBvXBh1Fie63qb02I9XQ/CQIDAQAB","name":"Gmail","options_page":"https://mail.google.com/mail/ca/#settings","permissions":["notifications"],"update_url":"http://clients2.google.com/service/update2/crx","version":"7"},"never_activated_since_loaded":true,"page_ordinal":"n","path":"pjkljhegncpnkpknbcohdijeoejaedia/7_0","preferences":{},"regular_only_preferences":{},"state":1,"was_installed_by_default":true,"was_installed_by_oem":false}},"toolbar":[]},"gcm":{"product_category_for_subtypes":"com.chrome.linux"},"http_original_content_length":"0","http_received_content_length":"0","invalidator":{"client_id":"x6cJ4hkDPcTtgUa+csbaeA=="},"language_model_counters":{"en":1},"media":{"device_id_salt":"j0B8rEZ8ji9OpqjrgXC85w=="},"pinned_tabs":[],"plugins":{"plugins_list":[]},"profile":{"avatar_bubble_tutorial_shown":2,"avatar_index":26,"content_settings":{"domain_to_origin_migration_status":1,"exceptions":{"app_banner":{},"auto_select_certificate":{},"automatic_downloads":{},"autoplay":{},"background_sync":{},"bluetooth_guard":{},"cookies":{},"durable_storage":{},"geolocation":{},"images":{},"important_site_info":{},"javascript":{},"media_stream_camera":{},"media_stream_mic":{},"midi_sysex":{},"mixed_script":{},"notifications":{},"password_protection":{},"permission_autoblocking_data":{},"plugins":{},"popups":{},"ppapi_broker":{},"prompt_no_decision_count":{},"protocol_handler":{},"site_engagement":{},"sound":{},"ssl_cert_decisions":{},"subresource_filter":{},"subresource_filter_data":{},"usb_chooser_data":{}},"pref_version":1},"created_by_version":"61.0.3163.100","exit_type":"Normal","exited_cleanly":true,"local_profile_id":1600579,"managed_user_id":"","name":"Person 1","was_obsolete_http_data_cleaned":true},"protection":{"macs":{"browser":{"show_home_button":"9DDE23BD288B95F7CE675BBD01A9E2B63A7624B8C3CDB431097FDF3F63AB4E51"},"default_search_provider_data":{"template_url_data":"705F2D2FDD2FF483A1A9E675DFD71CCB223E81A2CEBF5D20C031A68B0020CF77"},"extensions":{"settings":{"ahfgeienlihckogmohjhadlkjgocpleb":"0FACA21761F5C3C55A185815143676F25C5B9999CDE55683A1DAAA8F14CF43C7","aohghmighlieiainnegkcijnfilokake":"6FDAFC85728A6DAA39F4B7511D63202C34177A16A74C66D9E7434FF5423F3121","apdfllckaahabafndbhieahigkjlhalf":"7EA584EC2447622593D62423388BD9EBDD5301F59B5B2D497E5375CF3DBF330E","bepbmhgboaologfdajaanbcjmnhjmhfn":"1AF5697DC58855220EC37C72526ED6ADDC2D3D47161F97F5D99B6A849DB352D6","blpcfgokakmgnkcojhhkbfbldkacnbeo":"2E9C5F2E2257AFEC55D38438E75257FDAC52AC359E1C95C6F4B86169C4B02DFF","eemcgdkfndhakfknompkggombfjjjeno":"072CFBAA1125243D5CF25A4CB628747D1C160F2361435B43EAF6836C671A3A58","gfdkimpbcpahaombhbimeihdjnejgicl":"0CF62E42F1DDF107D90B9E552138565E970976856E54961F7EB7695AC2D13EEB","kmendfapggjehodndflmmgagdbamhnfd":"E250B95C88E352BE90C3A2C7BEEEAE0D5262C838841B5D1B1981766ACD8B9413","mfehgcgbbipciphmccgaenjidiccnmng":"C15FE16FFD5CCB478ABF593D8A95E3492AF9524D48585A9F8C71D1FBEC024D82","mhjfbmdgcfjbbpaeojofohoefgiehjai":"B08FBC6056E1041E83C81557B788114F3FCE26A250EE813DC29F872888D1B374","neajdppkdcdipfabeoofebfddakdcjhd":"9E766EFBA9F666D9A0DCB822C0AFAC0FDFC342BCC35EA7A50358CE85144FEE0C","nkeimhogjdpnpccoofpliimaahmaaome":"D5611CA0586D1FED0E07597645AC555D066C91283FBE63FBF8E389A94DF53E8D","pjkljhegncpnkpknbcohdijeoejaedia":"533DB683C863A1D815B1849069AF6166BDEF22FBEE3B4F732169348971BD0167"}},"google":{"services":{"account_id":"07620F46EF9994C94D86883494C13E89DC6509B3D4E8978B2E18F6776C85CDBF","last_account_id":"8452449E1468A5CF585BF23BDC52A3CA1BED67E36262AAE4BAC3583936F8B7AB","last_username":"C202CF3B01A560B8B7D71D3B0076B61126EF72F4B11D79B3EA6E3661DB757E93","username":"1CA30EB4EEE885888D93E71C93383D2E2A14715338EDF9B157FF935504B57767"}},"homepage":"B2A199504AEACAAD5C3A7BB4A96D9C3A9536D7A29672EB4DA3B9552B8D39C49C","homepage_is_newtabpage":"306C67E79E036278678ED45B3C668C4421665A206FC4B97F053015981C8BAAE2","pinned_tabs":"14F8B2B035A86C0AEA5637DFD2AA7F5BDEADD0AAFF13141260E56C9477047715","prefs":{"preference_reset_time":"7B22235E8A603BE387D81441C8C88F0C4E591567147FA05BE235C96189AC4490"},"safebrowsing":{"incidents_sent":"F1827D0C55798CE7843DAF5DDEAB06A9BB2F9628970A5DCDA2543102436E4749"},"search_provider_overrides":"99AC1EA12DA6196886F08A934B3B5006A725063DF41E9D0EE38F1FCFFDFDD5B0","session":{"restore_on_startup":"7BADFD2212B8A15263FDE51964FD3BAA8E29BF70E76A05BFC8C68CFFEE5706AA","startup_urls":"C1B359171D6112C9E4C5F9FA96ABAF6B61E8A18C14D75E6A86F5561B2FB9AD2A"}}},"protocol_handler":{"excluded_schemes":{"afp":true,"data":true,"disk":true,"disks":true,"file":true,"hcp":true,"javascript":true,"mailto":false,"ms-help":true,"news":false,"nntp":true,"shell":true,"snews":false,"vbscript":true,"view-source":true,"vnd":{"ms":{"radio":true}}}},"safebrowsing":{"scout_group_selected":true},"session":{"restore_on_startup":4,"startup_urls":["http://localhost:8000/"]},"spellcheck":{"dictionaries":["en-US"],"dictionary":""}}
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/QuotaManager b/nichrome/home/user/.config/google-chrome/Default/QuotaManager
new file mode 100644
index 000000000..5f3869624
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/QuotaManager differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/QuotaManager-journal b/nichrome/home/user/.config/google-chrome/Default/QuotaManager-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/README b/nichrome/home/user/.config/google-chrome/Default/README
new file mode 100644
index 000000000..98d9d2785
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/README
@@ -0,0 +1 @@
+Google Chrome settings and storage represent user-selected preferences and information and MUST not be extracted, overwritten or modified except through Google Chrome defined APIs.
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Secure Preferences b/nichrome/home/user/.config/google-chrome/Default/Secure Preferences
new file mode 100644
index 000000000..f06075202
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Secure Preferences
@@ -0,0 +1 @@
+{"protection":{"super_mac":"33F663353631B144EA660B5F809D89BA41CAF954EE5776BE5004BB589CA96BE1"}}
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Default/Session Storage/000003.log b/nichrome/home/user/.config/google-chrome/Default/Session Storage/000003.log
new file mode 100644
index 000000000..e81ba6766
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Session Storage/000003.log differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Session Storage/CURRENT b/nichrome/home/user/.config/google-chrome/Default/Session Storage/CURRENT
new file mode 100644
index 000000000..7ed683d17
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Session Storage/CURRENT
@@ -0,0 +1 @@
+MANIFEST-000001
diff --git a/nichrome/home/user/.config/google-chrome/Default/Session Storage/LOCK b/nichrome/home/user/.config/google-chrome/Default/Session Storage/LOCK
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Session Storage/LOG b/nichrome/home/user/.config/google-chrome/Default/Session Storage/LOG
new file mode 100644
index 000000000..114e9f882
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/Session Storage/LOG
@@ -0,0 +1 @@
+2018/07/20-17:15:01.520 2498 Reusing MANIFEST /home/user/.config/google-chrome/Default/Session Storage/MANIFEST-000001
diff --git a/nichrome/home/user/.config/google-chrome/Default/Session Storage/MANIFEST-000001 b/nichrome/home/user/.config/google-chrome/Default/Session Storage/MANIFEST-000001
new file mode 100644
index 000000000..18e5cab72
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Session Storage/MANIFEST-000001 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Shortcuts b/nichrome/home/user/.config/google-chrome/Default/Shortcuts
new file mode 100644
index 000000000..27fef1a73
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Shortcuts differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Shortcuts-journal b/nichrome/home/user/.config/google-chrome/Default/Shortcuts-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Top Sites b/nichrome/home/user/.config/google-chrome/Default/Top Sites
new file mode 100644
index 000000000..2ceff122e
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Top Sites differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Top Sites-journal b/nichrome/home/user/.config/google-chrome/Default/Top Sites-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/Visited Links b/nichrome/home/user/.config/google-chrome/Default/Visited Links
new file mode 100644
index 000000000..69b38d8f4
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Visited Links differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Web Data b/nichrome/home/user/.config/google-chrome/Default/Web Data
new file mode 100644
index 000000000..a05857713
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/Web Data differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/Web Data-journal b/nichrome/home/user/.config/google-chrome/Default/Web Data-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/000005.log b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/000005.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/CURRENT b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/CURRENT
new file mode 100644
index 000000000..cacca7574
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/CURRENT
@@ -0,0 +1 @@
+MANIFEST-000004
diff --git a/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOCK b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOCK
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOG b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOG
new file mode 100644
index 000000000..ab274fffe
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOG
@@ -0,0 +1,3 @@
+2018/07/20-17:25:34.212 2883 Recovering log #3
+2018/07/20-17:25:34.212 2883 Delete type=3 #2
+2018/07/20-17:25:34.212 2883 Delete type=0 #3
diff --git a/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOG.old b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOG.old
new file mode 100644
index 000000000..29925d614
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/LOG.old
@@ -0,0 +1 @@
+2018/07/20-17:13:46.148 2498 Delete type=3 #1
diff --git a/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/MANIFEST-000004 b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/MANIFEST-000004
new file mode 100644
index 000000000..0a6e9237f
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/data_reduction_proxy_leveldb/MANIFEST-000004 differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/databases/Databases.db b/nichrome/home/user/.config/google-chrome/Default/databases/Databases.db
new file mode 100644
index 000000000..c330fac20
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/databases/Databases.db differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/databases/Databases.db-journal b/nichrome/home/user/.config/google-chrome/Default/databases/Databases.db-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Default/previews_opt_out.db b/nichrome/home/user/.config/google-chrome/Default/previews_opt_out.db
new file mode 100644
index 000000000..5c951f52b
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Default/previews_opt_out.db differ
diff --git a/nichrome/home/user/.config/google-chrome/Default/previews_opt_out.db-journal b/nichrome/home/user/.config/google-chrome/Default/previews_opt_out.db-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/First Run b/nichrome/home/user/.config/google-chrome/First Run
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/Local State b/nichrome/home/user/.config/google-chrome/Local State
new file mode 100644
index 000000000..75d5541fb
--- /dev/null
+++ b/nichrome/home/user/.config/google-chrome/Local State
@@ -0,0 +1 @@
+{"browser":{"last_redirect_origin":""},"easy_unlock":{"device_id":"db633022-5ddd-4b74-bc8d-53c5bd2e17b2"},"gl_renderer_string":"Google SwiftShader","gl_vendor_string":"Google Inc.","gl_version_string":"OpenGL ES 2.0 SwiftShader","hardware_acceleration_mode_previous":true,"policy":{"last_statistics_update":"13176580425380815"},"profile":{"info_cache":{"Default":{"active_time":1532106841.514689,"avatar_icon":"chrome://theme/IDR_PROFILE_AVATAR_26","background_apps":false,"gaia_id":"","is_ephemeral":false,"is_omitted_from_profile_list":false,"is_using_default_avatar":true,"is_using_default_name":true,"managed_user_id":"","name":"Person 1","user_name":""}},"last_active_profiles":["Default"]},"rappor":{"cohort_seed":477,"last_daily_sample":"13176580456555149","secret":"TgqgQjiH7x1jJ68Bhrxfr9dMf/ujpRLwh7o0ruPucXvmP7GHTBQtvoHtj1kqKt2o"},"show-first-run-bubble-option":0,"shutdown":{"num_processes":2,"num_processes_slow":0,"type":1},"startup_metric":{"last_startup_timestamp":"13176581131070000","last_startup_version":"61.0.3163.100","same_version_startup_count":1},"supervised_users":{"whitelists":{}},"uninstall_metrics":{"installation_date2":"1532106825","launch_count":"2","page_load_count":"12","uptime_sec":"691"},"user_experience_metrics":{"client_id2":"e663dba7-466a-43d0-8a03-826b03f69486","client_id_timestamp":"1532106841","default_opt_in":2,"initial_logs2":[],"last_seen":{"CrashpadMetrics":"0"},"low_entropy_source2":3566,"ongoing_logs2":[{"data":"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","hash":"8qIYXPNO/LvSoVBYeyjm/qi2rSs=","timestamp":"1532106901"},{"data":"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","hash":"ciG35VTSvwjaMwAHAofSIO5+bVo=","timestamp":"1532107517"}],"reporting_enabled":true,"session_id":1,"stability":{"breakpad_registration_fail":0,"breakpad_registration_ok":1,"child_process_crash_count":1,"crash_count":0,"debugger_not_present":1,"debugger_present":0,"deferred_count":0,"discard_count":0,"execution_phase":700,"exited_cleanly":true,"extension_renderer_crash_count":0,"extension_renderer_failed_launch_count":0,"extension_renderer_launch_count":0,"incomplete_session_end_count":0,"launch_count":1,"page_load_count":9,"plugin_stats2":[],"renderer_crash_count":0,"renderer_failed_launch_count":0,"renderer_hang_count":0,"renderer_launch_count":4,"saved_system_profile":"CNDrh84FEhA2MS4wLjMxNjMuMTAwLTY0GJCqyNoFIgVlbi1VUyoPCgVMaW51eBIGNC4xMi43MnIKBng4Nl82NBDpHSIAKAEw1go4gAZCOggAEAAaBzMuMy4wLjIiCjIwMTcvMDQvMDcyC0dvb2dsZSBJbmMuOhJHb29nbGUgU3dpZnRTaGFkZXJlAACAP2oUCgxHZW51aW5lSW50ZWwQyY0UGAKCAQCKAQA6OwoRQ2hyb21lIFBERiBWaWV3ZXISIG1oamZibWRnY2ZqYmJwYWVvam9mb2hvZWZnaWVoamFpGgAgACgAOjsKD1Nob2Nrd2F2ZSBGbGFzaBIYaW50ZXJuYWwtbm90LXlldC1wcmVzZW50GgoyNC4wLjAuMTg5IAAoATpOCiJXaWRldmluZSBDb250ZW50IERlY3J5cHRpb24gTW9kdWxlEhhsaWJ3aWRldmluZWNkbWFkYXB0ZXIuc28aCjEuNC44LjEwMDggACgBOisKDU5hdGl2ZSBDbGllbnQSFGludGVybmFsLW5hY2wtcGx1Z2luGgAgACgBOi4KEUNocm9tZSBQREYgUGx1Z2luEhNpbnRlcm5hbC1wZGYtdmlld2VyGgAgACgBSgoNMZBVDBX09Ec9UARiAGoMCAAQBxgAIAY4AEAAgAGQqsjaBZABlgGQAdEBkAHvAZAB4AKQAYgDkAGRBJABtgSQAeQEkAHHBZAB7QaQAZMHkAGnB5gBArABAQ==","saved_system_profile_hash":"518D024AB868CFDB52F6C346B7B6DC2C8F267874","session_end_completed":true,"stats_buildtime":"1505883600","stats_version":"61.0.3163.100-64","version_mismatch_count":0}},"was":{"restarted":false}}
\ No newline at end of file
diff --git a/nichrome/home/user/.config/google-chrome/Safe Browsing Cookies b/nichrome/home/user/.config/google-chrome/Safe Browsing Cookies
new file mode 100644
index 000000000..401f09539
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/Safe Browsing Cookies differ
diff --git a/nichrome/home/user/.config/google-chrome/Safe Browsing Cookies-journal b/nichrome/home/user/.config/google-chrome/Safe Browsing Cookies-journal
new file mode 100644
index 000000000..e69de29bb
diff --git a/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_0 b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_0
new file mode 100644
index 000000000..d76fb77e9
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_0 differ
diff --git a/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_1 b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_1
new file mode 100644
index 000000000..a545dac39
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_1 differ
diff --git a/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_2 b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_2
new file mode 100644
index 000000000..c7e2eb9ad
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_2 differ
diff --git a/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_3 b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_3
new file mode 100644
index 000000000..5eec97358
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/data_3 differ
diff --git a/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/index b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/index
new file mode 100644
index 000000000..99361f7e0
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/ShaderCache/GPUCache/index differ
diff --git a/nichrome/home/user/.config/google-chrome/chrome_shutdown_ms.txt b/nichrome/home/user/.config/google-chrome/chrome_shutdown_ms.txt
new file mode 100644
index 000000000..f5c03ffce
Binary files /dev/null and b/nichrome/home/user/.config/google-chrome/chrome_shutdown_ms.txt differ
diff --git a/nichrome/logo/logo_linux_clut224.ppm b/nichrome/logo/logo_linux_clut224.ppm
new file mode 100644
index 000000000..9f6ce73cc
--- /dev/null
+++ b/nichrome/logo/logo_linux_clut224.ppm
@@ -0,0 +1,24303 @@
+P3
+90 90
+255
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+4
+2
+2
+4
+2
+2
+4
+2
+2
+4
+2
+2
+4
+2
+2
+4
+2
+2
+4
+2
+2
+4
+2
+2
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+2
+2
+1
+4
+2
+2
+4
+4
+2
+6
+4
+2
+6
+6
+2
+8
+6
+3
+8
+8
+3
+10
+8
+4
+10
+8
+4
+10
+8
+4
+10
+8
+4
+10
+8
+4
+10
+8
+4
+8
+8
+3
+8
+6
+3
+6
+6
+2
+6
+4
+2
+4
+4
+2
+4
+2
+2
+2
+2
+1
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+1
+4
+2
+2
+6
+4
+2
+6
+6
+3
+10
+8
+4
+12
+8
+4
+14
+10
+5
+16
+12
+6
+20
+14
+7
+22
+16
+8
+23
+18
+9
+25
+19
+9
+25
+19
+9
+27
+19
+10
+27
+19
+10
+25
+19
+9
+25
+19
+9
+23
+18
+9
+22
+16
+8
+20
+14
+7
+16
+12
+6
+14
+10
+5
+12
+10
+4
+10
+8
+4
+6
+6
+3
+6
+4
+2
+4
+2
+2
+2
+2
+1
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+4
+2
+2
+6
+4
+2
+8
+6
+3
+12
+8
+4
+14
+10
+5
+20
+14
+7
+23
+18
+9
+27
+21
+11
+33
+25
+13
+37
+27
+14
+40
+31
+15
+46
+34
+18
+49
+36
+18
+51
+38
+20
+53
+40
+20
+55
+41
+21
+55
+41
+21
+53
+40
+20
+51
+38
+20
+49
+36
+18
+46
+34
+18
+40
+31
+15
+37
+27
+13
+33
+25
+13
+27
+21
+11
+23
+18
+9
+20
+14
+7
+16
+12
+6
+12
+8
+4
+8
+6
+3
+6
+4
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+2
+2
+0
+4
+4
+2
+6
+6
+2
+10
+8
+4
+15
+12
+5
+20
+16
+7
+25
+19
+9
+33
+25
+13
+40
+31
+16
+48
+36
+18
+55
+41
+21
+62
+47
+23
+69
+52
+26
+74
+55
+28
+80
+60
+30
+85
+64
+33
+89
+65
+34
+90
+69
+34
+92
+68
+35
+92
+68
+35
+90
+69
+34
+89
+65
+34
+84
+64
+32
+80
+60
+30
+74
+55
+28
+69
+52
+26
+62
+47
+23
+55
+41
+21
+48
+36
+18
+40
+31
+16
+33
+25
+13
+27
+19
+10
+22
+16
+8
+16
+12
+6
+10
+8
+4
+8
+6
+2
+4
+4
+2
+2
+2
+0
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+4
+4
+2
+8
+6
+2
+12
+8
+4
+18
+14
+7
+23
+18
+9
+33
+25
+13
+42
+31
+16
+51
+38
+20
+62
+47
+23
+74
+55
+28
+84
+62
+32
+93
+68
+36
+101
+75
+39
+109
+81
+42
+115
+85
+43
+118
+88
+45
+125
+93
+47
+128
+95
+49
+132
+98
+50
+134
+100
+51
+134
+100
+51
+132
+98
+50
+128
+95
+49
+125
+93
+47
+119
+90
+46
+115
+85
+43
+109
+81
+42
+101
+75
+39
+93
+68
+36
+84
+62
+32
+74
+55
+28
+62
+47
+24
+53
+40
+20
+42
+32
+16
+33
+25
+13
+25
+19
+9
+18
+14
+7
+12
+10
+4
+8
+6
+2
+4
+4
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+6
+6
+2
+12
+8
+4
+18
+14
+7
+25
+19
+9
+37
+27
+13
+48
+36
+18
+60
+45
+23
+74
+55
+28
+87
+65
+33
+100
+75
+38
+112
+84
+43
+123
+91
+47
+132
+98
+50
+142
+106
+55
+157
+120
+69
+174
+139
+90
+195
+163
+120
+214
+185
+147
+223
+196
+163
+231
+207
+177
+238
+216
+189
+238
+216
+189
+231
+207
+177
+223
+196
+163
+214
+185
+147
+195
+163
+120
+174
+139
+90
+157
+120
+69
+142
+106
+55
+132
+98
+50
+123
+91
+47
+112
+84
+43
+101
+75
+39
+89
+65
+34
+74
+55
+28
+62
+45
+23
+49
+36
+18
+37
+27
+14
+27
+19
+10
+18
+14
+7
+12
+8
+4
+8
+6
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+6
+4
+2
+10
+8
+4
+18
+12
+7
+25
+19
+9
+37
+27
+14
+51
+38
+20
+65
+48
+25
+80
+60
+31
+96
+72
+37
+112
+83
+43
+125
+93
+47
+138
+103
+52
+164
+128
+76
+198
+166
+123
+238
+216
+189
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+238
+216
+189
+198
+166
+123
+164
+128
+76
+140
+105
+53
+127
+94
+48
+112
+84
+43
+98
+73
+37
+81
+60
+30
+67
+48
+25
+51
+38
+20
+38
+27
+15
+25
+19
+9
+18
+12
+7
+10
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+8
+6
+3
+14
+10
+5
+23
+18
+9
+35
+25
+13
+49
+36
+18
+65
+48
+25
+84
+62
+32
+101
+75
+39
+118
+88
+45
+134
+100
+51
+157
+120
+69
+200
+169
+128
+252
+233
+212
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+252
+234
+213
+209
+181
+143
+161
+126
+77
+135
+101
+51
+119
+90
+46
+103
+76
+39
+85
+64
+33
+65
+48
+25
+49
+36
+18
+35
+27
+13
+23
+18
+9
+15
+12
+5
+8
+6
+3
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+6
+4
+2
+10
+8
+4
+18
+14
+7
+29
+21
+11
+44
+32
+17
+60
+45
+23
+80
+60
+31
+100
+75
+39
+119
+90
+46
+137
+102
+53
+171
+136
+89
+238
+216
+189
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+252
+234
+213
+236
+212
+185
+223
+196
+163
+206
+176
+137
+189
+157
+114
+181
+148
+101
+177
+141
+91
+171
+136
+89
+171
+136
+89
+177
+141
+91
+181
+148
+101
+194
+161
+116
+206
+176
+137
+223
+196
+163
+236
+212
+185
+252
+234
+213
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+242
+220
+194
+178
+144
+98
+138
+103
+52
+121
+90
+46
+101
+75
+39
+80
+60
+31
+62
+45
+23
+44
+32
+17
+29
+21
+11
+18
+14
+7
+10
+8
+4
+6
+4
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+6
+4
+2
+12
+10
+5
+22
+16
+9
+35
+27
+13
+53
+40
+20
+72
+54
+28
+95
+70
+36
+116
+87
+44
+135
+101
+51
+178
+144
+98
+246
+225
+201
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+240
+218
+192
+209
+181
+143
+181
+148
+101
+151
+114
+61
+140
+105
+53
+134
+100
+51
+128
+95
+49
+123
+91
+47
+119
+90
+46
+118
+88
+45
+116
+87
+44
+116
+87
+44
+118
+88
+45
+119
+90
+46
+123
+91
+47
+128
+95
+49
+134
+100
+51
+140
+105
+53
+153
+116
+63
+181
+148
+101
+209
+181
+143
+240
+218
+192
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+243
+222
+198
+178
+144
+98
+136
+101
+51
+116
+87
+44
+95
+70
+36
+72
+54
+28
+53
+40
+20
+35
+27
+13
+22
+16
+9
+12
+10
+5
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+14
+10
+5
+25
+19
+9
+40
+31
+15
+60
+45
+23
+82
+62
+31
+106
+79
+40
+128
+95
+49
+157
+120
+69
+234
+210
+181
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+249
+228
+206
+214
+185
+147
+174
+139
+90
+142
+106
+55
+131
+98
+50
+121
+90
+46
+110
+82
+42
+101
+75
+39
+95
+70
+36
+89
+65
+34
+84
+62
+32
+79
+59
+30
+77
+57
+30
+74
+56
+28
+74
+56
+28
+77
+57
+30
+79
+59
+30
+84
+62
+32
+89
+65
+34
+95
+70
+36
+101
+75
+39
+110
+82
+42
+121
+90
+46
+131
+98
+50
+142
+105
+54
+174
+139
+90
+214
+185
+147
+249
+229
+207
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+237
+214
+187
+161
+126
+77
+128
+95
+49
+106
+79
+40
+84
+62
+32
+60
+45
+23
+40
+31
+16
+25
+19
+9
+14
+10
+5
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+16
+12
+6
+27
+21
+11
+44
+32
+17
+65
+48
+25
+90
+67
+34
+116
+87
+44
+138
+103
+52
+206
+176
+137
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+247
+227
+204
+206
+176
+137
+155
+117
+63
+134
+100
+51
+119
+90
+46
+106
+79
+40
+93
+68
+36
+81
+60
+30
+72
+54
+28
+62
+47
+24
+55
+41
+21
+51
+38
+20
+48
+36
+18
+44
+32
+17
+42
+32
+16
+42
+31
+16
+42
+31
+16
+42
+32
+16
+44
+32
+17
+48
+36
+18
+51
+38
+20
+55
+41
+21
+62
+47
+24
+72
+54
+28
+81
+60
+30
+93
+68
+36
+106
+79
+40
+118
+88
+45
+134
+100
+51
+153
+116
+63
+200
+169
+128
+246
+225
+201
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+206
+176
+137
+140
+105
+53
+116
+87
+44
+90
+69
+34
+67
+50
+25
+44
+32
+17
+27
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+16
+12
+6
+29
+21
+11
+48
+36
+18
+70
+54
+27
+96
+72
+37
+123
+91
+47
+153
+116
+63
+237
+214
+187
+255
+237
+218
+255
+237
+218
+255
+237
+218
+251
+231
+210
+204
+173
+133
+151
+114
+61
+131
+98
+50
+113
+85
+43
+97
+73
+37
+82
+62
+31
+69
+50
+26
+55
+41
+21
+48
+34
+18
+40
+29
+15
+33
+25
+13
+29
+21
+11
+25
+19
+9
+23
+18
+9
+22
+16
+8
+20
+16
+7
+20
+14
+7
+20
+14
+7
+20
+16
+7
+22
+16
+8
+23
+18
+9
+25
+19
+9
+29
+21
+11
+33
+25
+13
+40
+29
+15
+48
+34
+18
+55
+41
+21
+69
+50
+26
+81
+60
+30
+97
+73
+37
+113
+85
+43
+131
+97
+50
+151
+114
+61
+204
+173
+133
+251
+231
+210
+255
+237
+218
+255
+237
+218
+255
+237
+218
+240
+218
+192
+157
+119
+65
+123
+91
+47
+96
+72
+37
+70
+54
+27
+48
+36
+18
+29
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+16
+12
+6
+29
+21
+11
+49
+36
+18
+74
+55
+28
+101
+75
+39
+128
+95
+49
+174
+139
+90
+252
+234
+213
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+161
+126
+77
+134
+100
+51
+113
+85
+43
+95
+70
+36
+77
+57
+30
+62
+45
+23
+48
+36
+18
+37
+29
+14
+29
+21
+11
+23
+18
+9
+18
+14
+7
+15
+12
+5
+12
+10
+4
+10
+8
+4
+10
+8
+4
+8
+6
+2
+8
+6
+2
+8
+6
+2
+8
+6
+2
+8
+6
+2
+8
+6
+3
+10
+8
+4
+10
+8
+4
+12
+10
+4
+15
+12
+5
+18
+14
+7
+23
+18
+9
+29
+21
+11
+38
+29
+15
+48
+36
+18
+62
+45
+23
+77
+57
+30
+95
+70
+36
+113
+85
+43
+134
+100
+51
+164
+128
+76
+226
+200
+167
+255
+237
+218
+255
+237
+218
+255
+237
+218
+252
+233
+212
+174
+139
+90
+128
+95
+49
+101
+75
+39
+74
+55
+28
+49
+36
+18
+31
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+1
+6
+6
+2
+15
+12
+5
+27
+21
+11
+48
+36
+18
+74
+55
+28
+103
+76
+39
+128
+96
+49
+185
+153
+108
+255
+237
+218
+255
+237
+218
+255
+237
+218
+251
+231
+210
+194
+161
+116
+140
+105
+53
+121
+90
+46
+98
+73
+37
+79
+59
+30
+60
+45
+23
+46
+34
+18
+33
+25
+13
+25
+19
+9
+18
+14
+7
+14
+10
+5
+10
+8
+4
+8
+6
+3
+6
+4
+2
+4
+4
+2
+4
+2
+2
+4
+2
+2
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+4
+2
+2
+4
+2
+2
+4
+4
+2
+6
+4
+2
+8
+6
+3
+10
+8
+4
+14
+10
+5
+18
+14
+7
+23
+20
+9
+33
+25
+13
+45
+34
+17
+60
+45
+23
+77
+59
+30
+98
+73
+37
+119
+90
+46
+140
+105
+53
+194
+161
+116
+251
+231
+210
+255
+237
+218
+255
+237
+218
+255
+237
+218
+189
+157
+114
+131
+98
+50
+103
+78
+39
+74
+55
+28
+49
+36
+19
+29
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+10
+4
+23
+18
+9
+44
+32
+17
+70
+52
+27
+100
+75
+38
+128
+95
+49
+198
+166
+123
+255
+237
+218
+255
+237
+218
+255
+237
+218
+238
+216
+189
+170
+134
+84
+132
+98
+50
+109
+81
+42
+85
+64
+33
+65
+48
+25
+48
+34
+18
+33
+25
+13
+23
+18
+9
+16
+12
+6
+10
+8
+4
+8
+6
+2
+4
+4
+2
+4
+2
+2
+2
+2
+0
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+2
+2
+0
+4
+2
+2
+4
+4
+2
+8
+6
+2
+10
+8
+4
+16
+12
+6
+23
+18
+9
+33
+25
+13
+48
+34
+18
+65
+48
+25
+85
+64
+33
+109
+81
+42
+132
+98
+50
+170
+134
+84
+240
+218
+192
+255
+237
+218
+255
+237
+218
+255
+237
+218
+200
+169
+128
+132
+98
+50
+103
+78
+39
+74
+55
+28
+48
+36
+18
+27
+21
+11
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+18
+14
+7
+35
+27
+13
+60
+45
+23
+90
+67
+34
+122
+91
+46
+198
+166
+123
+255
+237
+218
+255
+237
+218
+255
+237
+218
+231
+207
+177
+155
+117
+63
+125
+93
+47
+100
+75
+39
+74
+56
+28
+55
+41
+21
+38
+29
+15
+25
+19
+9
+16
+12
+6
+10
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+4
+2
+2
+6
+4
+2
+10
+8
+4
+16
+12
+6
+25
+19
+9
+38
+27
+15
+55
+41
+21
+74
+56
+28
+100
+75
+39
+125
+93
+47
+153
+116
+63
+231
+207
+177
+255
+237
+218
+255
+237
+218
+255
+237
+218
+200
+169
+128
+132
+98
+50
+101
+75
+39
+70
+52
+27
+44
+32
+17
+23
+18
+9
+12
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+8
+4
+25
+19
+9
+46
+34
+18
+74
+55
+28
+106
+79
+40
+178
+144
+98
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+146
+110
+59
+118
+88
+45
+93
+70
+36
+69
+50
+26
+48
+34
+18
+31
+23
+11
+20
+14
+7
+12
+8
+4
+6
+6
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+6
+6
+2
+12
+10
+4
+20
+16
+7
+31
+23
+11
+48
+36
+18
+69
+52
+26
+93
+70
+36
+121
+90
+46
+148
+112
+59
+226
+200
+167
+255
+237
+218
+255
+237
+218
+255
+237
+218
+189
+157
+114
+128
+96
+49
+95
+72
+36
+62
+47
+23
+35
+27
+13
+18
+14
+7
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+29
+21
+11
+53
+40
+20
+82
+62
+31
+157
+120
+69
+255
+237
+218
+255
+237
+218
+255
+237
+218
+223
+196
+163
+140
+105
+53
+116
+87
+44
+90
+67
+34
+62
+47
+24
+42
+32
+16
+27
+19
+10
+16
+12
+6
+8
+6
+3
+4
+4
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+6
+4
+2
+10
+6
+4
+16
+12
+6
+27
+19
+10
+42
+32
+16
+65
+48
+25
+93
+70
+36
+125
+93
+47
+151
+114
+61
+226
+200
+167
+255
+237
+218
+255
+237
+218
+255
+237
+218
+174
+139
+90
+118
+88
+45
+80
+60
+31
+48
+36
+18
+25
+19
+9
+12
+8
+4
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+31
+23
+11
+53
+40
+20
+93
+71
+40
+252
+234
+213
+255
+237
+218
+255
+237
+218
+228
+203
+173
+134
+100
+51
+109
+81
+42
+85
+64
+33
+60
+45
+23
+40
+29
+15
+23
+18
+9
+14
+10
+5
+8
+6
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+2
+14
+10
+5
+25
+19
+9
+44
+32
+17
+69
+52
+26
+101
+75
+39
+137
+102
+53
+168
+130
+77
+234
+210
+181
+255
+237
+218
+255
+237
+218
+252
+234
+213
+146
+110
+59
+97
+73
+37
+60
+45
+23
+31
+23
+12
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+2
+16
+12
+6
+29
+21
+11
+51
+38
+19
+171
+136
+89
+189
+157
+114
+195
+163
+120
+185
+153
+108
+117
+88
+46
+98
+73
+37
+79
+59
+30
+56
+43
+22
+38
+29
+15
+23
+18
+9
+14
+10
+5
+8
+6
+3
+4
+4
+2
+4
+2
+2
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+2
+16
+12
+6
+29
+21
+11
+53
+40
+20
+87
+65
+33
+125
+94
+47
+157
+119
+65
+177
+141
+91
+252
+233
+212
+255
+237
+218
+255
+237
+218
+236
+212
+185
+106
+79
+40
+67
+50
+25
+37
+27
+13
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+1
+6
+4
+2
+10
+8
+4
+18
+14
+7
+29
+21
+11
+44
+32
+17
+62
+47
+23
+77
+57
+30
+87
+65
+33
+90
+67
+34
+84
+62
+32
+72
+54
+28
+55
+41
+21
+40
+31
+15
+27
+21
+11
+18
+14
+7
+14
+10
+5
+10
+8
+4
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+8
+6
+3
+6
+6
+3
+6
+4
+2
+6
+4
+2
+4
+4
+2
+4
+4
+2
+2
+2
+1
+2
+2
+0
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+8
+4
+25
+19
+9
+49
+36
+18
+84
+62
+32
+125
+93
+47
+157
+119
+65
+200
+169
+128
+255
+237
+218
+255
+237
+218
+255
+237
+218
+236
+212
+185
+109
+81
+42
+69
+52
+26
+37
+27
+14
+18
+14
+7
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+2
+2
+1
+6
+4
+2
+10
+8
+4
+16
+12
+6
+23
+18
+9
+33
+25
+13
+44
+32
+17
+55
+41
+21
+65
+48
+25
+70
+54
+27
+72
+54
+28
+67
+50
+25
+56
+43
+22
+48
+34
+18
+38
+29
+15
+31
+23
+11
+25
+19
+9
+23
+18
+9
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+22
+16
+8
+20
+16
+7
+20
+14
+7
+18
+14
+7
+16
+12
+6
+14
+10
+5
+12
+10
+4
+10
+8
+4
+8
+6
+2
+6
+4
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+29
+21
+11
+55
+40
+20
+90
+67
+34
+131
+97
+50
+168
+130
+77
+246
+225
+201
+255
+237
+218
+255
+237
+218
+255
+237
+218
+161
+126
+77
+103
+78
+39
+65
+48
+25
+35
+27
+13
+18
+14
+6
+8
+6
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+6
+4
+2
+12
+10
+5
+20
+16
+7
+29
+21
+11
+38
+29
+15
+49
+36
+18
+56
+43
+22
+65
+48
+25
+70
+52
+27
+72
+54
+28
+72
+54
+28
+69
+50
+26
+63
+47
+25
+56
+43
+22
+53
+40
+20
+49
+36
+19
+48
+36
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+46
+34
+18
+44
+32
+17
+42
+31
+16
+40
+29
+15
+37
+27
+14
+33
+25
+13
+29
+21
+11
+23
+18
+9
+20
+14
+7
+14
+10
+5
+10
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+18
+14
+7
+37
+27
+14
+67
+50
+25
+103
+78
+39
+142
+106
+55
+214
+185
+147
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+134
+100
+51
+93
+70
+36
+58
+43
+23
+35
+25
+13
+20
+14
+7
+10
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+1
+6
+4
+2
+14
+10
+5
+25
+19
+9
+38
+29
+15
+53
+40
+20
+67
+50
+25
+79
+59
+30
+87
+63
+33
+92
+68
+35
+93
+70
+36
+95
+70
+36
+93
+70
+36
+92
+68
+35
+90
+67
+34
+87
+65
+33
+85
+64
+33
+84
+62
+32
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+82
+62
+31
+81
+60
+30
+80
+60
+31
+77
+59
+30
+74
+55
+28
+69
+52
+26
+63
+47
+25
+55
+41
+21
+49
+36
+18
+40
+31
+15
+31
+23
+12
+23
+18
+9
+16
+12
+6
+10
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+10
+5
+27
+19
+11
+51
+38
+20
+85
+64
+33
+123
+91
+47
+168
+130
+77
+252
+233
+212
+255
+237
+218
+255
+237
+218
+242
+220
+194
+155
+117
+63
+116
+87
+44
+80
+60
+31
+53
+40
+20
+35
+25
+13
+23
+18
+9
+18
+12
+7
+12
+8
+4
+8
+6
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+10
+4
+25
+19
+9
+42
+31
+16
+62
+47
+24
+85
+64
+33
+103
+78
+39
+118
+88
+45
+127
+94
+48
+128
+96
+49
+131
+97
+50
+131
+97
+50
+131
+97
+50
+128
+95
+49
+128
+95
+49
+128
+96
+49
+127
+94
+48
+127
+94
+48
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+125
+94
+47
+127
+94
+48
+127
+94
+48
+127
+94
+48
+127
+94
+48
+127
+94
+48
+127
+94
+48
+127
+94
+48
+125
+94
+47
+125
+93
+47
+121
+90
+46
+116
+87
+44
+112
+83
+43
+103
+78
+39
+95
+72
+36
+85
+64
+33
+72
+54
+28
+60
+45
+23
+46
+34
+18
+33
+25
+13
+23
+18
+9
+14
+10
+5
+8
+6
+3
+4
+4
+2
+2
+2
+0
+2
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+20
+14
+7
+38
+29
+15
+69
+52
+26
+106
+78
+40
+142
+105
+54
+226
+200
+167
+255
+237
+218
+255
+237
+218
+255
+237
+218
+185
+153
+108
+134
+100
+51
+100
+75
+38
+70
+54
+27
+53
+40
+20
+42
+32
+16
+37
+27
+13
+29
+21
+11
+22
+16
+9
+14
+10
+5
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+10
+6
+4
+20
+16
+7
+38
+29
+15
+63
+47
+25
+93
+68
+36
+137
+102
+53
+185
+153
+108
+214
+185
+147
+214
+185
+147
+196
+162
+116
+196
+162
+116
+196
+162
+116
+196
+162
+116
+196
+162
+116
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+162
+115
+195
+163
+120
+200
+169
+128
+200
+169
+128
+168
+130
+77
+160
+123
+71
+148
+112
+59
+138
+103
+52
+127
+94
+48
+112
+84
+43
+96
+72
+37
+79
+59
+30
+60
+45
+23
+44
+32
+17
+29
+21
+11
+18
+14
+7
+10
+8
+4
+6
+4
+2
+2
+2
+1
+2
+2
+1
+6
+4
+2
+14
+10
+5
+29
+21
+11
+55
+41
+21
+90
+67
+34
+128
+95
+49
+181
+148
+101
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+148
+112
+59
+113
+85
+43
+85
+64
+33
+65
+48
+25
+58
+43
+23
+58
+43
+22
+67
+51
+27
+49
+36
+18
+38
+29
+15
+25
+19
+9
+14
+10
+5
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+29
+21
+11
+55
+41
+21
+87
+65
+33
+122
+91
+46
+240
+218
+192
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+247
+227
+204
+209
+181
+143
+164
+128
+76
+136
+101
+51
+116
+87
+44
+95
+72
+36
+74
+55
+28
+51
+38
+20
+33
+25
+13
+20
+16
+7
+10
+8
+4
+6
+4
+2
+6
+4
+2
+10
+8
+4
+22
+16
+9
+42
+32
+16
+74
+55
+28
+110
+82
+42
+148
+112
+59
+237
+214
+187
+255
+237
+218
+255
+237
+218
+252
+234
+213
+170
+134
+84
+127
+94
+48
+95
+72
+36
+74
+55
+28
+67
+50
+25
+72
+54
+28
+80
+60
+31
+209
+181
+143
+74
+55
+28
+58
+43
+22
+40
+29
+15
+23
+18
+9
+12
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+20
+14
+7
+40
+31
+15
+72
+54
+28
+109
+81
+42
+160
+123
+71
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+236
+212
+185
+170
+134
+84
+132
+98
+50
+107
+81
+42
+80
+60
+31
+55
+41
+21
+35
+25
+13
+20
+14
+7
+12
+8
+4
+10
+8
+4
+18
+12
+7
+33
+25
+13
+60
+45
+23
+95
+70
+36
+133
+99
+51
+198
+166
+123
+255
+237
+218
+255
+237
+218
+255
+237
+218
+214
+185
+147
+140
+105
+53
+106
+79
+40
+79
+59
+30
+67
+50
+26
+72
+54
+28
+89
+65
+34
+171
+136
+89
+255
+237
+218
+125
+94
+51
+81
+60
+30
+56
+43
+22
+35
+25
+13
+18
+14
+7
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+4
+2
+12
+8
+4
+25
+19
+9
+51
+38
+20
+87
+65
+33
+127
+94
+48
+209
+181
+143
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+142
+106
+55
+112
+83
+43
+80
+60
+31
+53
+40
+20
+31
+23
+12
+20
+14
+7
+18
+14
+7
+27
+19
+11
+48
+36
+18
+79
+59
+30
+116
+87
+44
+157
+119
+65
+247
+227
+204
+255
+237
+218
+255
+237
+218
+246
+225
+201
+157
+119
+65
+118
+88
+45
+87
+65
+33
+65
+48
+25
+63
+49
+25
+79
+59
+30
+108
+82
+45
+243
+222
+198
+255
+237
+218
+198
+166
+123
+103
+78
+39
+74
+56
+28
+46
+34
+18
+23
+18
+9
+10
+8
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+33
+25
+13
+62
+47
+23
+101
+75
+39
+142
+105
+54
+252
+234
+213
+255
+237
+218
+255
+237
+218
+195
+162
+115
+177
+141
+91
+168
+130
+77
+160
+123
+71
+159
+121
+68
+157
+119
+65
+157
+119
+65
+155
+117
+63
+155
+117
+63
+155
+117
+63
+155
+117
+63
+155
+117
+63
+155
+117
+63
+155
+117
+63
+155
+117
+63
+155
+117
+63
+157
+119
+65
+157
+119
+65
+157
+119
+65
+157
+119
+65
+157
+119
+65
+157
+119
+65
+159
+121
+68
+160
+123
+71
+160
+123
+71
+160
+123
+71
+160
+123
+71
+160
+123
+71
+159
+121
+68
+159
+121
+68
+157
+119
+65
+159
+121
+68
+168
+130
+77
+177
+141
+91
+196
+162
+116
+223
+196
+163
+249
+229
+207
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+242
+220
+194
+146
+110
+59
+103
+78
+39
+72
+54
+28
+44
+32
+17
+29
+21
+11
+27
+19
+11
+40
+29
+15
+65
+48
+25
+101
+75
+39
+140
+104
+53
+214
+185
+147
+255
+237
+218
+255
+237
+218
+255
+237
+218
+198
+166
+123
+134
+100
+51
+97
+73
+37
+69
+50
+26
+55
+41
+21
+62
+45
+23
+85
+64
+33
+137
+102
+53
+255
+237
+218
+255
+237
+218
+252
+233
+212
+127
+94
+48
+92
+68
+35
+58
+43
+23
+31
+23
+12
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+3
+20
+14
+7
+40
+31
+15
+74
+55
+28
+112
+84
+43
+168
+130
+77
+255
+237
+218
+255
+237
+218
+242
+220
+194
+168
+130
+77
+155
+117
+63
+138
+103
+52
+125
+93
+47
+116
+87
+44
+112
+84
+43
+110
+82
+42
+110
+82
+42
+110
+82
+42
+110
+82
+42
+110
+82
+42
+110
+82
+42
+110
+82
+42
+110
+82
+42
+112
+83
+43
+112
+84
+43
+112
+84
+43
+115
+85
+43
+115
+85
+44
+116
+87
+44
+116
+87
+44
+115
+85
+44
+113
+85
+43
+112
+84
+43
+112
+84
+43
+112
+84
+43
+112
+84
+43
+112
+84
+43
+112
+84
+43
+112
+84
+43
+112
+84
+43
+116
+87
+44
+119
+90
+46
+127
+94
+48
+135
+101
+51
+144
+108
+55
+159
+121
+68
+200
+169
+128
+249
+228
+206
+255
+237
+218
+255
+237
+218
+255
+237
+218
+249
+229
+207
+125
+94
+51
+87
+65
+33
+56
+43
+22
+40
+29
+15
+38
+29
+15
+55
+41
+21
+85
+64
+33
+123
+91
+47
+170
+134
+84
+252
+234
+213
+255
+237
+218
+255
+237
+218
+237
+214
+187
+148
+112
+59
+112
+83
+43
+74
+56
+28
+51
+38
+20
+45
+34
+17
+56
+43
+22
+85
+64
+33
+121
+90
+46
+240
+218
+192
+255
+237
+218
+255
+237
+218
+161
+126
+77
+107
+81
+42
+70
+54
+27
+40
+29
+15
+20
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+48
+36
+18
+84
+62
+32
+123
+91
+47
+200
+169
+128
+255
+237
+218
+255
+237
+218
+214
+185
+147
+151
+114
+61
+125
+93
+47
+101
+75
+39
+84
+62
+33
+74
+55
+28
+69
+52
+26
+67
+50
+26
+67
+50
+26
+67
+50
+26
+67
+50
+26
+67
+50
+26
+67
+50
+26
+67
+50
+26
+69
+52
+26
+70
+52
+27
+72
+54
+28
+74
+55
+28
+79
+59
+30
+80
+60
+31
+82
+62
+31
+80
+60
+31
+79
+59
+30
+74
+56
+28
+72
+54
+28
+70
+54
+27
+70
+52
+27
+69
+52
+26
+69
+52
+26
+69
+52
+26
+70
+52
+27
+70
+52
+27
+74
+55
+28
+77
+57
+30
+84
+62
+32
+93
+70
+36
+106
+79
+40
+125
+93
+47
+142
+105
+54
+164
+128
+76
+231
+207
+177
+255
+237
+218
+255
+237
+218
+255
+237
+218
+236
+212
+185
+95
+70
+36
+65
+48
+25
+49
+36
+18
+53
+40
+20
+74
+55
+28
+107
+81
+42
+144
+108
+55
+228
+203
+173
+255
+237
+218
+255
+237
+218
+255
+237
+218
+178
+144
+98
+127
+94
+48
+90
+67
+34
+58
+43
+22
+38
+29
+15
+37
+27
+13
+51
+38
+20
+84
+62
+32
+121
+90
+46
+209
+181
+143
+255
+237
+218
+255
+237
+218
+195
+163
+120
+121
+90
+46
+82
+62
+31
+48
+36
+18
+23
+18
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+4
+2
+12
+8
+4
+27
+21
+11
+55
+41
+21
+93
+68
+36
+132
+98
+50
+237
+214
+187
+255
+237
+218
+255
+237
+218
+181
+148
+101
+132
+98
+50
+100
+73
+38
+70
+52
+27
+51
+38
+20
+42
+31
+16
+37
+27
+13
+35
+25
+13
+35
+25
+13
+35
+25
+13
+35
+25
+13
+35
+25
+13
+35
+25
+13
+37
+27
+13
+38
+27
+15
+40
+31
+15
+46
+34
+18
+53
+40
+20
+60
+45
+23
+65
+48
+25
+67
+50
+25
+63
+49
+25
+58
+43
+22
+51
+38
+20
+46
+34
+18
+40
+31
+15
+38
+29
+15
+37
+27
+13
+37
+27
+13
+37
+27
+13
+37
+27
+13
+37
+29
+13
+38
+29
+15
+42
+32
+16
+48
+36
+18
+55
+41
+21
+69
+52
+26
+85
+64
+33
+103
+78
+39
+127
+94
+48
+146
+110
+59
+219
+192
+156
+255
+237
+218
+255
+237
+218
+209
+181
+143
+92
+68
+35
+69
+50
+26
+58
+43
+22
+69
+50
+26
+95
+70
+36
+128
+96
+49
+185
+153
+108
+255
+237
+218
+255
+237
+218
+255
+237
+218
+223
+196
+163
+142
+106
+55
+103
+78
+39
+69
+52
+26
+42
+31
+16
+27
+19
+11
+29
+21
+11
+46
+34
+18
+77
+57
+30
+116
+87
+44
+181
+148
+101
+255
+237
+218
+255
+237
+218
+237
+214
+187
+131
+97
+50
+92
+68
+35
+55
+41
+21
+27
+21
+11
+12
+8
+4
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+33
+25
+13
+62
+47
+23
+101
+75
+39
+142
+106
+55
+255
+237
+218
+255
+237
+218
+252
+234
+213
+155
+117
+63
+116
+87
+44
+80
+60
+30
+51
+38
+20
+31
+23
+11
+22
+16
+8
+18
+14
+6
+16
+12
+6
+16
+12
+6
+16
+12
+6
+16
+12
+6
+16
+12
+6
+16
+12
+6
+18
+14
+6
+22
+16
+8
+27
+21
+11
+38
+29
+15
+51
+38
+20
+62
+47
+24
+72
+54
+28
+74
+55
+28
+69
+50
+26
+56
+43
+22
+44
+32
+17
+33
+25
+13
+23
+18
+9
+20
+14
+7
+18
+14
+6
+16
+12
+6
+16
+12
+6
+16
+12
+6
+16
+12
+6
+18
+14
+6
+20
+14
+7
+23
+18
+9
+29
+21
+11
+38
+29
+15
+51
+38
+20
+69
+52
+26
+90
+67
+34
+109
+81
+42
+127
+94
+48
+223
+196
+163
+251
+231
+210
+125
+94
+51
+84
+62
+32
+69
+50
+26
+69
+50
+26
+85
+64
+33
+116
+87
+44
+151
+114
+61
+240
+218
+192
+255
+237
+218
+255
+237
+218
+252
+233
+212
+164
+128
+76
+121
+90
+46
+84
+62
+32
+51
+38
+20
+29
+21
+11
+20
+14
+7
+22
+16
+9
+40
+29
+15
+70
+52
+27
+109
+81
+42
+151
+114
+61
+252
+234
+213
+255
+237
+218
+255
+237
+218
+142
+106
+55
+100
+75
+39
+62
+47
+23
+33
+25
+13
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+37
+27
+14
+69
+50
+26
+107
+81
+42
+157
+120
+69
+255
+237
+218
+255
+237
+218
+236
+212
+185
+142
+105
+54
+103
+78
+39
+67
+50
+25
+38
+27
+15
+20
+14
+7
+12
+8
+4
+8
+6
+2
+6
+4
+2
+6
+4
+2
+6
+4
+2
+6
+4
+2
+6
+4
+2
+8
+6
+2
+10
+8
+4
+16
+12
+6
+27
+19
+10
+44
+32
+17
+62
+47
+24
+82
+62
+31
+95
+70
+36
+96
+72
+37
+87
+65
+33
+70
+52
+27
+51
+38
+20
+33
+25
+13
+20
+14
+7
+12
+8
+4
+8
+6
+2
+6
+4
+2
+6
+4
+2
+6
+4
+2
+6
+4
+2
+6
+4
+2
+8
+6
+2
+10
+8
+4
+12
+10
+5
+18
+14
+7
+27
+21
+11
+40
+31
+16
+56
+43
+22
+74
+55
+28
+89
+65
+34
+108
+82
+45
+178
+144
+98
+81
+60
+30
+70
+54
+27
+67
+50
+26
+79
+59
+30
+103
+78
+39
+138
+103
+52
+204
+173
+133
+255
+237
+218
+255
+237
+218
+255
+237
+218
+206
+176
+137
+137
+102
+53
+98
+73
+37
+63
+47
+25
+37
+27
+13
+20
+14
+7
+14
+10
+5
+18
+14
+6
+35
+25
+13
+62
+47
+24
+101
+75
+39
+140
+104
+53
+237
+214
+187
+255
+237
+218
+255
+237
+218
+157
+120
+69
+107
+81
+42
+69
+50
+26
+37
+27
+14
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+2
+20
+14
+7
+40
+31
+16
+74
+55
+28
+115
+85
+43
+174
+139
+90
+255
+237
+218
+255
+237
+218
+223
+196
+163
+134
+100
+51
+95
+72
+36
+58
+43
+22
+31
+23
+11
+15
+12
+5
+6
+6
+2
+4
+2
+1
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+4
+4
+1
+8
+6
+2
+18
+14
+6
+33
+25
+13
+55
+41
+21
+84
+62
+32
+125
+94
+51
+234
+210
+181
+236
+212
+185
+234
+210
+181
+161
+126
+77
+62
+47
+23
+37
+29
+13
+20
+16
+7
+10
+8
+4
+4
+4
+2
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+4
+2
+2
+4
+4
+2
+8
+6
+3
+14
+10
+5
+22
+16
+8
+33
+25
+13
+44
+32
+17
+55
+41
+21
+62
+47
+23
+65
+48
+25
+62
+45
+23
+62
+45
+23
+70
+52
+27
+92
+68
+35
+123
+91
+47
+160
+123
+71
+249
+229
+207
+255
+237
+218
+255
+237
+218
+243
+222
+198
+155
+117
+63
+115
+85
+43
+77
+57
+30
+46
+34
+18
+23
+18
+9
+12
+10
+4
+8
+6
+3
+14
+10
+5
+29
+21
+11
+56
+43
+22
+95
+70
+36
+134
+100
+51
+223
+196
+163
+255
+237
+218
+255
+237
+218
+174
+139
+90
+113
+85
+43
+74
+55
+28
+40
+31
+15
+20
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+22
+16
+8
+46
+34
+18
+79
+59
+30
+119
+90
+46
+195
+163
+120
+255
+237
+218
+255
+237
+218
+206
+176
+137
+128
+95
+49
+89
+65
+34
+51
+38
+20
+25
+19
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+22
+16
+8
+42
+31
+16
+72
+54
+28
+106
+79
+40
+200
+169
+128
+255
+237
+218
+255
+237
+218
+247
+227
+204
+110
+82
+42
+72
+54
+28
+42
+31
+16
+22
+16
+8
+8
+6
+3
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+1
+6
+4
+2
+10
+8
+4
+16
+12
+6
+23
+18
+9
+31
+23
+12
+38
+29
+15
+42
+31
+16
+48
+36
+18
+60
+45
+23
+80
+60
+30
+110
+82
+42
+144
+108
+55
+219
+192
+156
+255
+237
+218
+255
+237
+218
+255
+237
+218
+195
+162
+115
+131
+97
+50
+93
+68
+36
+58
+43
+22
+31
+23
+12
+16
+12
+6
+8
+6
+2
+6
+4
+2
+12
+8
+4
+25
+19
+9
+51
+38
+20
+89
+65
+34
+128
+95
+49
+206
+176
+137
+255
+237
+218
+255
+237
+218
+195
+163
+120
+118
+88
+45
+79
+59
+30
+44
+32
+17
+22
+16
+8
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+48
+36
+18
+85
+64
+33
+125
+93
+47
+214
+185
+147
+255
+237
+218
+255
+237
+218
+189
+157
+114
+123
+91
+47
+84
+62
+32
+48
+36
+18
+23
+18
+9
+10
+6
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+12
+8
+4
+25
+19
+9
+51
+38
+20
+87
+65
+33
+125
+93
+47
+247
+227
+204
+255
+237
+218
+255
+237
+218
+214
+185
+147
+115
+85
+44
+79
+59
+30
+44
+32
+17
+22
+16
+8
+10
+6
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+8
+6
+2
+12
+8
+4
+18
+12
+7
+23
+18
+9
+31
+23
+11
+44
+32
+17
+65
+48
+25
+95
+70
+36
+128
+96
+49
+174
+139
+90
+254
+236
+216
+255
+237
+218
+255
+237
+218
+234
+210
+181
+144
+108
+55
+109
+81
+42
+72
+54
+28
+42
+31
+16
+22
+16
+8
+10
+8
+4
+4
+4
+2
+4
+4
+2
+10
+8
+4
+23
+18
+9
+48
+36
+18
+84
+62
+32
+123
+91
+47
+189
+157
+114
+255
+237
+218
+255
+237
+218
+209
+181
+143
+125
+93
+47
+84
+62
+33
+48
+36
+18
+23
+18
+9
+10
+6
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+25
+19
+9
+51
+38
+20
+89
+65
+34
+128
+95
+49
+223
+196
+163
+255
+237
+218
+255
+237
+218
+181
+148
+101
+119
+90
+46
+79
+59
+30
+44
+32
+17
+22
+16
+8
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+4
+2
+14
+10
+5
+31
+23
+11
+58
+43
+23
+98
+73
+37
+142
+106
+55
+255
+237
+218
+255
+237
+218
+255
+237
+218
+185
+153
+108
+121
+90
+46
+80
+60
+31
+46
+34
+18
+22
+16
+8
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+6
+4
+2
+10
+8
+4
+18
+12
+7
+31
+21
+11
+51
+38
+20
+79
+59
+30
+115
+85
+43
+148
+112
+59
+231
+207
+177
+255
+237
+218
+255
+237
+218
+254
+236
+216
+177
+141
+91
+125
+93
+47
+87
+65
+33
+53
+40
+20
+29
+21
+11
+14
+10
+5
+6
+4
+2
+2
+2
+1
+4
+2
+2
+8
+6
+3
+22
+16
+8
+44
+32
+17
+79
+59
+30
+119
+90
+46
+181
+148
+101
+255
+237
+218
+255
+237
+218
+219
+192
+156
+128
+95
+49
+89
+65
+34
+51
+38
+20
+25
+19
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+27
+19
+10
+53
+40
+20
+92
+68
+35
+131
+98
+50
+231
+207
+177
+255
+237
+218
+255
+237
+218
+177
+141
+91
+118
+88
+45
+77
+57
+30
+42
+32
+16
+20
+16
+7
+8
+6
+3
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+33
+25
+13
+63
+49
+25
+103
+78
+39
+157
+120
+69
+255
+237
+218
+255
+237
+218
+255
+237
+218
+177
+141
+91
+121
+90
+46
+79
+59
+30
+44
+32
+17
+22
+16
+8
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+10
+6
+4
+20
+14
+7
+37
+27
+14
+63
+49
+25
+100
+75
+38
+137
+102
+53
+214
+185
+147
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+142
+105
+54
+103
+76
+39
+67
+50
+25
+38
+29
+15
+20
+14
+7
+8
+6
+3
+4
+2
+2
+2
+2
+0
+2
+2
+1
+8
+6
+3
+20
+16
+7
+42
+32
+16
+77
+57
+30
+118
+88
+45
+178
+144
+98
+255
+237
+218
+255
+237
+218
+228
+203
+173
+131
+97
+50
+90
+67
+34
+53
+40
+20
+25
+19
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+12
+8
+4
+27
+19
+11
+55
+41
+21
+92
+68
+35
+134
+100
+51
+238
+216
+189
+255
+237
+218
+255
+237
+218
+170
+134
+84
+116
+87
+44
+74
+56
+28
+42
+31
+16
+20
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+35
+25
+13
+67
+50
+25
+107
+81
+42
+164
+128
+76
+255
+237
+218
+255
+237
+218
+255
+237
+218
+164
+128
+76
+122
+91
+46
+79
+59
+30
+44
+32
+17
+20
+16
+7
+8
+6
+3
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+10
+5
+27
+19
+11
+51
+38
+20
+84
+62
+32
+122
+91
+46
+159
+121
+68
+252
+234
+213
+255
+237
+218
+255
+237
+218
+249
+229
+207
+160
+123
+71
+119
+90
+46
+81
+60
+30
+49
+36
+18
+25
+19
+9
+12
+8
+4
+4
+4
+2
+2
+2
+0
+2
+0
+0
+2
+2
+0
+8
+6
+3
+20
+14
+7
+42
+31
+16
+74
+56
+28
+116
+87
+44
+171
+136
+89
+255
+237
+218
+255
+237
+218
+237
+214
+187
+132
+98
+50
+92
+68
+35
+55
+41
+21
+27
+19
+11
+12
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+12
+8
+4
+27
+19
+11
+55
+41
+21
+92
+68
+35
+134
+100
+51
+238
+216
+189
+255
+237
+218
+255
+237
+218
+170
+134
+84
+116
+87
+44
+74
+56
+28
+42
+31
+16
+20
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+35
+25
+13
+67
+50
+25
+109
+81
+42
+164
+128
+76
+255
+237
+218
+255
+237
+218
+255
+237
+218
+168
+130
+77
+125
+93
+47
+80
+60
+31
+44
+32
+17
+22
+16
+8
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+20
+14
+7
+38
+29
+15
+69
+50
+26
+106
+78
+40
+144
+108
+55
+231
+207
+177
+255
+237
+218
+255
+237
+218
+255
+237
+218
+204
+173
+133
+136
+101
+51
+98
+73
+37
+62
+47
+23
+35
+25
+13
+18
+12
+7
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+3
+20
+14
+7
+42
+31
+16
+74
+56
+28
+116
+87
+44
+171
+136
+89
+255
+237
+218
+255
+237
+218
+237
+214
+187
+132
+98
+50
+92
+68
+35
+55
+41
+21
+27
+19
+11
+12
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+27
+19
+10
+53
+40
+20
+92
+68
+35
+131
+98
+50
+231
+207
+177
+255
+237
+218
+255
+237
+218
+177
+141
+91
+118
+88
+45
+77
+57
+30
+42
+32
+16
+20
+16
+7
+8
+6
+3
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+33
+25
+13
+65
+48
+25
+106
+79
+40
+157
+120
+69
+255
+237
+218
+255
+237
+218
+255
+237
+218
+177
+141
+91
+128
+95
+49
+85
+64
+33
+49
+36
+18
+23
+18
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+29
+21
+11
+55
+41
+21
+90
+67
+34
+128
+95
+49
+177
+141
+91
+255
+237
+218
+255
+237
+218
+255
+237
+218
+242
+220
+194
+153
+116
+63
+115
+85
+43
+77
+57
+30
+46
+34
+18
+23
+18
+9
+10
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+3
+20
+16
+7
+42
+32
+16
+77
+57
+30
+118
+88
+45
+178
+144
+98
+255
+237
+218
+255
+237
+218
+228
+203
+173
+131
+97
+50
+90
+67
+34
+53
+40
+20
+25
+19
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+25
+19
+9
+51
+38
+20
+89
+65
+34
+128
+95
+49
+223
+196
+163
+255
+237
+218
+255
+237
+218
+181
+148
+101
+119
+90
+46
+79
+59
+30
+44
+32
+17
+22
+16
+8
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+4
+2
+14
+10
+5
+31
+23
+11
+62
+45
+23
+101
+75
+39
+148
+112
+59
+255
+237
+218
+255
+237
+218
+255
+237
+218
+195
+162
+115
+136
+101
+51
+93
+70
+36
+55
+41
+21
+29
+21
+11
+12
+10
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+10
+8
+4
+22
+16
+8
+42
+31
+16
+74
+55
+28
+110
+82
+42
+148
+112
+59
+242
+220
+194
+255
+237
+218
+255
+237
+218
+255
+237
+218
+185
+153
+108
+131
+97
+50
+92
+68
+35
+56
+43
+22
+31
+23
+11
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+22
+16
+8
+45
+34
+17
+79
+59
+30
+119
+90
+46
+181
+148
+101
+255
+237
+218
+255
+237
+218
+219
+192
+156
+128
+95
+49
+89
+65
+34
+51
+38
+20
+25
+19
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+49
+36
+18
+85
+64
+33
+125
+93
+47
+214
+185
+147
+255
+237
+218
+255
+237
+218
+189
+157
+114
+123
+91
+47
+84
+62
+32
+48
+36
+18
+23
+18
+9
+10
+6
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+12
+8
+4
+27
+21
+11
+55
+41
+21
+95
+70
+36
+136
+101
+51
+247
+227
+204
+255
+237
+218
+255
+237
+218
+223
+196
+163
+144
+108
+55
+106
+79
+40
+67
+50
+25
+37
+27
+14
+18
+14
+6
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+2
+16
+12
+6
+33
+25
+13
+60
+45
+23
+95
+70
+36
+133
+99
+51
+189
+157
+114
+255
+237
+218
+255
+237
+218
+255
+237
+218
+231
+207
+177
+144
+108
+55
+109
+81
+42
+72
+54
+28
+40
+31
+15
+22
+16
+8
+10
+8
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+6
+4
+23
+18
+9
+48
+36
+18
+84
+62
+32
+123
+91
+47
+189
+157
+114
+255
+237
+218
+255
+237
+218
+214
+185
+147
+125
+93
+47
+84
+62
+33
+48
+36
+18
+23
+18
+9
+10
+6
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+22
+16
+8
+46
+34
+18
+79
+59
+30
+119
+90
+46
+195
+163
+120
+255
+237
+218
+255
+237
+218
+206
+176
+137
+128
+95
+49
+89
+65
+34
+51
+38
+20
+25
+19
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+48
+36
+18
+85
+64
+33
+127
+94
+48
+209
+181
+143
+255
+237
+218
+255
+237
+218
+249
+228
+206
+159
+121
+68
+122
+91
+46
+82
+62
+31
+48
+36
+18
+25
+19
+9
+12
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+27
+21
+11
+49
+36
+18
+80
+60
+31
+118
+88
+45
+151
+114
+61
+249
+229
+207
+255
+237
+218
+255
+237
+218
+254
+236
+216
+174
+139
+90
+125
+93
+47
+87
+65
+33
+53
+40
+20
+27
+21
+11
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+25
+19
+9
+51
+38
+20
+89
+65
+34
+128
+95
+49
+206
+176
+137
+255
+237
+218
+255
+237
+218
+195
+163
+120
+118
+88
+45
+79
+59
+30
+44
+32
+17
+22
+16
+8
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+2
+20
+14
+7
+40
+31
+16
+74
+55
+28
+115
+85
+43
+174
+139
+90
+255
+237
+218
+255
+237
+218
+223
+196
+163
+134
+100
+51
+95
+70
+36
+55
+41
+21
+29
+21
+11
+12
+10
+4
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+3
+20
+14
+7
+40
+31
+15
+74
+55
+28
+113
+85
+43
+168
+130
+77
+255
+237
+218
+255
+237
+218
+255
+237
+218
+200
+169
+128
+140
+104
+53
+101
+75
+39
+63
+49
+25
+35
+27
+13
+18
+12
+7
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+2
+2
+0
+4
+4
+2
+8
+6
+3
+14
+10
+5
+25
+19
+9
+44
+32
+17
+72
+54
+28
+103
+78
+39
+140
+105
+53
+204
+173
+133
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+140
+104
+53
+101
+75
+39
+65
+48
+25
+37
+27
+14
+18
+14
+7
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+4
+2
+12
+10
+5
+29
+21
+11
+56
+43
+22
+95
+70
+36
+134
+100
+51
+223
+196
+163
+255
+237
+218
+255
+237
+218
+174
+139
+90
+113
+85
+43
+74
+55
+28
+40
+31
+15
+20
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+37
+27
+14
+69
+50
+26
+107
+81
+42
+157
+120
+69
+255
+237
+218
+255
+237
+218
+236
+212
+185
+140
+105
+53
+101
+75
+39
+63
+47
+25
+33
+25
+13
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+33
+25
+13
+62
+45
+23
+100
+75
+38
+140
+104
+53
+234
+210
+181
+255
+237
+218
+255
+237
+218
+252
+233
+212
+159
+121
+68
+123
+91
+47
+84
+62
+33
+51
+38
+20
+27
+19
+11
+12
+10
+5
+6
+4
+2
+2
+2
+1
+2
+2
+0
+2
+2
+1
+4
+4
+2
+8
+6
+3
+12
+8
+4
+18
+14
+7
+29
+21
+11
+45
+34
+17
+69
+50
+26
+98
+73
+37
+131
+98
+50
+168
+130
+77
+249
+229
+207
+255
+237
+218
+255
+237
+218
+249
+229
+207
+157
+119
+65
+115
+85
+44
+79
+59
+30
+48
+34
+18
+25
+19
+9
+12
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+35
+25
+13
+63
+47
+25
+103
+76
+39
+140
+105
+53
+237
+214
+187
+255
+237
+218
+255
+237
+218
+157
+120
+69
+107
+81
+42
+69
+50
+26
+37
+27
+14
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+33
+25
+13
+62
+47
+23
+101
+75
+39
+142
+106
+55
+255
+237
+218
+255
+237
+218
+252
+234
+213
+153
+116
+63
+110
+82
+42
+72
+54
+28
+40
+29
+15
+18
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+49
+36
+18
+84
+62
+32
+125
+93
+47
+181
+148
+101
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+144
+108
+55
+106
+78
+40
+69
+50
+26
+38
+29
+15
+20
+14
+7
+10
+6
+4
+6
+4
+2
+6
+4
+2
+8
+6
+2
+12
+8
+4
+18
+14
+6
+25
+19
+9
+37
+27
+13
+51
+38
+20
+74
+55
+28
+100
+73
+38
+128
+95
+49
+157
+119
+65
+234
+210
+181
+255
+237
+218
+255
+237
+218
+255
+237
+218
+168
+130
+77
+128
+95
+49
+92
+68
+35
+58
+43
+22
+33
+25
+13
+16
+12
+6
+6
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+2
+18
+14
+7
+40
+29
+15
+72
+54
+28
+112
+83
+43
+153
+116
+63
+252
+234
+213
+255
+237
+218
+255
+237
+218
+142
+106
+55
+100
+75
+39
+62
+47
+23
+33
+25
+13
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+4
+2
+12
+8
+4
+27
+21
+11
+55
+41
+21
+92
+68
+35
+132
+98
+50
+237
+214
+187
+255
+237
+218
+255
+237
+218
+181
+148
+101
+121
+90
+46
+81
+60
+30
+48
+34
+18
+23
+18
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+2
+18
+14
+7
+37
+27
+14
+67
+50
+26
+106
+79
+40
+148
+112
+59
+249
+229
+207
+255
+237
+218
+255
+237
+218
+255
+237
+218
+177
+141
+91
+128
+95
+49
+90
+67
+34
+55
+41
+21
+31
+23
+11
+16
+12
+6
+10
+8
+4
+10
+8
+4
+16
+12
+6
+23
+18
+9
+35
+27
+13
+49
+36
+18
+65
+48
+25
+85
+64
+33
+106
+79
+40
+132
+98
+50
+157
+119
+65
+223
+196
+163
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+138
+103
+52
+103
+76
+39
+69
+50
+26
+40
+31
+15
+22
+16
+8
+10
+8
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+48
+36
+18
+81
+60
+30
+121
+90
+46
+181
+148
+101
+255
+237
+218
+255
+237
+218
+237
+214
+187
+132
+98
+50
+92
+68
+35
+55
+41
+21
+27
+21
+11
+12
+8
+4
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+48
+36
+18
+84
+62
+32
+122
+91
+46
+198
+166
+123
+255
+237
+218
+255
+237
+218
+209
+181
+143
+132
+98
+50
+93
+70
+36
+55
+41
+21
+29
+21
+11
+14
+10
+5
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+10
+4
+27
+19
+11
+53
+40
+20
+87
+65
+33
+127
+94
+48
+185
+153
+108
+255
+237
+218
+255
+237
+218
+255
+237
+218
+243
+222
+198
+148
+112
+59
+112
+84
+43
+74
+55
+28
+44
+32
+17
+25
+19
+9
+18
+12
+7
+20
+14
+7
+27
+21
+11
+42
+31
+16
+60
+45
+23
+79
+59
+30
+100
+75
+38
+121
+90
+46
+142
+105
+54
+168
+130
+77
+234
+210
+181
+255
+237
+218
+255
+237
+218
+255
+237
+218
+240
+218
+192
+146
+110
+59
+112
+83
+43
+77
+57
+30
+48
+36
+18
+25
+19
+9
+12
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+14
+10
+5
+29
+21
+11
+56
+43
+22
+93
+70
+36
+132
+98
+50
+214
+185
+147
+255
+237
+218
+255
+237
+218
+198
+166
+123
+123
+91
+47
+84
+62
+32
+48
+36
+18
+23
+18
+9
+10
+8
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+3
+20
+14
+7
+40
+31
+15
+74
+55
+28
+112
+84
+43
+164
+128
+76
+255
+237
+218
+255
+237
+218
+240
+218
+192
+142
+105
+54
+106
+79
+40
+69
+50
+26
+38
+29
+15
+18
+14
+7
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+20
+14
+7
+38
+29
+15
+69
+52
+26
+106
+79
+40
+144
+108
+55
+231
+207
+177
+255
+237
+218
+255
+237
+218
+255
+237
+218
+198
+166
+123
+134
+100
+51
+95
+72
+36
+60
+45
+23
+37
+27
+14
+27
+19
+11
+31
+23
+11
+44
+32
+17
+65
+48
+25
+90
+67
+34
+112
+84
+43
+135
+101
+51
+155
+117
+63
+200
+169
+128
+249
+228
+206
+255
+237
+218
+255
+237
+218
+255
+237
+218
+249
+229
+207
+153
+116
+63
+118
+88
+45
+84
+62
+32
+55
+40
+20
+31
+23
+11
+16
+12
+6
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+2
+18
+14
+7
+38
+29
+15
+69
+50
+26
+106
+79
+40
+142
+106
+55
+242
+220
+194
+255
+237
+218
+255
+237
+218
+164
+128
+76
+112
+84
+43
+72
+54
+28
+40
+31
+15
+20
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+33
+25
+13
+62
+47
+23
+100
+75
+39
+138
+103
+52
+252
+233
+212
+255
+237
+218
+255
+237
+218
+174
+139
+90
+119
+90
+46
+81
+60
+30
+48
+36
+18
+25
+19
+9
+10
+8
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+10
+5
+27
+19
+11
+51
+38
+20
+85
+64
+33
+125
+93
+47
+170
+134
+84
+252
+234
+213
+255
+237
+218
+255
+237
+218
+252
+233
+212
+155
+117
+63
+118
+88
+45
+80
+60
+31
+53
+40
+20
+40
+29
+15
+42
+32
+16
+62
+47
+24
+108
+82
+45
+146
+110
+59
+181
+148
+101
+219
+192
+156
+249
+229
+207
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+238
+216
+189
+153
+116
+63
+118
+88
+45
+89
+65
+34
+58
+43
+23
+35
+27
+13
+18
+14
+7
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+10
+8
+4
+25
+19
+9
+48
+36
+18
+82
+62
+31
+121
+90
+46
+177
+141
+91
+255
+237
+218
+255
+237
+218
+252
+233
+212
+138
+103
+52
+100
+75
+39
+62
+47
+24
+33
+25
+13
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+4
+2
+12
+8
+4
+27
+19
+10
+51
+38
+20
+87
+65
+33
+127
+94
+48
+206
+176
+137
+255
+237
+218
+255
+237
+218
+214
+185
+147
+134
+100
+51
+96
+72
+37
+62
+45
+23
+33
+25
+13
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+18
+14
+7
+37
+27
+14
+65
+48
+25
+103
+76
+39
+140
+105
+53
+214
+185
+147
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+140
+104
+53
+101
+75
+39
+70
+52
+27
+51
+38
+20
+53
+40
+20
+70
+52
+27
+195
+163
+120
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+144
+108
+55
+116
+87
+44
+87
+65
+33
+60
+45
+23
+37
+27
+14
+22
+16
+8
+10
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+33
+25
+13
+62
+45
+23
+97
+73
+37
+134
+100
+51
+214
+185
+147
+255
+237
+218
+255
+237
+218
+206
+176
+137
+125
+94
+47
+87
+65
+33
+51
+38
+20
+25
+19
+9
+12
+8
+4
+4
+4
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+20
+16
+7
+42
+31
+16
+74
+55
+28
+112
+84
+43
+161
+126
+77
+255
+237
+218
+255
+237
+218
+249
+229
+207
+153
+116
+63
+112
+84
+43
+77
+57
+30
+46
+34
+18
+23
+18
+9
+10
+8
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+8
+4
+25
+19
+9
+48
+36
+18
+80
+60
+30
+118
+88
+45
+159
+121
+68
+247
+227
+204
+255
+237
+218
+255
+237
+218
+252
+233
+212
+164
+128
+76
+122
+91
+46
+90
+67
+34
+65
+48
+25
+62
+45
+23
+74
+55
+28
+108
+82
+45
+243
+222
+198
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+236
+212
+185
+170
+134
+84
+132
+98
+50
+109
+81
+42
+82
+62
+31
+58
+43
+22
+37
+29
+14
+22
+16
+8
+12
+8
+4
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+46
+34
+18
+77
+57
+30
+113
+85
+43
+153
+116
+63
+249
+229
+207
+255
+237
+218
+255
+237
+218
+161
+126
+77
+112
+84
+43
+74
+55
+28
+42
+31
+16
+20
+16
+7
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+33
+25
+13
+62
+45
+23
+97
+73
+37
+134
+100
+51
+242
+220
+194
+255
+237
+218
+255
+237
+218
+204
+173
+133
+131
+97
+50
+95
+70
+36
+60
+45
+23
+33
+25
+13
+16
+12
+6
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+6
+2
+16
+12
+6
+33
+25
+13
+60
+45
+23
+96
+72
+37
+134
+100
+51
+198
+166
+123
+255
+237
+218
+255
+237
+218
+255
+237
+218
+214
+185
+147
+142
+105
+54
+106
+79
+40
+79
+59
+30
+67
+50
+25
+72
+54
+28
+90
+69
+34
+178
+144
+98
+255
+237
+218
+246
+225
+201
+204
+173
+133
+160
+123
+71
+134
+100
+51
+116
+87
+44
+95
+72
+36
+74
+55
+28
+53
+40
+20
+35
+25
+13
+22
+16
+8
+12
+8
+4
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+2
+16
+12
+6
+33
+25
+13
+60
+45
+23
+95
+70
+36
+131
+97
+50
+204
+173
+133
+255
+237
+218
+255
+237
+218
+240
+218
+192
+134
+100
+51
+96
+72
+37
+60
+45
+23
+33
+25
+13
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+10
+8
+4
+25
+19
+9
+48
+36
+18
+81
+60
+30
+118
+88
+45
+177
+141
+91
+255
+237
+218
+255
+237
+218
+247
+227
+204
+151
+114
+61
+113
+85
+43
+79
+59
+30
+48
+34
+18
+25
+19
+9
+12
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+10
+8
+4
+23
+18
+9
+44
+32
+17
+74
+55
+28
+112
+84
+43
+148
+112
+59
+237
+214
+187
+255
+237
+218
+255
+237
+218
+252
+234
+213
+170
+134
+84
+127
+94
+48
+95
+70
+36
+74
+55
+28
+67
+50
+25
+74
+56
+28
+90
+67
+34
+107
+81
+42
+112
+84
+43
+112
+84
+43
+106
+79
+40
+93
+70
+36
+79
+59
+30
+60
+45
+23
+44
+32
+17
+29
+21
+11
+18
+14
+7
+10
+8
+4
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+8
+4
+25
+19
+9
+48
+34
+18
+79
+59
+30
+113
+85
+43
+151
+114
+61
+247
+227
+204
+255
+237
+218
+255
+237
+218
+177
+141
+91
+118
+88
+45
+80
+60
+31
+48
+36
+18
+23
+18
+9
+10
+8
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+8
+6
+2
+18
+14
+7
+37
+27
+14
+65
+48
+25
+101
+75
+39
+138
+103
+52
+243
+222
+198
+255
+237
+218
+255
+237
+218
+204
+173
+133
+134
+100
+51
+98
+73
+37
+65
+48
+25
+37
+29
+14
+20
+14
+7
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+29
+21
+11
+55
+41
+21
+90
+67
+34
+128
+95
+49
+181
+148
+101
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+144
+108
+55
+112
+84
+43
+84
+62
+32
+65
+48
+25
+60
+45
+23
+65
+48
+25
+72
+54
+28
+74
+56
+28
+74
+55
+28
+67
+50
+25
+58
+43
+22
+46
+34
+18
+33
+25
+13
+23
+18
+9
+16
+12
+6
+8
+6
+3
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+20
+14
+7
+38
+29
+15
+65
+48
+25
+98
+73
+37
+134
+100
+51
+206
+176
+137
+255
+237
+218
+255
+237
+218
+246
+225
+201
+138
+103
+52
+101
+75
+39
+65
+48
+25
+37
+27
+14
+18
+14
+7
+8
+6
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+10
+4
+27
+19
+10
+51
+38
+20
+84
+62
+32
+119
+90
+46
+178
+144
+98
+255
+237
+218
+255
+237
+218
+252
+233
+212
+164
+128
+76
+121
+90
+46
+85
+64
+33
+55
+41
+21
+31
+23
+12
+16
+12
+6
+8
+6
+2
+2
+2
+1
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+20
+16
+7
+40
+29
+15
+69
+52
+26
+106
+79
+40
+142
+105
+54
+226
+200
+167
+255
+237
+218
+255
+237
+218
+255
+237
+218
+181
+148
+101
+131
+98
+50
+96
+72
+37
+69
+52
+26
+53
+40
+20
+46
+34
+18
+44
+32
+17
+44
+32
+17
+42
+31
+16
+37
+27
+14
+29
+21
+11
+23
+18
+9
+16
+12
+6
+10
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+2
+16
+12
+6
+31
+23
+12
+55
+41
+21
+85
+64
+33
+121
+90
+46
+164
+128
+76
+251
+231
+210
+255
+237
+218
+255
+237
+218
+178
+144
+98
+119
+90
+46
+84
+62
+32
+51
+38
+20
+27
+19
+10
+12
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+18
+14
+7
+37
+29
+14
+65
+48
+25
+101
+75
+38
+135
+101
+51
+234
+210
+181
+255
+237
+218
+255
+237
+218
+226
+200
+167
+140
+105
+53
+109
+81
+42
+74
+56
+28
+48
+34
+18
+27
+19
+10
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+10
+5
+27
+19
+11
+51
+38
+20
+84
+62
+32
+122
+91
+46
+168
+130
+77
+252
+233
+212
+255
+237
+218
+255
+237
+218
+240
+218
+192
+151
+114
+61
+115
+85
+43
+80
+60
+31
+55
+41
+21
+37
+27
+14
+27
+21
+11
+23
+18
+9
+20
+16
+7
+18
+12
+7
+14
+10
+5
+10
+6
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+27
+19
+10
+48
+34
+18
+74
+56
+28
+109
+81
+42
+142
+105
+54
+228
+203
+173
+255
+237
+218
+255
+237
+218
+236
+212
+185
+135
+101
+51
+100
+75
+39
+65
+48
+25
+37
+27
+14
+18
+14
+7
+8
+6
+3
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+8
+4
+25
+19
+9
+49
+36
+18
+80
+60
+31
+116
+87
+44
+160
+123
+71
+255
+237
+218
+255
+237
+218
+255
+237
+218
+195
+163
+120
+132
+98
+50
+100
+75
+39
+69
+52
+26
+42
+31
+16
+23
+18
+9
+12
+10
+4
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+3
+18
+14
+7
+37
+27
+13
+63
+47
+25
+100
+75
+38
+138
+103
+52
+209
+181
+143
+255
+237
+218
+255
+237
+218
+255
+237
+218
+200
+169
+128
+135
+101
+51
+98
+73
+37
+65
+48
+25
+40
+29
+15
+23
+18
+9
+15
+12
+5
+10
+8
+4
+8
+6
+2
+6
+4
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+8
+4
+23
+18
+9
+42
+31
+16
+69
+50
+26
+100
+75
+39
+132
+98
+50
+195
+163
+120
+255
+237
+218
+255
+237
+218
+255
+237
+218
+157
+120
+69
+115
+85
+44
+80
+60
+31
+49
+36
+18
+25
+19
+9
+12
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+1
+8
+6
+2
+18
+14
+6
+35
+25
+13
+60
+45
+23
+93
+70
+36
+128
+95
+49
+206
+176
+137
+255
+237
+218
+255
+237
+218
+251
+231
+210
+170
+134
+84
+125
+93
+47
+93
+70
+36
+63
+49
+25
+40
+29
+15
+23
+18
+9
+12
+10
+4
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+12
+8
+4
+23
+18
+9
+46
+34
+18
+79
+59
+30
+115
+85
+44
+155
+117
+63
+246
+225
+201
+255
+237
+218
+255
+237
+218
+249
+229
+207
+159
+121
+68
+118
+88
+45
+81
+60
+30
+49
+36
+18
+27
+21
+11
+14
+10
+5
+8
+6
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+10
+4
+22
+18
+8
+38
+31
+15
+63
+49
+25
+93
+70
+36
+125
+94
+47
+170
+134
+84
+252
+233
+212
+255
+237
+218
+255
+237
+218
+204
+173
+133
+128
+95
+49
+93
+70
+36
+60
+45
+23
+35
+25
+13
+18
+12
+7
+8
+6
+2
+2
+2
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+10
+8
+4
+23
+18
+9
+44
+32
+17
+72
+54
+28
+106
+79
+40
+140
+105
+53
+237
+214
+187
+255
+237
+218
+255
+237
+218
+240
+218
+192
+155
+117
+63
+121
+90
+46
+90
+67
+34
+62
+47
+23
+38
+29
+15
+23
+18
+9
+12
+10
+4
+6
+4
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+16
+12
+6
+33
+25
+13
+58
+43
+22
+93
+70
+36
+132
+98
+50
+195
+162
+115
+255
+237
+218
+255
+237
+218
+255
+237
+218
+214
+185
+147
+140
+104
+53
+101
+75
+39
+65
+48
+25
+38
+27
+15
+20
+14
+7
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+6
+4
+2
+12
+8
+4
+22
+16
+8
+38
+29
+15
+62
+45
+23
+90
+67
+34
+121
+90
+46
+155
+117
+63
+240
+218
+192
+255
+237
+218
+255
+237
+218
+236
+212
+185
+138
+103
+52
+106
+79
+40
+72
+54
+28
+44
+32
+17
+23
+18
+9
+10
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+29
+21
+11
+53
+40
+20
+82
+62
+31
+116
+87
+44
+153
+116
+63
+252
+233
+212
+255
+237
+218
+255
+237
+218
+234
+210
+181
+148
+112
+59
+118
+88
+45
+90
+67
+34
+62
+47
+23
+40
+29
+15
+23
+18
+9
+14
+10
+5
+8
+6
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+10
+8
+4
+22
+16
+8
+42
+31
+16
+72
+54
+28
+110
+82
+42
+144
+108
+55
+234
+210
+181
+255
+237
+218
+255
+237
+218
+254
+236
+216
+170
+134
+84
+125
+93
+47
+85
+64
+33
+53
+40
+20
+27
+21
+11
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+2
+14
+10
+5
+23
+18
+9
+40
+29
+15
+62
+45
+23
+89
+65
+34
+118
+88
+45
+148
+112
+59
+231
+207
+177
+255
+237
+218
+255
+237
+218
+252
+234
+213
+153
+116
+63
+115
+85
+44
+82
+62
+31
+51
+38
+20
+29
+21
+11
+14
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+18
+14
+7
+35
+25
+13
+60
+45
+23
+90
+67
+34
+122
+91
+46
+174
+139
+90
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+144
+108
+55
+118
+88
+45
+90
+67
+34
+63
+47
+25
+42
+31
+16
+27
+19
+10
+16
+12
+6
+8
+6
+3
+4
+4
+2
+2
+2
+0
+2
+0
+0
+2
+0
+0
+2
+2
+0
+6
+4
+2
+14
+10
+5
+29
+21
+11
+53
+40
+20
+87
+65
+33
+125
+94
+47
+177
+141
+91
+254
+236
+216
+255
+237
+218
+255
+237
+218
+231
+207
+177
+144
+108
+55
+107
+81
+42
+70
+52
+27
+40
+31
+15
+22
+16
+8
+10
+6
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+4
+4
+2
+8
+6
+3
+16
+12
+6
+27
+19
+10
+42
+31
+16
+63
+47
+25
+90
+67
+34
+118
+88
+45
+146
+110
+59
+226
+200
+167
+255
+237
+218
+255
+237
+218
+255
+237
+218
+171
+136
+89
+123
+91
+47
+90
+67
+34
+60
+45
+23
+35
+25
+13
+18
+14
+7
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+10
+8
+4
+22
+16
+8
+40
+31
+15
+65
+48
+25
+96
+72
+37
+128
+95
+49
+185
+153
+108
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+148
+112
+59
+121
+90
+46
+93
+70
+36
+69
+52
+26
+48
+36
+18
+31
+23
+11
+20
+14
+7
+12
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+20
+14
+7
+38
+29
+15
+67
+50
+25
+103
+78
+39
+142
+105
+54
+223
+196
+163
+255
+237
+218
+255
+237
+218
+255
+237
+218
+185
+153
+108
+128
+96
+49
+92
+68
+35
+55
+41
+21
+31
+23
+11
+16
+12
+6
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+6
+4
+2
+12
+8
+4
+20
+14
+7
+31
+23
+11
+48
+36
+18
+69
+50
+26
+93
+70
+36
+119
+90
+46
+148
+112
+59
+223
+196
+163
+255
+237
+218
+255
+237
+218
+255
+237
+218
+189
+157
+114
+128
+95
+49
+96
+72
+37
+65
+48
+25
+40
+31
+15
+22
+16
+8
+10
+8
+4
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+6
+4
+2
+12
+10
+5
+25
+19
+9
+45
+34
+17
+70
+54
+27
+101
+75
+39
+131
+97
+50
+195
+163
+120
+255
+237
+218
+255
+237
+218
+255
+237
+218
+234
+210
+181
+155
+117
+63
+125
+93
+47
+100
+75
+39
+74
+56
+28
+55
+41
+21
+38
+29
+15
+25
+19
+9
+16
+12
+6
+10
+8
+4
+6
+4
+2
+4
+4
+2
+4
+2
+2
+6
+4
+2
+12
+10
+5
+27
+19
+10
+49
+36
+18
+82
+62
+31
+119
+90
+46
+164
+128
+76
+251
+231
+210
+255
+237
+218
+255
+237
+218
+242
+220
+194
+151
+114
+61
+113
+85
+43
+74
+56
+28
+45
+34
+17
+23
+18
+9
+10
+8
+4
+4
+4
+2
+2
+2
+0
+2
+2
+0
+2
+2
+0
+4
+2
+2
+6
+4
+2
+10
+8
+4
+16
+12
+6
+25
+19
+9
+37
+29
+14
+55
+41
+21
+74
+56
+28
+100
+75
+38
+125
+93
+47
+153
+116
+63
+231
+207
+177
+255
+237
+218
+255
+237
+218
+255
+237
+218
+198
+166
+123
+131
+97
+50
+101
+75
+39
+70
+52
+27
+44
+32
+17
+25
+19
+9
+12
+10
+5
+6
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+1
+6
+4
+2
+14
+10
+5
+27
+21
+11
+48
+36
+18
+74
+55
+28
+103
+76
+39
+132
+98
+50
+198
+166
+123
+255
+237
+218
+255
+237
+218
+255
+237
+218
+240
+218
+192
+170
+134
+84
+132
+98
+50
+109
+81
+42
+85
+64
+33
+65
+48
+25
+48
+36
+18
+33
+25
+13
+23
+18
+9
+16
+12
+6
+10
+8
+4
+8
+6
+3
+8
+6
+2
+10
+8
+4
+20
+14
+7
+37
+27
+14
+63
+47
+25
+98
+73
+37
+136
+101
+51
+206
+176
+137
+255
+237
+218
+255
+237
+218
+255
+237
+218
+204
+173
+133
+135
+101
+51
+98
+73
+37
+62
+47
+23
+35
+25
+13
+18
+14
+6
+8
+6
+3
+6
+4
+2
+6
+4
+2
+6
+6
+2
+10
+8
+4
+16
+12
+6
+23
+18
+9
+33
+25
+13
+48
+36
+18
+65
+48
+25
+87
+63
+33
+109
+81
+42
+132
+98
+50
+170
+134
+84
+240
+218
+192
+255
+237
+218
+255
+237
+218
+255
+237
+218
+198
+166
+123
+132
+98
+50
+103
+76
+39
+74
+55
+28
+48
+36
+18
+27
+21
+11
+14
+10
+5
+6
+4
+2
+2
+2
+1
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+8
+6
+3
+16
+12
+6
+29
+21
+11
+49
+36
+18
+74
+55
+28
+103
+76
+39
+131
+97
+50
+185
+153
+108
+255
+237
+218
+255
+237
+218
+255
+237
+218
+252
+233
+212
+198
+166
+123
+142
+105
+54
+121
+90
+46
+98
+73
+37
+79
+59
+30
+60
+45
+23
+46
+34
+18
+33
+25
+13
+25
+19
+9
+18
+14
+7
+15
+12
+5
+14
+10
+5
+18
+14
+6
+27
+21
+11
+48
+36
+18
+77
+59
+30
+115
+85
+43
+153
+116
+63
+242
+220
+194
+255
+237
+218
+255
+237
+218
+251
+231
+210
+160
+123
+71
+121
+90
+46
+84
+62
+32
+51
+38
+20
+29
+21
+11
+18
+14
+7
+14
+10
+5
+15
+12
+5
+18
+14
+7
+23
+20
+9
+33
+25
+13
+46
+34
+18
+60
+45
+23
+79
+59
+30
+98
+73
+37
+121
+90
+46
+142
+105
+54
+194
+161
+116
+251
+231
+210
+255
+237
+218
+255
+237
+218
+255
+237
+218
+185
+153
+108
+131
+97
+50
+103
+76
+39
+74
+55
+28
+49
+36
+19
+29
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+16
+12
+6
+29
+21
+11
+49
+36
+18
+74
+55
+28
+101
+75
+39
+128
+95
+49
+174
+139
+90
+252
+233
+212
+255
+237
+218
+255
+237
+218
+255
+237
+218
+226
+200
+167
+164
+128
+76
+134
+100
+51
+115
+85
+43
+95
+70
+36
+77
+57
+30
+62
+45
+23
+49
+36
+18
+38
+29
+15
+29
+21
+11
+25
+19
+9
+23
+18
+9
+27
+19
+10
+38
+29
+15
+62
+47
+23
+95
+70
+36
+131
+98
+50
+189
+157
+114
+255
+237
+218
+255
+237
+218
+255
+237
+218
+219
+192
+156
+142
+105
+54
+106
+79
+40
+74
+55
+28
+49
+36
+18
+35
+25
+13
+31
+23
+11
+31
+23
+12
+38
+29
+15
+49
+36
+18
+62
+45
+23
+77
+57
+30
+95
+70
+36
+115
+85
+43
+134
+100
+51
+164
+128
+76
+228
+203
+173
+255
+237
+218
+255
+237
+218
+255
+237
+218
+252
+233
+212
+171
+136
+89
+128
+95
+49
+101
+75
+39
+74
+55
+28
+49
+36
+18
+31
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+16
+12
+6
+29
+21
+11
+48
+36
+18
+70
+52
+27
+96
+72
+37
+122
+91
+46
+151
+114
+61
+234
+210
+181
+255
+237
+218
+255
+237
+218
+255
+237
+218
+251
+231
+210
+204
+173
+133
+151
+114
+61
+131
+98
+50
+113
+85
+43
+98
+73
+37
+82
+62
+31
+69
+52
+26
+55
+41
+21
+48
+34
+18
+40
+29
+15
+37
+27
+14
+40
+29
+15
+53
+40
+20
+79
+59
+30
+112
+84
+43
+144
+108
+55
+231
+207
+177
+255
+237
+218
+255
+237
+218
+254
+236
+216
+177
+141
+91
+132
+98
+50
+101
+75
+39
+74
+55
+28
+60
+45
+23
+55
+41
+21
+60
+45
+23
+70
+52
+27
+82
+62
+31
+98
+73
+37
+113
+85
+43
+131
+97
+50
+151
+114
+61
+206
+176
+137
+252
+233
+212
+255
+237
+218
+255
+237
+218
+255
+237
+218
+236
+212
+185
+153
+116
+63
+122
+91
+46
+96
+72
+37
+70
+52
+27
+48
+36
+18
+29
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+16
+12
+6
+27
+19
+11
+44
+32
+17
+65
+48
+25
+90
+67
+34
+115
+85
+43
+138
+103
+52
+204
+173
+133
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+249
+228
+206
+206
+176
+137
+155
+117
+63
+134
+100
+51
+121
+90
+46
+106
+79
+40
+92
+68
+35
+79
+59
+30
+67
+50
+25
+55
+41
+21
+51
+38
+20
+53
+40
+20
+67
+50
+25
+93
+70
+36
+128
+95
+49
+174
+139
+90
+254
+236
+216
+255
+237
+218
+255
+237
+218
+234
+210
+181
+155
+117
+63
+131
+98
+50
+109
+81
+42
+95
+72
+36
+92
+68
+35
+98
+73
+37
+107
+81
+42
+121
+90
+46
+135
+101
+51
+153
+116
+63
+200
+169
+128
+246
+225
+201
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+204
+173
+133
+138
+103
+52
+115
+85
+44
+90
+67
+34
+65
+48
+25
+44
+32
+17
+27
+21
+11
+16
+12
+6
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+3
+14
+10
+5
+25
+19
+9
+40
+29
+15
+60
+45
+23
+81
+60
+30
+106
+78
+40
+128
+95
+49
+157
+120
+69
+234
+210
+181
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+249
+229
+207
+214
+185
+147
+174
+139
+90
+142
+105
+54
+128
+96
+49
+116
+87
+44
+101
+75
+39
+85
+64
+33
+72
+54
+28
+62
+47
+23
+63
+49
+25
+80
+60
+31
+109
+81
+42
+142
+105
+54
+219
+192
+156
+255
+237
+218
+255
+237
+218
+255
+237
+218
+198
+166
+123
+157
+119
+65
+144
+108
+55
+134
+100
+51
+132
+98
+50
+136
+101
+51
+144
+108
+55
+177
+141
+91
+214
+185
+147
+249
+229
+207
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+236
+212
+185
+160
+123
+71
+128
+95
+49
+106
+79
+40
+82
+62
+31
+60
+45
+23
+40
+31
+15
+25
+19
+9
+14
+10
+5
+8
+6
+3
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+4
+2
+2
+6
+4
+2
+12
+10
+5
+22
+16
+9
+35
+25
+13
+51
+38
+20
+72
+54
+28
+93
+70
+36
+115
+85
+43
+135
+101
+51
+178
+144
+98
+243
+222
+198
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+240
+218
+192
+209
+181
+143
+178
+144
+98
+142
+106
+55
+116
+87
+44
+96
+72
+37
+77
+57
+30
+67
+50
+26
+72
+54
+28
+92
+68
+35
+123
+91
+47
+160
+123
+71
+249
+229
+207
+255
+237
+218
+255
+237
+218
+246
+225
+201
+177
+141
+91
+168
+130
+77
+168
+130
+77
+185
+153
+108
+214
+185
+147
+242
+220
+194
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+243
+222
+198
+178
+144
+98
+135
+101
+51
+116
+87
+44
+93
+70
+36
+72
+54
+28
+51
+38
+20
+35
+25
+13
+22
+16
+9
+12
+10
+5
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+6
+4
+2
+10
+8
+4
+18
+14
+7
+29
+21
+11
+44
+32
+17
+60
+45
+23
+80
+60
+30
+100
+75
+38
+118
+88
+45
+138
+103
+52
+171
+136
+89
+237
+214
+187
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+252
+234
+213
+234
+210
+181
+171
+136
+89
+92
+68
+35
+72
+54
+28
+67
+50
+25
+77
+57
+30
+103
+76
+39
+136
+101
+51
+206
+176
+137
+255
+237
+218
+255
+237
+218
+255
+237
+218
+240
+218
+192
+240
+218
+192
+254
+236
+216
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+242
+220
+194
+178
+144
+98
+138
+103
+52
+121
+90
+46
+101
+75
+39
+80
+60
+31
+62
+47
+23
+44
+32
+17
+29
+21
+11
+18
+14
+7
+10
+8
+4
+6
+4
+2
+2
+2
+1
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+4
+2
+8
+6
+3
+14
+10
+5
+23
+18
+9
+35
+25
+13
+48
+36
+18
+65
+48
+25
+82
+62
+31
+101
+75
+39
+118
+88
+45
+134
+100
+51
+157
+120
+69
+200
+169
+128
+252
+233
+212
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+251
+231
+210
+117
+88
+46
+74
+55
+28
+62
+45
+23
+62
+47
+24
+82
+62
+31
+112
+84
+43
+148
+112
+59
+252
+234
+213
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+252
+234
+213
+209
+181
+143
+161
+126
+77
+135
+101
+51
+119
+90
+46
+103
+76
+39
+84
+62
+33
+65
+48
+25
+49
+36
+18
+35
+25
+13
+23
+18
+9
+14
+10
+5
+8
+6
+3
+4
+4
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+4
+2
+2
+6
+4
+2
+10
+8
+4
+18
+14
+6
+25
+19
+9
+37
+27
+14
+51
+38
+19
+65
+48
+25
+80
+60
+31
+96
+72
+37
+110
+82
+42
+125
+93
+47
+138
+103
+52
+161
+126
+77
+195
+163
+120
+237
+214
+187
+255
+237
+218
+255
+237
+218
+255
+237
+218
+209
+181
+143
+70
+52
+27
+53
+40
+20
+51
+38
+20
+62
+47
+24
+87
+65
+33
+118
+88
+45
+189
+157
+114
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+255
+237
+218
+237
+214
+187
+198
+166
+123
+168
+130
+77
+140
+105
+53
+127
+94
+48
+112
+84
+43
+98
+73
+37
+81
+60
+30
+65
+48
+25
+51
+38
+20
+37
+27
+14
+25
+19
+9
+18
+14
+6
+10
+8
+4
+6
+4
+2
+4
+2
+2
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+4
+2
+2
+8
+6
+2
+12
+8
+4
+18
+14
+7
+25
+19
+9
+37
+27
+13
+48
+36
+18
+60
+45
+23
+74
+55
+28
+87
+65
+33
+100
+75
+38
+110
+82
+42
+118
+88
+45
+125
+93
+47
+127
+94
+48
+133
+99
+51
+146
+110
+59
+161
+126
+77
+88
+65
+34
+44
+32
+17
+38
+29
+15
+44
+32
+17
+62
+47
+23
+87
+65
+33
+112
+84
+43
+185
+153
+108
+189
+157
+114
+171
+136
+89
+160
+123
+71
+144
+108
+55
+134
+100
+51
+125
+93
+47
+112
+84
+43
+101
+75
+39
+89
+65
+34
+74
+55
+28
+62
+45
+23
+49
+36
+18
+37
+27
+14
+27
+19
+11
+18
+14
+7
+12
+8
+4
+8
+6
+3
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+2
+2
+0
+4
+4
+2
+8
+6
+2
+12
+10
+4
+18
+14
+7
+23
+18
+9
+33
+25
+13
+42
+31
+16
+51
+38
+20
+62
+47
+23
+72
+54
+28
+80
+60
+31
+87
+63
+33
+87
+65
+33
+84
+62
+32
+74
+55
+28
+60
+45
+23
+44
+32
+17
+31
+23
+11
+25
+19
+9
+27
+21
+11
+40
+29
+15
+56
+43
+22
+74
+56
+28
+92
+68
+35
+103
+76
+39
+106
+79
+40
+106
+79
+40
+101
+75
+39
+93
+68
+36
+84
+62
+32
+74
+55
+28
+62
+47
+24
+53
+40
+20
+42
+32
+16
+33
+25
+13
+25
+19
+9
+18
+14
+7
+12
+10
+4
+8
+6
+2
+4
+4
+2
+2
+2
+0
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+2
+2
+0
+4
+4
+2
+6
+6
+2
+10
+8
+4
+15
+12
+5
+20
+16
+7
+25
+19
+9
+33
+25
+13
+40
+31
+15
+46
+34
+18
+51
+38
+20
+53
+40
+20
+51
+38
+20
+46
+34
+18
+37
+27
+14
+27
+21
+11
+20
+14
+7
+16
+12
+6
+16
+12
+6
+23
+18
+9
+33
+25
+13
+46
+34
+18
+55
+41
+21
+62
+47
+24
+65
+48
+25
+65
+48
+25
+60
+45
+23
+55
+41
+21
+48
+36
+18
+40
+31
+16
+33
+25
+13
+27
+19
+10
+22
+16
+8
+16
+12
+6
+10
+8
+4
+8
+6
+2
+4
+4
+2
+2
+2
+0
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+4
+2
+2
+6
+4
+2
+8
+6
+3
+12
+8
+4
+16
+12
+6
+20
+14
+7
+23
+16
+8
+25
+19
+9
+27
+19
+10
+27
+19
+10
+25
+19
+9
+20
+16
+7
+16
+12
+6
+10
+8
+4
+8
+6
+3
+8
+6
+3
+12
+8
+4
+16
+12
+6
+23
+18
+9
+29
+21
+11
+33
+25
+13
+35
+25
+13
+35
+25
+13
+31
+23
+11
+27
+19
+10
+23
+18
+9
+20
+14
+7
+16
+12
+6
+12
+8
+4
+8
+6
+3
+6
+4
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+2
+2
+1
+4
+2
+2
+6
+4
+2
+6
+6
+3
+8
+6
+3
+10
+8
+4
+12
+10
+4
+12
+10
+4
+10
+8
+4
+10
+8
+4
+6
+6
+2
+4
+4
+2
+4
+2
+2
+4
+2
+2
+4
+4
+2
+6
+6
+2
+10
+8
+4
+12
+10
+5
+14
+10
+5
+16
+12
+6
+15
+12
+5
+14
+10
+5
+12
+8
+4
+10
+8
+4
+8
+6
+3
+6
+4
+2
+4
+2
+2
+4
+2
+2
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+2
+2
+0
+4
+2
+2
+4
+2
+2
+4
+4
+2
+4
+4
+2
+4
+4
+2
+4
+2
+2
+2
+2
+0
+2
+2
+0
+2
+0
+0
+2
+0
+0
+2
+2
+0
+2
+2
+1
+4
+2
+2
+4
+4
+2
+6
+4
+2
+6
+4
+2
+6
+4
+2
+4
+4
+2
+4
+4
+2
+4
+2
+2
+2
+2
+0
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+0
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+2
+0
+2
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
diff --git a/nichrome/logo/nichrome.png b/nichrome/logo/nichrome.png
new file mode 100644
index 000000000..1a6aa0f7a
Binary files /dev/null and b/nichrome/logo/nichrome.png differ
diff --git a/nichrome/logo/nichrome.svg b/nichrome/logo/nichrome.svg
new file mode 100644
index 000000000..afef0dae1
--- /dev/null
+++ b/nichrome/logo/nichrome.svg
@@ -0,0 +1,332 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nichrome/logo/nichrome_stylized.png b/nichrome/logo/nichrome_stylized.png
new file mode 100644
index 000000000..ef88d2593
Binary files /dev/null and b/nichrome/logo/nichrome_stylized.png differ
diff --git a/nichrome/pkg/sos/client.go b/nichrome/pkg/sos/client.go
new file mode 100644
index 000000000..94c74b262
--- /dev/null
+++ b/nichrome/pkg/sos/client.go
@@ -0,0 +1,147 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sos
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "net"
+ "net/http"
+ "os"
+ "os/signal"
+ "strconv"
+ "strings"
+ "syscall"
+
+ "github.com/gorilla/mux"
+)
+
+// RegistersNecessaryPatterns registers all the necessary patterns needed
+// to make a service becomes a SoS client.
+func RegistersNecessaryPatterns(router *mux.Router) {
+ router.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("pong"))
+ }).Methods("GET")
+}
+
+// RegisterServiceWithSos tries to register a service with SoS.
+// If an non-nil error is returned, the service needs to exit immediately.
+func RegisterServiceWithSos(service string, port uint) error {
+ return registerServiceWithSos(service, port, "http://localhost:"+PortNum)
+}
+
+func registerServiceWithSos(service string, port uint, sosServerURL string) error {
+ m := RegisterReqJson{service, port}
+ return makeRequestToServer("POST", sosServerURL+"/register", m)
+}
+
+// UnregisterServiceWithSos makes a request to SoS Server to unregister the service.
+// This function should be called before a service exit.
+func UnregisterServiceWithSos(service string) error {
+ return unregisterServiceWithSos(service, "http://localhost:"+PortNum)
+}
+
+func unregisterServiceWithSos(service string, sosServerURL string) error {
+ m := UnRegisterReqJson{service}
+ return makeRequestToServer("POST", sosServerURL+"/unregister", m)
+}
+
+func makeRequestToServer(reqType, url string, reqJSON interface{}) error {
+ b, err := json.Marshal(reqJSON)
+ if err != nil {
+ return err
+ }
+
+ req, err := http.NewRequest(reqType, url, bytes.NewBuffer(b))
+ if err != nil {
+ return err
+ }
+
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return err
+ }
+
+ if res.StatusCode < 200 || res.StatusCode >= 300 {
+ decoder := json.NewDecoder(res.Body)
+ defer res.Body.Close()
+ var retMsg struct{ Error string }
+ if err := decoder.Decode(&retMsg); err != nil {
+ return err
+ }
+ if retMsg.Error != "" {
+ return fmt.Errorf(retMsg.Error)
+ }
+ }
+
+ return nil
+}
+
+// GetListener starts listener on a random port in localhost
+// and returns the listener and the port that the listener is on.
+// Remember to close the listener with:
+//
+// defer listener.close()
+//
+// or if it's used in a server, remember to shutdown the server.
+func GetListener() (net.Listener, uint, error) {
+ listener, err := net.Listen("tcp", "localhost:0")
+ if err != nil {
+ return nil, 0, err
+ }
+
+ addrSplit := strings.Split(listener.Addr().String(), ":")
+ if len(addrSplit) != 2 {
+ listener.Close()
+ return nil, 0, fmt.Errorf("Address format not recognized: %v", listener.Addr().String())
+ }
+
+ port, err := strconv.ParseUint(addrSplit[1], 10, 32)
+ if err != nil {
+ listener.Close()
+ return nil, 0, err
+ }
+ return listener, uint(port), nil
+}
+
+// StartServiceServer establishes registers all necessary patterns to the router passed in,
+// registers the service with SoS using the port passed in, and starts serving the service on the
+// listener passed in. If any of the above step fails, this function will return an error.
+// This function wraps around RegistersNecessaryPatterns, RegisterServiceWithSos, and UnregisterServiceWithSos.
+// If no extenral settings are required, instead of calling each of the above separately, one can call
+// the GetListener function and pass the result into this function to start and serve their HTTP server right away.
+func StartServiceServer(router *mux.Router, serviceName string, listener net.Listener, port uint) error {
+ RegistersNecessaryPatterns(router)
+ if err := RegisterServiceWithSos(serviceName, port); err != nil {
+ return err
+ }
+ defer UnregisterServiceWithSos(serviceName)
+
+ shutdownChan := make(chan bool, 2)
+ server := http.Server{Handler: router}
+ defer func() {
+ shutdownChan <- true
+ }() // Use to collect any other failure besides signals
+
+ // Signals Collector
+ sigs := make(chan os.Signal, 1)
+ signal.Notify(sigs, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT)
+ go func() {
+ sig := <-sigs
+ fmt.Printf("Received: %v\n", sig)
+ shutdownChan <- true
+ }()
+
+ // Server Shutdown code
+ go func() {
+ <-shutdownChan
+ fmt.Println("Shutting down...")
+ server.Shutdown(context.Background())
+ }()
+
+ return server.Serve(listener)
+}
diff --git a/nichrome/pkg/sos/html/css/stylesheet.css b/nichrome/pkg/sos/html/css/stylesheet.css
new file mode 100644
index 000000000..e1d3e71a2
--- /dev/null
+++ b/nichrome/pkg/sos/html/css/stylesheet.css
@@ -0,0 +1,116 @@
+body {
+ font: 12px Helvetica, sans-serif;
+ background-color: #f1f1f1
+}
+
+h1 {
+ margin-left: 40px;
+}
+
+h2.center, h2.centernarrow {
+ padding: 5px;
+ color: #616161
+}
+
+.banner {
+ background-color: #3367d6;
+ color: white;
+ position: absolute;
+ top: 0px;
+ right: 0;
+ left: 0;
+ margin: 0 auto;
+}
+
+.bannerbtn {
+ text-decoration: none;
+ color: white;
+}
+
+.content {
+ margin-top: 100px;
+}
+
+.center {
+ margin: auto;
+ padding: 5px;
+ width: 75%
+}
+
+.centernarrow {
+ margin: auto;
+ padding: 5px;
+ width: 50%
+}
+
+.button {
+ background-color: #4885ed;
+ border: none;
+ color: white;
+ padding: 16px 32px;
+ text-align: center;
+ text-transform: uppercase;
+ font-size: 16px;
+ margin: 4px 2px;
+ transition: 0.3s;
+ display: inline-block;
+ text-decoration: none;
+ cursor: pointer;
+ border-radius: 4px;
+}
+
+.textbutton {
+ color: #3367d6;
+ background-color: white;
+ border: none;
+ font-size: 16px;
+ cursor: pointer;
+}
+
+.submitbtn {
+ float: right;
+ margin-right: 25%;
+ margin-top: 20px;
+}
+
+.button:hover {
+ background-color: #3875d8;
+}
+
+table {
+ background-color: white;
+ margin:auto;
+ border-collapse: collapse;
+ box-shadow: 0 2px 0 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
+}
+
+td, th {
+ border: 1px solid #dddddd;
+ text-align: center;
+ padding: 8px;
+}
+
+.card {
+ background-color: white;
+ margin:auto;
+ width: 50%;
+ box-shadow: 0 2px 0 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
+ padding-bottom: 10px;
+}
+
+.label {
+ padding: 20px;
+ padding-bottom: 0px;
+ margin-bottom: 5px;
+ margin-top: 0;
+}
+
+input.form[type=text] {
+ width: 75%;
+ box-sizing: border-box;
+ border: none;
+ border-bottom: 2px solid #bbbbbb;
+ padding: 0px;
+ margin-left: 20px;
+ margin-bottom: 10px;
+}
\ No newline at end of file
diff --git a/nichrome/pkg/sos/html/sos.html b/nichrome/pkg/sos/html/sos.html
new file mode 100644
index 000000000..243c1bd3b
--- /dev/null
+++ b/nichrome/pkg/sos/html/sos.html
@@ -0,0 +1,32 @@
+
+ Service of Services
+
+
+
+
+
+
+
+
+
Current Services
+
+
+ Service
+ Port Number
+
+ {{range $key, $value := .}}
+
+ {{$key}}
+ {{$value}}
+
+ {{else}}
+
+ No services
+
+ {{end}}
+
+
+
+
\ No newline at end of file
diff --git a/nichrome/pkg/sos/html/time.html b/nichrome/pkg/sos/html/time.html
new file mode 100644
index 000000000..d50caca4e
--- /dev/null
+++ b/nichrome/pkg/sos/html/time.html
@@ -0,0 +1,73 @@
+
+ Time
+
+
+
+
+
+
+
+
+
System Time Settings
+
+
+
+
+
diff --git a/nichrome/pkg/sos/html/upspin.html b/nichrome/pkg/sos/html/upspin.html
new file mode 100644
index 000000000..2ceba60d2
--- /dev/null
+++ b/nichrome/pkg/sos/html/upspin.html
@@ -0,0 +1,124 @@
+
+ Upspin
+
+
+
+
+
+
+
+
+ {{$user := .User}}
+ {{$dir := .Dir}}
+ {{$store := .Store}}
+ {{$seed := .Seed}}
+
+
+
+
diff --git a/nichrome/pkg/sos/html/wifi.html b/nichrome/pkg/sos/html/wifi.html
new file mode 100644
index 000000000..02cc16fa6
--- /dev/null
+++ b/nichrome/pkg/sos/html/wifi.html
@@ -0,0 +1,154 @@
+
+
+ WiFi
+
+
+
+
+
+
+
+
+ {{$NoEnc := 0}}
+ {{$WpaPsk := 1}}
+ {{$WpaEap := 2}}
+ {{$connectedEssid := .ConnectedEssid}}
+ {{$connectingEssid := .ConnectingEssid}}
+
+
+ {{if and (ne $connectingEssid "") (ne $connectingEssid $connectedEssid) }}
+
+ {{end}}
+
+
+
diff --git a/nichrome/pkg/sos/server.go b/nichrome/pkg/sos/server.go
new file mode 100644
index 000000000..92006f2ac
--- /dev/null
+++ b/nichrome/pkg/sos/server.go
@@ -0,0 +1,181 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sos
+
+import (
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "path/filepath"
+
+ "github.com/gorilla/mux"
+)
+
+const (
+ PortNum = "8000"
+ DefHtmlPage = `
+
+
+
+
+
+Current Services (html embedded)
+
+
+ Service
+ Port Number
+
+
+ {{range $key, $value := .}}
+
+ {{$key}}
+ {{$value}}
+ Go there!
+
+ {{else}}
+
+ No services
+
+ {{end}}
+
+
+`
+)
+
+// default path
+var htmlRoot = "/etc/sos/html"
+
+type SosServer struct {
+ service *SosService
+}
+
+type RegisterReqJson struct {
+ Service string
+ Port uint
+}
+
+// set htmlRoot var to array of dirs p
+func SetHTMLRoot(p ...string) {
+ if len(p) > 0 {
+ htmlRoot = filepath.Join(p...)
+ }
+}
+
+// HTMLPath returns the HTMLPath formed by joining the arguments together.
+// If there are no arguments, it simply returns the HTML root directory.
+func HTMLPath(n ...string) string {
+ return filepath.Join(htmlRoot, filepath.Join(n...))
+}
+
+func (s SosServer) registerHandle(w http.ResponseWriter, r *http.Request) {
+ var msg RegisterReqJson
+ decoder := json.NewDecoder(r.Body)
+ defer r.Body.Close()
+ if err := decoder.Decode(&msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+
+ if err := s.service.Register(msg.Service, msg.Port); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusInternalServerError)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ json.NewEncoder(w).Encode(nil)
+}
+
+type UnRegisterReqJson struct {
+ ServiceName string
+}
+
+func (s SosServer) unregisterHandle(w http.ResponseWriter, r *http.Request) {
+ var msg UnRegisterReqJson
+ decoder := json.NewDecoder(r.Body)
+ defer r.Body.Close()
+ if err := decoder.Decode(&msg); err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusBadRequest)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ s.service.Unregister(msg.ServiceName)
+ json.NewEncoder(w).Encode(nil)
+}
+
+type GetServiceResJson struct {
+ Port uint
+}
+
+func (s SosServer) getServiceHandle(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ port, err := s.service.Read(vars["service"])
+ if err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusNotFound)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ json.NewEncoder(w).Encode(GetServiceResJson{port})
+}
+
+func (s SosServer) redirectToResourceHandle(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ port, err := s.service.Read(vars["service"])
+ if err != nil {
+ log.Printf("error: %v", err)
+ w.WriteHeader(http.StatusNotFound)
+ json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
+ return
+ }
+ http.Redirect(w, r, fmt.Sprintf("http://localhost:%v/", port), http.StatusTemporaryRedirect)
+}
+
+func (s SosServer) displaySosHandle(w http.ResponseWriter, r *http.Request) {
+ snap := s.service.SnapshotRegistry()
+ var tmpl *template.Template
+ file, err := ioutil.ReadFile(HTMLPath("sos.html"))
+ if err == nil {
+ html := string(file)
+ tmpl = template.Must(template.New("SoS").Parse(html))
+ } else {
+ tmpl = template.Must(template.New("SoS").Parse(DefHtmlPage))
+ }
+ tmpl.Execute(w, snap)
+}
+
+func (s SosServer) buildRouter() http.Handler {
+ r := mux.NewRouter()
+ r.HandleFunc("/", s.displaySosHandle).Methods("GET")
+ r.HandleFunc("/register", s.registerHandle).Methods("POST")
+ r.HandleFunc("/unregister", s.unregisterHandle).Methods("POST")
+ r.HandleFunc("/service/{service}", s.getServiceHandle).Methods("GET")
+ r.HandleFunc("/go/{service}", s.redirectToResourceHandle).Methods("GET")
+ r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(HTMLPath("css")))))
+ return r
+}
+
+func StartServer(service *SosService) {
+ server := SosServer{service}
+ fmt.Println(http.ListenAndServe(fmt.Sprintf(":%s", PortNum), server.buildRouter()))
+}
diff --git a/nichrome/pkg/sos/server_test.go b/nichrome/pkg/sos/server_test.go
new file mode 100644
index 000000000..2be9bfc0f
--- /dev/null
+++ b/nichrome/pkg/sos/server_test.go
@@ -0,0 +1,203 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sos
+
+import (
+ "encoding/json"
+ "fmt"
+ "math/rand"
+ "net/http"
+ "net/http/httptest"
+ "path/filepath"
+ "reflect"
+ "sync"
+ "testing"
+)
+
+func TestSOSHtmlPath(t *testing.T) {
+ var tests = []struct {
+ paths []string
+ result string
+ }{
+ {paths: []string{""}, result: htmlRoot},
+ {paths: []string{"css"}, result: filepath.Join(htmlRoot, "css")},
+ {paths: []string{"html", "wifi.html"}, result: filepath.Join(htmlRoot, "html/wifi.html")},
+ {paths: []string{"html/wifi.html"}, result: filepath.Join(htmlRoot, "html/wifi.html")},
+ }
+
+ for _, test := range tests {
+ if p := HTMLPath(test.paths...); p != test.result {
+ t.Errorf("%v: want %v, got %v", test, test.result, p)
+ }
+ }
+}
+
+func TestSOSHtmlPathWithPresetRoot(t *testing.T) {
+ //set up
+ testRoot := "/a/b/html"
+ SetHTMLRoot("/a", "b", "html")
+
+ var tests = []struct {
+ paths []string
+ result string
+ }{
+ {paths: []string{""}, result: testRoot},
+ {paths: []string{"css"}, result: filepath.Join(testRoot, "css")},
+ {paths: []string{"html", "wifi.html"}, result: filepath.Join(testRoot, "html/wifi.html")},
+ {paths: []string{"html/wifi.html"}, result: filepath.Join(testRoot, "html/wifi.html")},
+ }
+
+ for _, test := range tests {
+ if p := HTMLPath(test.paths...); p != test.result {
+ t.Errorf("%v: want %v, got %v", test, test.result, p)
+ }
+ }
+}
+
+func TestRegisterHandle(t *testing.T) {
+ // Set up
+ s := SosServer{NewSosService()}
+ r := s.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+ m := RegisterReqJson{knownServ1.service, knownServ1.port}
+
+ // Execute
+ if err := makeRequestToServer("POST", ts.URL+"/register", m); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Assert
+ if s.service.registry[knownServ1.service] != knownServ1.port {
+ t.Errorf("got:(%v)\nwant:(%v)", s.service.registry[knownServ1.service], knownServ1.port)
+ }
+}
+
+func TestUnregisterHandle(t *testing.T) {
+ // Set up
+ s := SosServer{setUpKnownServices()}
+ r := s.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+ m := UnRegisterReqJson{knownServ1.service}
+
+ // Execute
+ if err := makeRequestToServer("POST", ts.URL+"/unregister", m); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ // Assert
+ if _, err := s.service.Read(knownServ1.service); !reflect.DeepEqual(err, fmt.Errorf("%v is not in the registry", knownServ1.service)) {
+ t.Errorf("\ngot:(%v)\nwant:(%v)", err, fmt.Errorf("%v is not in the registry", knownServ1.service))
+ }
+}
+
+func TestGetService(t *testing.T) {
+ // Set up
+ r := SosServer{setUpKnownServices()}.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+ req, err := http.NewRequest("GET", ts.URL+"/service/"+knownServ1.service, nil)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Execute
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Assert
+ decoder := json.NewDecoder(res.Body)
+ defer res.Body.Close()
+ var retMsg GetServiceResJson
+ if err := decoder.Decode(&retMsg); err != nil {
+ t.Errorf("Error Decode JSON Response")
+ return
+ }
+ if retMsg.Port != knownServ1.port {
+ t.Errorf("\ngot:(%v)\nwant:(%v)", retMsg.Port, knownServ1.port)
+ }
+}
+
+func TestGetServiceFails(t *testing.T) {
+ // Set up
+ r := SosServer{NewSosService()}.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+ req, err := http.NewRequest("GET", ts.URL+"/service/"+knownServ1.service, nil)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Execute
+ res, err := http.DefaultClient.Do(req)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // Assert
+ if res.StatusCode != http.StatusNotFound {
+ t.Errorf("\ngot:(%v)\nwant:(%v)", res.StatusCode, http.StatusNotFound)
+ }
+}
+
+func TestRace(t *testing.T) {
+ // Set Up
+ numRegisterGoRoutines, numUnregisterGoRoutines, numReadGoRoutines := 10, 10, 100
+ serviceChoices := []RegistryEntryStub{
+ knownServ1, knownServ2, knownServ3,
+ newServ1, newServ2, newServ3,
+ }
+
+ r := SosServer{setUpKnownServices()}.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+
+ // Execute
+ var wg sync.WaitGroup
+
+ for i := 0; i < numRegisterGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ idx := rand.Intn(len(serviceChoices))
+ m := RegisterReqJson{serviceChoices[idx].service, serviceChoices[idx].port}
+ makeRequestToServer("POST", ts.URL+"/register", m)
+ }()
+ }
+
+ for i := 0; i < numUnregisterGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ idx := rand.Intn(len(serviceChoices))
+ m := UnRegisterReqJson{serviceChoices[idx].service}
+ makeRequestToServer("POST", ts.URL+"/unregister", m)
+ }()
+ }
+
+ for i := 0; i < numReadGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ idx := rand.Intn(len(serviceChoices))
+ req, err := http.NewRequest("GET", ts.URL+"/service/"+serviceChoices[idx].service, nil)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+ http.DefaultClient.Do(req)
+ }()
+ }
+
+ wg.Wait()
+}
diff --git a/nichrome/pkg/sos/service.go b/nichrome/pkg/sos/service.go
new file mode 100644
index 000000000..651380b13
--- /dev/null
+++ b/nichrome/pkg/sos/service.go
@@ -0,0 +1,60 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sos
+
+import (
+ "fmt"
+ "sync"
+)
+
+type Registry map[string]uint
+
+type SosService struct {
+ rWLock sync.RWMutex
+ registry Registry
+}
+
+func (s *SosService) Read(serviceName string) (uint, error) {
+ s.rWLock.RLock()
+ defer s.rWLock.RUnlock()
+ port, exists := s.registry[serviceName]
+ if !exists {
+ return 0, fmt.Errorf("%v is not in the registry", serviceName)
+ }
+ return port, nil
+}
+
+func (s *SosService) Register(serviceName string, portNum uint) error {
+ s.rWLock.Lock()
+ defer s.rWLock.Unlock()
+ _, exists := s.registry[serviceName]
+ if exists {
+ return fmt.Errorf("%v already exists", serviceName)
+ }
+ s.registry[serviceName] = portNum
+ return nil
+}
+
+func (s *SosService) Unregister(serviceName string) {
+ s.rWLock.Lock()
+ defer s.rWLock.Unlock()
+ delete(s.registry, serviceName)
+}
+
+func (s *SosService) SnapshotRegistry() Registry {
+ s.rWLock.RLock()
+ defer s.rWLock.RUnlock()
+ snapshot := make(map[string]uint)
+ for name, port := range s.registry {
+ snapshot[name] = port
+ }
+ return snapshot
+}
+
+func NewSosService() *SosService {
+ return &SosService{
+ registry: make(map[string]uint),
+ }
+}
diff --git a/nichrome/pkg/sos/serviceFuncs_test.go b/nichrome/pkg/sos/serviceFuncs_test.go
new file mode 100644
index 000000000..deb3c6fd0
--- /dev/null
+++ b/nichrome/pkg/sos/serviceFuncs_test.go
@@ -0,0 +1,96 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sos
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "reflect"
+ "testing"
+
+ "github.com/gorilla/mux"
+)
+
+func TestRegistersNecessaryPatterns(t *testing.T) {
+ router := mux.NewRouter()
+ RegistersNecessaryPatterns(router)
+ ts := httptest.NewServer(router)
+ defer ts.Close()
+
+ res, err := http.Get(ts.URL + "/ping")
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ if res.StatusCode != http.StatusOK {
+ t.Errorf("Status Code\ngot:%v\nwant:%v", res.StatusCode, http.StatusOK)
+ return
+ }
+
+ msg, err := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ if string(msg) != "pong" {
+ t.Errorf("Body\ngot:%v\nwant:%v", string(msg), "pong")
+ }
+}
+
+func TestRegisterServiceWithSosSuccess(t *testing.T) {
+ // Set up
+ service := NewSosService()
+ server := SosServer{service}
+ r := server.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+
+ if err := registerServiceWithSos(knownServ1.service, knownServ1.port, ts.URL); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ if service.registry[knownServ1.service] != knownServ1.port {
+ t.Errorf("In Registry\ngot:%v\nwant:%v", service.registry[knownServ1.service], knownServ1.port)
+ }
+}
+
+func TestRegisterServiceWithSosFail(t *testing.T) {
+ // Set up
+ service := setUpKnownServices()
+ server := SosServer{service}
+ r := server.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+
+ err := registerServiceWithSos(knownServ1.service, knownServ1.port, ts.URL)
+ if !reflect.DeepEqual(err, fmt.Errorf("%v already exists", knownServ1.service)) {
+ t.Errorf("\ngot:%v\nwant:%v", err, fmt.Errorf("%v already exists", knownServ1.service))
+ }
+}
+
+func TestUnregisterServiceWithSosSuccess(t *testing.T) {
+ // Set up
+ service := setUpKnownServices()
+ server := SosServer{service}
+ r := server.buildRouter()
+ ts := httptest.NewServer(r)
+ defer ts.Close()
+
+ if err := unregisterServiceWithSos(knownServ1.service, ts.URL); err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ if _, err := service.Read(knownServ1.service); !reflect.DeepEqual(err, fmt.Errorf("%v is not in the registry", knownServ1.service)) {
+ t.Errorf("unregister(%v)\ngot:(%v)\nwant:(%v)", knownServ1.service, err, fmt.Errorf("%v is not in the registry", knownServ1.service))
+ }
+
+}
diff --git a/nichrome/pkg/sos/service_test.go b/nichrome/pkg/sos/service_test.go
new file mode 100644
index 000000000..392bb90af
--- /dev/null
+++ b/nichrome/pkg/sos/service_test.go
@@ -0,0 +1,135 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sos
+
+import (
+ "fmt"
+ "reflect"
+ "sync"
+ "testing"
+)
+
+type RegistryEntryStub struct {
+ service string
+ port uint
+}
+
+var (
+ knownServ1 = RegistryEntryStub{"stub1", 1}
+ knownServ2 = RegistryEntryStub{"stub2", 2}
+ knownServ3 = RegistryEntryStub{"stub3", 3}
+ newServ1 = RegistryEntryStub{"stub4", 4}
+ newServ2 = RegistryEntryStub{"stub5", 5}
+ newServ3 = RegistryEntryStub{"stub6", 6}
+)
+
+func setUpKnownServices() *SosService {
+ service := NewSosService()
+ service.registry[knownServ1.service] = knownServ1.port
+ service.registry[knownServ2.service] = knownServ2.port
+ service.registry[knownServ3.service] = knownServ3.port
+ return service
+}
+
+func TestReadNonExist(t *testing.T) {
+ s := NewSosService()
+ if _, err := s.Read(knownServ1.service); !reflect.DeepEqual(err, fmt.Errorf("%v is not in the registry", knownServ1.service)) {
+ t.Errorf("read(%v)\ngot:(%v)\nwant:(%v)", knownServ1.service, err, fmt.Errorf("%v is not in the registry", knownServ1.service))
+ }
+}
+
+func TestRead(t *testing.T) {
+ s := setUpKnownServices()
+ if port, err := s.Read(knownServ1.service); err != nil || port != knownServ1.port {
+ t.Errorf("read(%v)\ngot:(%v, %v)\nwant:(%v, %v)", knownServ1.service, port, err, knownServ1.port, nil)
+ }
+}
+
+func TestRegisterAlreadyExists(t *testing.T) {
+ s := setUpKnownServices()
+ err := s.Register(knownServ1.service, knownServ1.port)
+ if !reflect.DeepEqual(err, fmt.Errorf("%v already exists", knownServ1.service)) {
+ t.Errorf("Already Exists Register\ngot:(%v)\nwant:(%v)", err, fmt.Errorf("%v already exists", knownServ1.service))
+ }
+}
+
+func TestRegisterSuccess(t *testing.T) {
+ s := NewSosService()
+ s.Register(knownServ1.service, knownServ1.port)
+ if port, err := s.Read(knownServ1.service); err != nil || port != knownServ1.port {
+ t.Errorf("register(%v)\ngot:(%v, %v)\nwant:(%v, %v)", knownServ1, port, err, knownServ1.port, nil)
+ }
+}
+
+func TestUnregisterNonExist(t *testing.T) {
+ s := NewSosService()
+ s.Unregister(knownServ1.service)
+ // should not panic
+}
+
+func TestUnregister(t *testing.T) {
+ s := setUpKnownServices()
+ s.Unregister(knownServ1.service)
+ if _, err := s.Read(knownServ1.service); !reflect.DeepEqual(err, fmt.Errorf("%v is not in the registry", knownServ1.service)) {
+ t.Errorf("unregister(%v)\ngot:(%v)\nwant:(%v)", knownServ1.service, err, fmt.Errorf("%v is not in the registry", knownServ1.service))
+ }
+}
+
+func TestSnapshot(t *testing.T) {
+ s := setUpKnownServices().SnapshotRegistry()
+ if port, exists := s[knownServ1.service]; !exists || port != knownServ1.port {
+ t.Errorf("%v\ngot:(%v, %v)\nwant:(%v, %v)", knownServ1, port, exists, knownServ1.port, true)
+ }
+ if port, exists := s[knownServ2.service]; !exists || port != knownServ2.port {
+ t.Errorf("%v\ngot:(%v, %v)\nwant:(%v, %v)", knownServ2, port, exists, knownServ2.port, true)
+ }
+ if port, exists := s[knownServ3.service]; !exists || port != knownServ3.port {
+ t.Errorf("%v\ngot:(%v, %v)\nwant:(%v, %v)", knownServ3, port, exists, knownServ1.port, true)
+ }
+}
+
+func TestRaceCondtion(t *testing.T) {
+ //Set Up
+ s := NewSosService()
+ numReadGoRoutines := 10
+ numRegisterGoRoutines := 20
+ numUnregisterGoRoutines := 20
+ numSnapshotGoRoutines := 10
+
+ var wg sync.WaitGroup
+ for i := 0; i < numRegisterGoRoutines; i++ {
+ wg.Add(1)
+ go func(idx uint) {
+ defer wg.Done()
+ s.Register(fmt.Sprintf("stub%v", idx), idx)
+ }(uint(i))
+ }
+
+ for i := 0; i < numReadGoRoutines; i++ {
+ wg.Add(1)
+ go func(idx uint) {
+ defer wg.Done()
+ s.Read(fmt.Sprintf("stub%v", idx))
+ }(uint(i))
+ }
+
+ for i := 0; i < numUnregisterGoRoutines; i++ {
+ wg.Add(1)
+ go func(idx uint) {
+ defer wg.Done()
+ s.Unregister(fmt.Sprintf("stub%v", idx))
+ }(uint(i))
+ }
+
+ for i := 0; i < numSnapshotGoRoutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ s.SnapshotRegistry()
+ }()
+ }
+
+ wg.Wait()
+}
diff --git a/nichrome/pkg/wifi/iwl.go b/nichrome/pkg/wifi/iwl.go
new file mode 100644
index 000000000..54684965c
--- /dev/null
+++ b/nichrome/pkg/wifi/iwl.go
@@ -0,0 +1,197 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package wifi
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "regexp"
+ "strings"
+ "time"
+
+ "github.com/u-root/NiChrome/pkg/wpa/passphrase"
+)
+
+const (
+ nopassphrase = `network={
+ ssid="%s"
+ proto=RSN
+ key_mgmt=NONE
+ }`
+ eap = `network={
+ ssid="%s"
+ key_mgmt=WPA-EAP
+ identity="%s"
+ password="%s"
+ }`
+)
+
+var (
+ // RegEx for parsing iwlist output
+ cellRE = regexp.MustCompile("(?m)^\\s*Cell")
+ essidRE = regexp.MustCompile("(?m)^\\s*ESSID.*")
+ encKeyOptRE = regexp.MustCompile("(?m)^\\s*Encryption key:(on|off)$")
+ wpa2RE = regexp.MustCompile("(?m)^\\s*IE: IEEE 802.11i/WPA2 Version 1$")
+ authSuitesRE = regexp.MustCompile("(?m)^\\s*Authentication Suites .*$")
+)
+
+type SecProto int
+
+const (
+ NoEnc SecProto = iota
+ WpaPsk
+ WpaEap
+ NotSupportedProto
+)
+
+// IWLWorker implements the WiFi interface using the Intel Wireless LAN commands
+type IWLWorker struct {
+ Interface string
+}
+
+func NewIWLWorker(i string) (WiFi, error) {
+ if o, err := exec.Command("ip", "link", "set", "dev", i, "up").CombinedOutput(); err != nil {
+ return &IWLWorker{""}, fmt.Errorf("ip link set dev %v up: %v (%v)", i, string(o), err)
+ }
+ return &IWLWorker{i}, nil
+}
+
+func (w *IWLWorker) Scan() ([]Option, error) {
+ o, err := exec.Command("iwlist", w.Interface, "scanning").CombinedOutput()
+ if err != nil {
+ return nil, fmt.Errorf("iwlist: %v (%v)", string(o), err)
+ }
+ return parseIwlistOut(o), nil
+}
+
+/*
+ * Assumptions:
+ * 1) Cell, essid, and encryption key option are 1:1 match
+ * 2) We only support IEEE 802.11i/WPA2 Version 1
+ * 3) Each Wifi only support (1) authentication suites (based on observations)
+ */
+
+func parseIwlistOut(o []byte) []Option {
+ cells := cellRE.FindAllIndex(o, -1)
+ essids := essidRE.FindAll(o, -1)
+ encKeyOpts := encKeyOptRE.FindAll(o, -1)
+
+ if cells == nil {
+ return nil
+ }
+
+ var res []Option
+ knownEssids := make(map[string]bool)
+
+ // Assemble all the Wifi options
+ for i := 0; i < len(cells); i++ {
+ essid := strings.Trim(strings.Split(string(essids[i]), ":")[1], "\"\n")
+ if knownEssids[essid] {
+ continue
+ }
+ knownEssids[essid] = true
+ encKeyOpt := strings.Trim(strings.Split(string(encKeyOpts[i]), ":")[1], "\n")
+ if encKeyOpt == "off" {
+ res = append(res, Option{essid, NoEnc})
+ continue
+ }
+ // Find the proper Authentication Suites
+ start, end := cells[i][0], len(o)
+ if i != len(cells)-1 {
+ end = cells[i+1][0]
+ }
+ // Narrow down the scope when looking for WPA Tag
+ wpa2SearchArea := o[start:end]
+ l := wpa2RE.FindIndex(wpa2SearchArea)
+ if l == nil {
+ res = append(res, Option{essid, NotSupportedProto})
+ continue
+ }
+ // Narrow down the scope when looking for Authorization Suites
+ authSearchArea := wpa2SearchArea[l[0]:]
+ authSuites := strings.Trim(strings.Split(string(authSuitesRE.Find(authSearchArea)), ":")[1], "\n ")
+ switch authSuites {
+ case "PSK":
+ res = append(res, Option{essid, WpaPsk})
+ case "802.1x":
+ res = append(res, Option{essid, WpaEap})
+ default:
+ res = append(res, Option{essid, NotSupportedProto})
+ }
+ }
+ return res
+}
+
+func (w *IWLWorker) GetID() (string, error) {
+ o, err := exec.Command("iwgetid", "-r").CombinedOutput()
+ if err != nil {
+ return "", err
+ }
+ return strings.Trim(string(o), " \n"), nil
+}
+
+func (w *IWLWorker) Connect(a ...string) error {
+ // format of a: [essid, pass, id]
+ conf, err := generateConfig(a...)
+ if err != nil {
+ return err
+ }
+
+ if err := ioutil.WriteFile("/tmp/wifi.conf", conf, 0444); err != nil {
+ return fmt.Errorf("/tmp/wifi.conf: %v", err)
+ }
+
+ // Each request has a 30 second window to make a connection
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+ c := make(chan error, 1)
+
+ // There's no telling how long the supplicant will take, but on the other hand,
+ // it's been almost instantaneous. But, further, it needs to keep running.
+ go func() {
+ cmd := exec.CommandContext(ctx, "wpa_supplicant", "-i"+w.Interface, "-c/tmp/wifi.conf")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr //For an easier time debugging
+ cmd.Run()
+ }()
+
+ // dhclient might never return on incorrect passwords or identity
+ go func() {
+ cmd := exec.CommandContext(ctx, "dhclient", "-ipv4=true", "-ipv6=false", "-v", w.Interface)
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr //For an easier time debugging
+ if err := cmd.Run(); err != nil {
+ c <- err
+ } else {
+ c <- nil
+ }
+ }()
+
+ select {
+ case err := <-c:
+ return err
+ case <-ctx.Done():
+ return fmt.Errorf("Connection timeout")
+ }
+}
+
+func generateConfig(a ...string) (conf []byte, err error) {
+ // format of a: [essid, pass, id]
+ switch {
+ case len(a) == 3:
+ conf = []byte(fmt.Sprintf(eap, a[0], a[2], a[1]))
+ case len(a) == 2:
+ conf, err = passphrase.Run(a[0], a[1])
+ if err != nil {
+ return nil, fmt.Errorf("essid: %v, pass: %v : %v", a[0], a[1], err)
+ }
+ case len(a) == 1:
+ conf = []byte(fmt.Sprintf(nopassphrase, a[0]))
+ default:
+ return nil, fmt.Errorf("generateConfig needs 1, 2, or 3 args")
+ }
+ return
+}
diff --git a/nichrome/pkg/wifi/iwl_test.go b/nichrome/pkg/wifi/iwl_test.go
new file mode 100644
index 000000000..83cef43dd
--- /dev/null
+++ b/nichrome/pkg/wifi/iwl_test.go
@@ -0,0 +1,245 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package wifi
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "reflect"
+ "testing"
+
+ "github.com/u-root/NiChrome/pkg/wpa/passphrase"
+)
+
+type GenerateConfigTestCase struct {
+ name string
+ args []string
+ exp []byte
+ err error
+}
+
+var (
+ EssidStub = "stub"
+ IdStub = "stub"
+ PassStub = "123456789"
+ BadWpaPskPass = "123"
+ expWpaPsk, _ = passphrase.Run(EssidStub, PassStub)
+ _, expWpaPskErr = passphrase.Run(EssidStub, BadWpaPskPass)
+
+ generateConfigTestcases = []GenerateConfigTestCase{
+ {
+ name: "No Pass Phrase",
+ args: []string{EssidStub},
+ exp: []byte(fmt.Sprintf(nopassphrase, EssidStub)),
+ err: nil,
+ },
+ {
+ name: "WPA-PSK",
+ args: []string{EssidStub, PassStub},
+ exp: expWpaPsk,
+ err: nil,
+ },
+ {
+ name: "WPA-EAP",
+ args: []string{EssidStub, PassStub, IdStub},
+ exp: []byte(fmt.Sprintf(eap, EssidStub, IdStub, PassStub)),
+ err: nil,
+ },
+ {
+ name: "WPA-PSK Error",
+ args: []string{EssidStub, BadWpaPskPass},
+ exp: nil,
+ err: fmt.Errorf("essid: %v, pass: %v : %v", EssidStub, BadWpaPskPass, expWpaPskErr),
+ },
+ {
+ name: "Invalid Args Length Error",
+ args: nil,
+ exp: nil,
+ err: fmt.Errorf("generateConfig needs 1, 2, or 3 args"),
+ },
+ }
+)
+
+func TestGenerateConfig(t *testing.T) {
+ for _, test := range generateConfigTestcases {
+ out, err := generateConfig(test.args...)
+ if !reflect.DeepEqual(err, test.err) || !bytes.Equal(out, test.exp) {
+ t.Logf("TEST %v", test.name)
+ fncCall := fmt.Sprintf("genrateConfig(%v)", test.args)
+ t.Errorf("%s\ngot:[%v, %v]\nwant:[%v, %v]", fncCall, string(out), err, string(test.exp), test.err)
+ }
+ }
+}
+
+func TestCellRE(t *testing.T) {
+ testcases := []struct {
+ s string
+ exp bool
+ }{
+ {"blahblahblah\n Cell 01:", true},
+ {"blahblahblah\n Cell 01: blah blah", true},
+ {"\"Cell\"", false},
+ {"\"blah blah Cell blah blah\"", false},
+ }
+ for _, test := range testcases {
+ if out := cellRE.MatchString(test.s); out != test.exp {
+ t.Errorf("%s\ngot:%v\nwant:%v", test.s, out, test.exp)
+ }
+ }
+}
+
+func TestEssidRE(t *testing.T) {
+ testcases := []struct {
+ s string
+ exp bool
+ }{
+ {"blahblahblah\n ESSID:\"stub\"", true},
+ {"blahblahblah\n ESSID:\"stub\"\n", true},
+ {"blahblahblah\n ESSID:\"stub-stub\"", true},
+ {"blahblahblah\n ESSID:\"stub-stub\"\n", true},
+ {"blah blah ESSID blah", false},
+ }
+ for _, test := range testcases {
+ if out := essidRE.MatchString(test.s); out != test.exp {
+ t.Errorf("%s\ngot:%v\nwant:%v", test.s, out, test.exp)
+ }
+ }
+}
+
+func TestEncKeyOptRE(t *testing.T) {
+ testcases := []struct {
+ s string
+ exp bool
+ }{
+ {"blahblahblah\n Encryption key:on\n", true},
+ {"blahblahblah\n Encryption key:on", true},
+ {"blahblahblah\n Encryption key:off\n", true},
+ {"blahblahblah\n Encryption key:off", true},
+ {"blah blah Encryption key blah blah", false},
+ {"blah blah Encryption key:on blah blah", false},
+ {"blah blah Encryption key:off blah blah", false},
+ }
+ for _, test := range testcases {
+ if out := encKeyOptRE.MatchString(test.s); out != test.exp {
+ t.Errorf("%s\ngot:%v\nwant:%v", test.s, out, test.exp)
+ }
+ }
+}
+
+func TestWpa2RE(t *testing.T) {
+ testcases := []struct {
+ s string
+ exp bool
+ }{
+ {"blahblahblah\n IE: IEEE 802.11i/WPA2 Version 1\n", true},
+ {"blahblahblah\n IE: IEEE 802.11i/WPA2 Version 1", true},
+ {"blah blah IE: IEEE 802.11i/WPA2 Version 1", false},
+ }
+ for _, test := range testcases {
+ if out := wpa2RE.MatchString(test.s); out != test.exp {
+ t.Errorf("%s\ngot:%v\nwant:%v", test.s, out, test.exp)
+ }
+ }
+}
+
+func TestAuthSuitesRE(t *testing.T) {
+ testcases := []struct {
+ s string
+ exp bool
+ }{
+ {"blahblahblah\n Authentication Suites (1) : 802.1x\n", true},
+ {"blahblahblah\n Authentication Suites (1) : 802.1x", true},
+ {"blahblahblah\n Authentication Suites (1) : PSK\n", true},
+ {"blahblahblah\n Authentication Suites (1) : PSK\n", true},
+ {"blahblahblah\n Authentication Suites (2) : blah, blah\n", true},
+ {"blahblahblah\n Authentication Suites (1) : other protocol\n", true},
+ {"blahblahblah\n Authentication Suites (1) : other protocol", true},
+ {"blah blah Authentication Suites : blah blah", false},
+ }
+ for _, test := range testcases {
+ if out := authSuitesRE.MatchString(test.s); out != test.exp {
+ t.Errorf("%s\ngot:%v\nwant:%v", test.s, out, test.exp)
+ }
+ }
+}
+
+func TestParseIwlistOutput(t *testing.T) {
+ var (
+ o []byte
+ exp, out []Option
+ err error
+ )
+
+ // No WiFi present
+ o = nil
+ exp = nil
+ out = parseIwlistOut(o)
+ if !reflect.DeepEqual(out, exp) {
+ t.Errorf("\ngot:[%v]\nwant:[%v]", out, exp)
+ }
+
+ // Only 1 WiFi present
+ o = []byte(`
+wlan0 Scan completed :
+ Cell 01 - Address: 00:00:00:00:00:01
+ Channel:001
+ Frequency:5.58 GHz (Channel 001)
+ Quality=1/2 Signal level=-23 dBm
+ Encryption key:on
+ ESSID:"stub-wpa-eap-1"
+ Bit Rates:36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 1260ms ago
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: IEEE 802.11i/WPA2 Version 1
+ Group Cipher : CCMP
+ Pairwise Ciphers (1) : CCMP
+ Authentication Suites (1) : 802.1x
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+`)
+ exp = []Option{
+ {"stub-wpa-eap-1", WpaEap},
+ }
+ out = parseIwlistOut(o)
+ if !reflect.DeepEqual(out, exp) {
+ t.Errorf("\ngot:[%v]\nwant:[%v]", out, exp)
+ }
+
+ // Regular scenarios (many choices)
+ exp = []Option{
+ {"stub-wpa-eap-1", WpaEap},
+ {"stub-rsa-1", NoEnc},
+ {"stub-wpa-psk-1", WpaPsk},
+ {"stub-rsa-2", NoEnc},
+ {"stub-wpa-psk-2", WpaPsk},
+ }
+ o, err = ioutil.ReadFile("iwlistStubOutput.txt")
+ if err != nil {
+ t.Errorf("error reading iwlistStubOutput.txt: %v", err)
+ }
+ out = parseIwlistOut(o)
+ if !reflect.DeepEqual(out, exp) {
+ t.Errorf("\ngot:[%v]\nwant:[%v]", out, exp)
+ }
+}
+
+func BenchmarkParseIwlistOutput(b *testing.B) {
+ // Set Up
+ o, err := ioutil.ReadFile("iwlistStubOutput.txt")
+ if err != nil {
+ b.Errorf("error reading iwlistStubOutput.txt: %v", err)
+ }
+ for i := 0; i < b.N; i++ {
+ parseIwlistOut(o)
+ }
+}
diff --git a/nichrome/pkg/wifi/iwlistStubOutput.txt b/nichrome/pkg/wifi/iwlistStubOutput.txt
new file mode 100644
index 000000000..8f9ee1f3c
--- /dev/null
+++ b/nichrome/pkg/wifi/iwlistStubOutput.txt
@@ -0,0 +1,184 @@
+wlan0 Scan completed :
+ Cell 01 - Address: 00:00:00:00:00:01
+ Channel:001
+ Frequency:5.58 GHz (Channel 001)
+ Quality=1/2 Signal level=-23 dBm
+ Encryption key:on
+ ESSID:"stub-wpa-eap-1"
+ Bit Rates:36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 1260ms ago
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: IEEE 802.11i/WPA2 Version 1
+ Group Cipher : CCMP
+ Pairwise Ciphers (1) : CCMP
+ Authentication Suites (1) : 802.1x
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ Cell 02 - Address: 00:00:00:00:00:02
+ Channel:002
+ Frequency:5.58 GHz (Channel 001)
+ Quality=1/2 Signal level=-23 dBm
+ Encryption key:on
+ ESSID:"stub-wpa-eap-1"
+ Bit Rates:36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 1260ms ago
+ IE: Unknown: 0000000000000000000000000
+ IE: Unknown: 0000000
+ IE: Unknown: 000000000000000000
+ IE: IEEE 802.11i/WPA2 Version 1
+ Group Cipher : CCMP
+ Pairwise Ciphers (1) : CCMP
+ Authentication Suites (1) : 802.1x
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000000
+ IE: Unknown: 00000000000000000000
+ IE: Unknown: 000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 00000000000000000000000
+ IE: Unknown: 000000000000000000
+ Cell 03 - Address: 00:00:00:00:00:03
+ Channel:003
+ Frequency:5.785 GHz
+ Quality=50/70 Signal level=-60 dBm
+ Encryption key:off
+ ESSID:"stub-rsa-1"
+ Bit Rates:36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 188ms ago
+ IE: Unknown: 0000000000000000000000000
+ IE: Unknown: 0000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000000
+ IE: Unknown: 00000000000000000000
+ IE: Unknown: 000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 00000000000000000000000
+ IE: Unknown: 000000000000000000
+ Cell 04 - Address: 00:00:00:00:00:04
+ Channel:004
+ Frequency:5.785 GHz
+ Quality=50/70 Signal level=-60 dBm
+ Encryption key:on
+ ESSID:"stub-wpa-psk-1"
+ Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 188ms ago
+ IE: Unknown: 0000000000000000000000000
+ IE: Unknown: 0000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000000
+ IE: Unknown: 00000000000000000000
+ IE: Unknown: 000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 00000000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: IEEE 802.11i/WPA2 Version 1
+ Group Cipher : CCMP
+ Pairwise Ciphers (1) : CCMP
+ Authentication Suites (1) : PSK
+ Cell 05 - Address: 00:00:00:00:00:05
+ Channel:005
+ Frequency:2.412 GHz (Channel 1)
+ Quality=48/70 Signal level=-62 dBm
+ Encryption key:off
+ ESSID:"stub-rsa-2"
+ Bit Rates:36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 3416ms ago
+ IE: Unknown: 0000000000000000000000000
+ IE: Unknown: 0000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000000
+ IE: Unknown: 00000000000000000000
+ IE: Unknown: 000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 00000000000000000000000
+ IE: Unknown: 000000000000000000
+ Cell 06 - Address: 00:00:00:00:00:06
+ Channel:006
+ Frequency:5.785 GHz
+ Quality=50/70 Signal level=-60 dBm
+ Encryption key:on
+ ESSID:"stub-wpa-psk-2"
+ Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 188ms ago
+ IE: Unknown: 0000000000000000000000000
+ IE: Unknown: 0000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000000
+ IE: Unknown: 00000000000000000000
+ IE: Unknown: 000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 00000000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: IEEE 802.11i/WPA2 Version 1
+ Group Cipher : CCMP
+ Pairwise Ciphers (1) : CCMP
+ Authentication Suites (1) : PSK
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 00000000000000000000000
+ IE: Unknown: 000000000000000000
+ Cell 07 - Address: 00:00:00:00:00:07
+ Channel:007
+ Frequency:5.785 GHz
+ Quality=50/70 Signal level=-60 dBm
+ Encryption key:on
+ ESSID:"stub-wpa-psk-2"
+ Bit Rates:24 Mb/s; 36 Mb/s; 48 Mb/s; 54 Mb/s
+ Mode:Master
+ Extra:tsf=000000000000000000
+ Extra: Last beacon: 188ms ago
+ IE: Unknown: 0000000000000000000000000
+ IE: Unknown: 0000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000000
+ IE: Unknown: 00000000000000000000
+ IE: Unknown: 000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 00000000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: IEEE 802.11i/WPA2 Version 1
+ Group Cipher : CCMP
+ Pairwise Ciphers (1) : CCMP
+ Authentication Suites (1) : PSK
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 0000000000000000000
+ IE: Unknown: 0000000000000000000000
+ IE: Unknown: 00000000000000000000
+ IE: Unknown: 000000000000000
+ IE: Unknown: 000000000000000000
+ IE: Unknown: 000000000000000000
diff --git a/nichrome/pkg/wifi/native.go b/nichrome/pkg/wifi/native.go
new file mode 100644
index 000000000..d0590ccf2
--- /dev/null
+++ b/nichrome/pkg/wifi/native.go
@@ -0,0 +1,38 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package wifi
+
+import (
+ "fmt"
+ "syscall"
+ "unsafe"
+)
+
+type NativeWorker struct {
+ Interface string
+ FD int
+ Range IWRange
+}
+
+func NewNativeWorker(i string) (WiFi, error) {
+ s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_IP)
+ if err != nil {
+ return nil, err
+ }
+ return &NativeWorker{FD: s, Interface: i}, nil
+}
+
+func (w *NativeWorker) Scan() ([]Option, error) {
+ return nil, fmt.Errorf("Not Yet")
+}
+
+func (w *NativeWorker) GetID() (string, error) {
+ return "", fmt.Errorf("Not Yet")
+}
+
+func (w *NativeWorker) Connect(a ...string) error {
+ _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(w.FD), SIOCGIWRANGE, uintptr(unsafe.Pointer(&w.Range)))
+ return err
+}
diff --git a/nichrome/pkg/wifi/native_test.go b/nichrome/pkg/wifi/native_test.go
new file mode 100644
index 000000000..e6d69153c
--- /dev/null
+++ b/nichrome/pkg/wifi/native_test.go
@@ -0,0 +1,26 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package wifi
+
+import (
+ "testing"
+)
+
+func TestNative(t *testing.T) {
+ // Some things may fail as there may be no wlan or we might not
+ // have the right privs. So just bail out of the test if some early
+ // ops fail.
+ w, err := NewNativeWorker("wlan0")
+ if err != nil {
+ t.Log(err)
+ return
+ }
+ t.Logf("Native is %v", w)
+ err = w.Connect()
+ if err != nil {
+ t.Log(err)
+ return
+ }
+}
diff --git a/nichrome/pkg/wifi/stub.go b/nichrome/pkg/wifi/stub.go
new file mode 100644
index 000000000..c7c31b5e6
--- /dev/null
+++ b/nichrome/pkg/wifi/stub.go
@@ -0,0 +1,28 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package wifi
+
+var _ = WiFi(&StubWorker{})
+
+type StubWorker struct {
+ Options []Option
+ ID string
+}
+
+func (w *StubWorker) Scan() ([]Option, error) {
+ return w.Options, nil
+}
+
+func (w *StubWorker) GetID() (string, error) {
+ return w.ID, nil
+}
+
+func (*StubWorker) Connect(a ...string) error {
+ return nil
+}
+
+func NewStubWorker(id string, options ...Option) (WiFi, error) {
+ return &StubWorker{ID: id, Options: options}, nil
+}
diff --git a/nichrome/pkg/wifi/types.go b/nichrome/pkg/wifi/types.go
new file mode 100644
index 000000000..7d00ba875
--- /dev/null
+++ b/nichrome/pkg/wifi/types.go
@@ -0,0 +1,16 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package wifi
+
+type Option struct {
+ Essid string
+ AuthSuite SecProto
+}
+
+type WiFi interface {
+ Scan() ([]Option, error)
+ GetID() (string, error)
+ Connect(a ...string) error
+}
diff --git a/nichrome/pkg/wifi/wireless.go b/nichrome/pkg/wifi/wireless.go
new file mode 100644
index 000000000..5bfd4c4d8
--- /dev/null
+++ b/nichrome/pkg/wifi/wireless.go
@@ -0,0 +1,2252 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package wifi
+
+import "unsafe" // yuck
+// This file is from the linux wifi definitions. We leave the
+// original in here for reference. We'll probably remove it later.
+var _ = `
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version : 22 16.3.07
+ *
+ * Authors : Jean Tourrilhes - HPL -
+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
+ */
+
+#ifndef _LINUX_WIRELESS_H
+#define _LINUX_WIRELESS_H
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands. This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ * # net/core/dev.c (two place + add include)
+ * # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ * # net/core/dev.c (two other places)
+ * # include/linux/netdevice.h (one place)
+ * # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ * # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ * # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ * # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** INCLUDES *****************************/
+
+#include /* for __u* and __s* typedefs */
+#include /* for "struct sockaddr" et al */
+#include /* for IFNAMSIZ and co... */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+#define WIRELESS_EXT 22
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
+ * - Encryption renamed to Encode to avoid US regulation problems
+ * - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ * - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ * - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ * - Changed my e-mail address
+ * - More 802.11 support (nickname, rate, rts, frag)
+ * - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ * - Support for 'mode of operation' (ad-hoc, managed...)
+ * - Support for unicast and multicast power saving
+ * - Change encoding to support larger tokens (>64 bits)
+ * - Updated iw_params (disable, flags) and use it for NWID
+ * - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ * - Add PM capability to range structure
+ * - Add PM modifier : MAX/MIN/RELATIVE
+ * - Add encoding option : IW_ENCODE_NOKEY
+ * - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ * - Add WE version in range (help backward/forward compatibility)
+ * - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ * - Add new statistics (frag, retry, beacon)
+ * - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ * - Document creation of new driver API.
+ * - Extract union iwreq_data from struct iwreq (for new driver API).
+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ * - Wireless Events support : define struct iw_event
+ * - Define additional specific event numbers
+ * - Add "addr" and "param" fields in union iwreq_data
+ * - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ * - Make struct iw_freq signed (both m & e), add explicit padding
+ * - Add IWEVCUSTOM for driver specific event/scanning token
+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ * - Reshuffle struct iw_range for increases, add filler
+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ * - Add flags to frequency -> auto/fixed
+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ * - Wireless Event capability in struct iw_range
+ * - Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen )
+ * ----------
+ * - Add support for WPA/WPA2
+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
+ * SIOCGIWENCODEEXT)
+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
+ * - Add SIOCSIWMLME
+ * - Add SIOCSIWPMKSA
+ * - Add struct iw_range bit field for supported encoding capabilities
+ * - Add optional scan request parameters for SIOCSIWSCAN
+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ * related parameters (extensible up to 4096 parameter values)
+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ *
+ * V18 to V19
+ * ----------
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove header includes to help user space
+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
+ *
+ * V19 to V20
+ * ----------
+ * - RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ * - Remove (struct net_device *)->get_wireless_stats()
+ * - Change length in ESSID and NICK to strlen() instead of strlen()+1
+ * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ * - Power/Retry relative values no longer * 100000
+ * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
+ *
+ * V21 to V22
+ * ----------
+ * - Prevent leaking of kernel space in stream on 64 bits.
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Wireless Identification */
+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
+#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
+#define SIOCSIWMODE 0x8B06 /* set operation mode */
+#define SIOCGIWMODE 0x8B07 /* get operation mode */
+#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */
+#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */
+
+/* Informative stuff */
+#define SIOCSIWRANGE 0x8B0A /* Unused */
+#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */
+#define SIOCSIWPRIV 0x8B0C /* Unused */
+#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
+#define SIOCSIWSTATS 0x8B0E /* Unused */
+#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
+#define SIOCSIWSPY 0x8B10 /* set spy addresses */
+#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */
+
+/* Access Point manipulation */
+#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
+#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
+#define SIOCGIWSCAN 0x8B19 /* get scanning results */
+
+/* 802.11 specific support */
+#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */
+#define SIOCGIWESSID 0x8B1B /* get ESSID */
+#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */
+#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE... */
+
+/* Other parameters useful in 802.11 and some other devices */
+#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
+#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */
+#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */
+#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */
+#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */
+#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */
+#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */
+#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */
+#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */
+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
+#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
+
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
+ * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 32 ioctl are wireless device private, for 16 commands.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+#define SIOCIWFIRSTPRIV 0x8BE0
+#define SIOCIWLASTPRIV 0x8BFF
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'even' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+#define SIOCIWFIRST 0x8B00
+#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */
+#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST)
+#define IW_HANDLER(id, func) \
+ [IW_IOCTL_IDX(id)] = func
+
+/* Odd : get (world access), even : set (root access) */
+#define IW_IS_SET(cmd) (!((cmd) & 0x1))
+#define IW_IS_GET(cmd) ((cmd) & 0x1)
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
+ * (scan results); This includes id and
+ * length fields. One IWEVGENIE may
+ * contain more than one IE. Scan
+ * results may contain one or more
+ * IWEVGENIE events. */
+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
+ * (struct iw_michaelmicfailure)
+ */
+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
+ * The data includes id and length
+ * fields and may contain more than one
+ * IE. This event is required in
+ * Managed mode if the driver
+ * generates its own WPA/RSN IE. This
+ * should be sent just before
+ * IWEVREGISTERED event for the
+ * association. */
+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
+ * Response. The data includes id and
+ * length fields and may contain more
+ * than one IE. This may be sent
+ * between IWEVASSOCREQIE and
+ * IWEVREGISTERED events for the
+ * association. */
+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
+ * pre-authentication
+ * (struct iw_pmkid_cand) */
+
+#define IWEVFIRST 0x8C00
+#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */
+#define IW_PRIV_TYPE_NONE 0x0000
+#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
+#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
+#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
+
+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */
+
+#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+#define IW_MAX_FREQUENCIES 32
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+#define IW_MAX_BITRATES 32
+
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER 8
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
+
+/* Maximum of address that you may set with SPY */
+#define IW_MAX_SPY 8
+
+/* Maximum of address that you may get in the
+ list of access points in range */
+#define IW_MAX_AP 64
+
+/* Maximum size of the ESSID and NICKN strings */
+#define IW_ESSID_MAX_SIZE 32
+
+/* Modes of operation */
+#define IW_MODE_AUTO 0 /* Let the driver decides */
+#define IW_MODE_ADHOC 1 /* Single cell network */
+#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */
+#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
+#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
+#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
+#define IW_MODE_MESH 7 /* Mesh (IEEE 802.11s) network */
+
+/* Statistics flags (bitmask in updated) */
+#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
+#define IW_QUAL_LEVEL_UPDATED 0x02
+#define IW_QUAL_NOISE_UPDATED 0x04
+#define IW_QUAL_ALL_UPDATED 0x07
+#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
+#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
+#define IW_QUAL_LEVEL_INVALID 0x20
+#define IW_QUAL_NOISE_INVALID 0x40
+#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */
+#define IW_QUAL_ALL_INVALID 0x70
+
+/* Frequency flags */
+#define IW_FREQ_AUTO 0x00 /* Let the driver decides */
+#define IW_FREQ_FIXED 0x01 /* Force a specific value */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+#define IW_MAX_ENCODING_SIZES 8
+
+/* Maximum size of the encoding token in bytes */
+#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
+#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
+#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
+#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
+#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
+#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
+#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
+
+/* Power management flags available (along with the value, if any) */
+#define IW_POWER_ON 0x0000 /* No details... */
+#define IW_POWER_TYPE 0xF000 /* Type of parameter */
+#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */
+#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */
+#define IW_POWER_MODE 0x0F00 /* Power Management mode */
+#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */
+#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */
+#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */
+#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */
+#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
+#define IW_POWER_MIN 0x0001 /* Value is a minimum */
+#define IW_POWER_MAX 0x0002 /* Value is a maximum */
+#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
+#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
+#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
+#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */
+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
+
+/* Retry limits and lifetime flags available */
+#define IW_RETRY_ON 0x0000 /* No details... */
+#define IW_RETRY_TYPE 0xF000 /* Type of parameter */
+#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/
+#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */
+#define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */
+#define IW_RETRY_MIN 0x0001 /* Value is a minimum */
+#define IW_RETRY_MAX 0x0002 /* Value is a maximum */
+#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT 0x0010 /* Value is for short packets */
+#define IW_RETRY_LONG 0x0020 /* Value is for long packets */
+
+/* Scanning request flags */
+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */
+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */
+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */
+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */
+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */
+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */
+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+#define IW_SCAN_TYPE_ACTIVE 0
+#define IW_SCAN_TYPE_PASSIVE 1
+/* Maximum size of returned data */
+#define IW_SCAN_MAX_DATA 4096 /* In bytes */
+
+/* Scan capability flags - in (struct iw_range *)->scan_capa */
+#define IW_SCAN_CAPA_NONE 0x00
+#define IW_SCAN_CAPA_ESSID 0x01
+#define IW_SCAN_CAPA_BSSID 0x02
+#define IW_SCAN_CAPA_CHANNEL 0x04
+#define IW_SCAN_CAPA_MODE 0x08
+#define IW_SCAN_CAPA_RATE 0x10
+#define IW_SCAN_CAPA_TYPE 0x20
+#define IW_SCAN_CAPA_TIME 0x40
+
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX 256 /* In bytes */
+
+/* Generic information element */
+#define IW_GENERIC_IE_MAX 1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+#define IW_MLME_DEAUTH 0
+#define IW_MLME_DISASSOC 1
+#define IW_MLME_AUTH 2
+#define IW_MLME_ASSOC 3
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+#define IW_AUTH_INDEX 0x0FFF
+#define IW_AUTH_FLAGS 0xF000
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+#define IW_AUTH_WPA_VERSION 0
+#define IW_AUTH_CIPHER_PAIRWISE 1
+#define IW_AUTH_CIPHER_GROUP 2
+#define IW_AUTH_KEY_MGMT 3
+#define IW_AUTH_TKIP_COUNTERMEASURES 4
+#define IW_AUTH_DROP_UNENCRYPTED 5
+#define IW_AUTH_80211_AUTH_ALG 6
+#define IW_AUTH_WPA_ENABLED 7
+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
+#define IW_AUTH_ROAMING_CONTROL 9
+#define IW_AUTH_PRIVACY_INVOKED 10
+#define IW_AUTH_CIPHER_GROUP_MGMT 11
+#define IW_AUTH_MFP 12
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT
+ * values (bit field) */
+#define IW_AUTH_CIPHER_NONE 0x00000001
+#define IW_AUTH_CIPHER_WEP40 0x00000002
+#define IW_AUTH_CIPHER_TKIP 0x00000004
+#define IW_AUTH_CIPHER_CCMP 0x00000008
+#define IW_AUTH_CIPHER_WEP104 0x00000010
+#define IW_AUTH_CIPHER_AES_CMAC 0x00000020
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+#define IW_AUTH_KEY_MGMT_802_1X 1
+#define IW_AUTH_KEY_MGMT_PSK 2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
+#define IW_AUTH_ALG_LEAP 0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
+ * control */
+
+/* IW_AUTH_MFP (management frame protection) values */
+#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */
+#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */
+#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_SEQ_MAX_SIZE 8
+/* struct iw_encode_ext ->alg */
+#define IW_ENCODE_ALG_NONE 0
+#define IW_ENCODE_ALG_WEP 1
+#define IW_ENCODE_ALG_TKIP 2
+#define IW_ENCODE_ALG_CCMP 3
+#define IW_ENCODE_ALG_PMK 4
+#define IW_ENCODE_ALG_AES_CMAC 5
+/* struct iw_encode_ext ->ext_flags */
+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
+#define IW_MICFAILURE_GROUP 0x00000004
+#define IW_MICFAILURE_PAIRWISE 0x00000008
+#define IW_MICFAILURE_STAKEY 0x00000010
+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
+ */
+
+/* Bit field values for enc_capa in struct iw_range */
+#define IW_ENC_CAPA_WPA 0x00000001
+#define IW_ENC_CAPA_WPA2 0x00000002
+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
+#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010
+
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \
+ (cmd - SIOCIWFIRSTPRIV + 0x60) : \
+ (cmd - SIOCIWFIRST))
+#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5)
+#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \
+ IW_EVENT_CAPA_MASK(0x8B06) | \
+ IW_EVENT_CAPA_MASK(0x8B1A))
+#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A))
+/* "Easy" macro to set events in iw_range (less efficient) */
+#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
+#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
+
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ * Generic format for most parameters that fit in an int
+ */
+struct iw_param {
+ __s32 value; /* The value of the parameter itself */
+ __u8 fixed; /* Hardware should not use auto select */
+ __u8 disabled; /* Disable the feature */
+ __u16 flags; /* Various specifc flags (if any) */
+};
+
+/*
+ * For all data larger than 16 octets, we need to use a
+ * pointer to memory allocated in user space.
+ */
+struct iw_point {
+ void *pointer; /* Pointer to the data (in user space) */
+ __u16 length; /* number of fields or size in bytes */
+ __u16 flags; /* Optional params */
+};
+
+
+/*
+ * A frequency
+ * For numbers lower than 10^9, we encode the number in 'm' and
+ * set 'e' to 0
+ * For number greater than 10^9, we divide it by the lowest power
+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ * The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+struct iw_freq {
+ __s32 m; /* Mantissa */
+ __s16 e; /* Exponent */
+ __u8 i; /* List index (when in range struct) */
+ __u8 flags; /* Flags (fixed/auto) */
+};
+
+/*
+ * Quality of the link
+ */
+struct iw_quality {
+ __u8 qual; /* link quality (%retries, SNR,
+ %missed beacons or better...) */
+ __u8 level; /* signal level (dBm) */
+ __u8 noise; /* noise level (dBm) */
+ __u8 updated; /* Flags to know if updated */
+};
+
+/*
+ * Packet discarded in the wireless adapter due to
+ * "wireless" specific problems...
+ * Note : the list of counter and statistics in net_device_stats
+ * is already pretty exhaustive, and you should use that first.
+ * This is only additional stats...
+ */
+struct iw_discarded {
+ __u32 nwid; /* Rx : Wrong nwid/essid */
+ __u32 code; /* Rx : Unable to code/decode (WEP) */
+ __u32 fragment; /* Rx : Can't perform MAC reassembly */
+ __u32 retries; /* Tx : Max MAC retries num reached */
+ __u32 misc; /* Others cases */
+};
+
+/*
+ * Packet/Time period missed in the wireless adapter due to
+ * "wireless" specific problems...
+ */
+struct iw_missed {
+ __u32 beacon; /* Missed beacons/superframe */
+};
+
+/*
+ * Quality range (for spy threshold)
+ */
+struct iw_thrspy {
+ struct sockaddr addr; /* Source address (hw/mac) */
+ struct iw_quality qual; /* Quality of the link */
+ struct iw_quality low; /* Low threshold */
+ struct iw_quality high; /* High threshold */
+};
+
+/*
+ * Optional data for scan request
+ *
+ * Note: these optional parameters are controlling parameters for the
+ * scanning behavior, these do not apply to getting scan results
+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ * provide a merged results with all BSSes even if the previous scan
+ * request limited scanning to a subset, e.g., by specifying an SSID.
+ * Especially, scan results are required to include an entry for the
+ * current BSS if the driver is in Managed mode and associated with an AP.
+ */
+struct iw_scan_req {
+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+ __u8 essid_len;
+ __u8 num_channels; /* num entries in channel_list;
+ * 0 = scan all allowed channels */
+ __u8 flags; /* reserved as padding; use zero, this may
+ * be used in the future for adding flags
+ * to request different scan behavior */
+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+ * individual address of a specific BSS */
+
+ /*
+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+ * the current ESSID. This allows scan requests for specific ESSID
+ * without having to change the current ESSID and potentially breaking
+ * the current association.
+ */
+ __u8 essid[IW_ESSID_MAX_SIZE];
+
+ /*
+ * Optional parameters for changing the default scanning behavior.
+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
+ * reasonable default values. min_channel_time defines the time that
+ * will be used to wait for the first reply on each channel. If no
+ * replies are received, next channel will be scanned after this. If
+ * replies are received, total time waited on the channel is defined by
+ * max_channel_time.
+ */
+ __u32 min_channel_time; /* in TU */
+ __u32 max_channel_time; /* in TU */
+
+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
+};
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ * Extended data structure for get/set encoding (this is used with
+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ * only the data contents changes (key data -> this structure, including
+ * key data).
+ *
+ * If the new key is the first group key, it will be set as the default
+ * TX key. Otherwise, default TX key index is only changed if
+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ * special "change TX key index" operation which is indicated by setting
+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ * tx_seq/rx_seq are only used when respective
+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ * used only by an Authenticator (AP or an IBSS station) to get the
+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ * debugging/testing.
+ */
+struct iw_encode_ext {
+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+ * (group) keys or unicast address for
+ * individual keys */
+ __u16 alg; /* IW_ENCODE_ALG_* */
+ __u16 key_len;
+ __u8 key[0];
+};
+
+/* SIOCSIWMLME data */
+struct iw_mlme {
+ __u16 cmd; /* IW_MLME_* */
+ __u16 reason_code;
+ struct sockaddr addr;
+};
+
+/* SIOCSIWPMKSA data */
+#define IW_PMKSA_ADD 1
+#define IW_PMKSA_REMOVE 2
+#define IW_PMKSA_FLUSH 3
+
+#define IW_PMKID_LEN 16
+
+struct iw_pmksa {
+ __u32 cmd; /* IW_PMKSA_* */
+ struct sockaddr bssid;
+ __u8 pmkid[IW_PMKID_LEN];
+};
+
+/* IWEVMICHAELMICFAILURE data */
+struct iw_michaelmicfailure {
+ __u32 flags;
+ struct sockaddr src_addr;
+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+};
+
+/* IWEVPMKIDCAND data */
+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
+struct iw_pmkid_cand {
+ __u32 flags; /* IW_PMKID_CAND_* */
+ __u32 index; /* the smaller the index, the higher the
+ * priority */
+ struct sockaddr bssid;
+};
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+struct iw_statistics {
+ __u16 status; /* Status
+ * - device dependent for now */
+
+ struct iw_quality qual; /* Quality of the link
+ * (instant/mean/max) */
+ struct iw_discarded discard; /* Packet discarded counts */
+ struct iw_missed miss; /* Packet missed counts */
+};
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ */
+union iwreq_data {
+ /* Config - generic */
+ char name[IFNAMSIZ];
+ /* Name : used to verify the presence of wireless extensions.
+ * Name of the protocol/provider... */
+
+ struct iw_point essid; /* Extended network name */
+ struct iw_param nwid; /* network id (or domain - the cell) */
+ struct iw_freq freq; /* frequency or channel :
+ * 0-1000 = channel
+ * > 1000 = frequency in Hz */
+
+ struct iw_param sens; /* signal level threshold */
+ struct iw_param bitrate; /* default bit rate */
+ struct iw_param txpower; /* default transmit power */
+ struct iw_param rts; /* RTS threshold threshold */
+ struct iw_param frag; /* Fragmentation threshold */
+ __u32 mode; /* Operation mode */
+ struct iw_param retry; /* Retry limits & lifetime */
+
+ struct iw_point encoding; /* Encoding stuff : tokens */
+ struct iw_param power; /* PM duration/timeout */
+ struct iw_quality qual; /* Quality part of statistics */
+
+ struct sockaddr ap_addr; /* Access point address */
+ struct sockaddr addr; /* Destination address (hw/mac) */
+
+ struct iw_param param; /* Other small parameters */
+ struct iw_point data; /* Other large parameters */
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+ */
+struct iwreq {
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
+ } ifr_ifrn;
+
+ /* Data part (defined just above) */
+ union iwreq_data u;
+};
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ * For those ioctl which want to exchange mode data that what could
+ * fit in the above structure...
+ */
+
+/*
+ * Range of parameters
+ */
+
+struct iw_range {
+ /* Informative stuff (to choose between different interface) */
+ __u32 throughput; /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ __u32 min_nwid; /* Minimal NWID we are able to set */
+ __u32 max_nwid; /* Maximal NWID we are able to set */
+
+ /* Old Frequency (backward compat - moved lower ) */
+ __u16 old_num_channels;
+ __u8 old_num_frequency;
+
+ /* Scan capabilities */
+ __u8 scan_capa; /* IW_SCAN_CAPA_* bit field */
+
+ /* Wireless event capability bitmasks */
+ __u32 event_capa[6];
+
+ /* signal level threshold range */
+ __s32 sensitivity;
+
+ /* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+ * If the quality is absolute, it will be in the range [0 ; max_qual],
+ * if the quality is dBm, it will be in the range [max_qual ; 0].
+ * Don't forget that we use 8 bit arithmetics... */
+ struct iw_quality max_qual; /* Quality of the link */
+ /* This should contain the average/typical values of the quality
+ * indicator. This should be the threshold between a "good" and
+ * a "bad" link (example : monitor going from green to orange).
+ * Currently, user space apps like quality monitors don't have any
+ * way to calibrate the measurement. With this, they can split
+ * the range between 0 and max_qual in different quality level
+ * (using a geometric subdivision centered on the average).
+ * I expect that people doing the user space apps will feedback
+ * us on which value we need to put in each driver... */
+ struct iw_quality avg_qual; /* Quality of the link */
+
+ /* Rates */
+ __u8 num_bitrates; /* Number of entries in the list */
+ __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */
+
+ /* RTS threshold */
+ __s32 min_rts; /* Minimal RTS threshold */
+ __s32 max_rts; /* Maximal RTS threshold */
+
+ /* Frag threshold */
+ __s32 min_frag; /* Minimal frag threshold */
+ __s32 max_frag; /* Maximal frag threshold */
+
+ /* Power Management duration & timeout */
+ __s32 min_pmp; /* Minimal PM period */
+ __s32 max_pmp; /* Maximal PM period */
+ __s32 min_pmt; /* Minimal PM timeout */
+ __s32 max_pmt; /* Maximal PM timeout */
+ __u16 pmp_flags; /* How to decode max/min PM period */
+ __u16 pmt_flags; /* How to decode max/min PM timeout */
+ __u16 pm_capa; /* What PM options are supported */
+
+ /* Encoder stuff */
+ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */
+ __u8 num_encoding_sizes; /* Number of entry in the list */
+ __u8 max_encoding_tokens; /* Max number of tokens */
+ /* For drivers that need a "login/passwd" form */
+ __u8 encoding_login_index; /* token index for login token */
+
+ /* Transmit power */
+ __u16 txpower_capa; /* What options are supported */
+ __u8 num_txpower; /* Number of entries in the list */
+ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */
+
+ /* Wireless Extension version info */
+ __u8 we_version_compiled; /* Must be WIRELESS_EXT */
+ __u8 we_version_source; /* Last update of source */
+
+ /* Retry limits and lifetime */
+ __u16 retry_capa; /* What retry options are supported */
+ __u16 retry_flags; /* How to decode max/min retry limit */
+ __u16 r_time_flags; /* How to decode max/min retry life */
+ __s32 min_retry; /* Minimal number of retries */
+ __s32 max_retry; /* Maximal number of retries */
+ __s32 min_r_time; /* Minimal retry lifetime */
+ __s32 max_r_time; /* Maximal retry lifetime */
+
+ /* Frequency */
+ __u16 num_channels; /* Number of channels [0; num - 1] */
+ __u8 num_frequency; /* Number of entry in the list */
+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
+
+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
+};
+
+/*
+ * Private ioctl interface information
+ */
+
+struct iw_priv_args {
+ __u32 cmd; /* Number of the ioctl to issue */
+ __u16 set_args; /* Type and number of args */
+ __u16 get_args; /* Type and number of args */
+ char name[IFNAMSIZ]; /* Name of the extension */
+};
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+struct iw_event {
+ __u16 len; /* Real length of this stuff */
+ __u16 cmd; /* Wireless IOCTL */
+ union iwreq_data u; /* IOCTL fixed payload */
+};
+
+/* Size of the Event prefix (including padding and alignement junk) */
+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events */
+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ)
+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32))
+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* iw_point events are special. First, the payload (extra data) come at
+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
+ * we omit the pointer, so start at an offset. */
+#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+ (char *) NULL)
+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \
+ IW_EV_POINT_OFF)
+
+
+/* Size of the Event prefix when packed in stream */
+#define IW_EV_LCP_PK_LEN (4)
+/* Size of the various events when packed in stream */
+#define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ)
+#define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(__u32))
+#define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
+#define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
+#define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
+#define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
+#define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4)
+
+#endif /* _LINUX_WIRELESS_H */
+`
+
+// This is the standard Unix style binary blob interface with all the
+// conversion fun that implies. Bummer.
+
+/*
+ * This file define a set of standard wireless extensions
+ *
+ * Version : 22 16.3.07
+ *
+ * Authors : Jean Tourrilhes - HPL -
+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
+ */
+
+/************************** DOCUMENTATION **************************/
+/*
+ * Initial APIs (1996 -> onward) :
+ * -----------------------------
+ * Basically, the wireless extensions are for now a set of standard ioctl
+ * call + /proc/net/wireless
+ *
+ * The entry /proc/net/wireless give statistics and information on the
+ * driver.
+ * This is better than having each driver having its entry because
+ * its centralised and we may remove the driver module safely.
+ *
+ * Ioctl are used to configure the driver and issue commands. This is
+ * better than command line options of insmod because we may want to
+ * change dynamically (while the driver is running) some parameters.
+ *
+ * The ioctl mechanimsm are copied from standard devices ioctl.
+ * We have the list of command plus a structure descibing the
+ * data exchanged...
+ * Note that to add these ioctl, I was obliged to modify :
+ * # net/core/dev.c (two place + add include)
+ * # net/ipv4/af_inet.c (one place + add include)
+ *
+ * /proc/net/wireless is a copy of /proc/net/dev.
+ * We have a structure for data passed from the driver to /proc/net/wireless
+ * Too add this, I've modified :
+ * # net/core/dev.c (two other places)
+ * # include/linux/netdevice.h (one place)
+ * # include/linux/proc_fs.h (one place)
+ *
+ * New driver API (2002 -> onward) :
+ * -------------------------------
+ * This file is only concerned with the user space API and common definitions.
+ * The new driver API is defined and documented in :
+ * # include/net/iw_handler.h
+ *
+ * Note as well that /proc/net/wireless implementation has now moved in :
+ * # net/core/wireless.c
+ *
+ * Wireless Events (2002 -> onward) :
+ * --------------------------------
+ * Events are defined at the end of this file, and implemented in :
+ * # net/core/wireless.c
+ *
+ * Other comments :
+ * --------------
+ * Do not add here things that are redundant with other mechanisms
+ * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
+ * wireless specific.
+ *
+ * These wireless extensions are not magic : each driver has to provide
+ * support for them...
+ *
+ * IMPORTANT NOTE : As everything in the kernel, this is very much a
+ * work in progress. Contact me if you have ideas of improvements...
+ */
+
+/***************************** VERSION *****************************/
+/*
+ * This constant is used to know the availability of the wireless
+ * extensions and to know which version of wireless extensions it is
+ * (there is some stuff that will be added in the future...)
+ * I just plan to increment with each new version.
+ */
+const WIRELESS_EXT = 22
+
+/*
+ * Changes :
+ *
+ * V2 to V3
+ * --------
+ * Alan Cox start some incompatibles changes. I've integrated a bit more.
+ * - Encryption renamed to Encode to avoid US regulation problems
+ * - Frequency changed from float to struct to avoid problems on old 386
+ *
+ * V3 to V4
+ * --------
+ * - Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ * - Missing encoding definitions in range
+ * - Access points stuff
+ *
+ * V5 to V6
+ * --------
+ * - 802.11 support (ESSID ioctls)
+ *
+ * V6 to V7
+ * --------
+ * - define IW_ESSID_MAX_SIZE and IW_MAX_AP
+ *
+ * V7 to V8
+ * --------
+ * - Changed my e-mail address
+ * - More 802.11 support (nickname, rate, rts, frag)
+ * - List index in frequencies
+ *
+ * V8 to V9
+ * --------
+ * - Support for 'mode of operation' (ad-hoc, managed...)
+ * - Support for unicast and multicast power saving
+ * - Change encoding to support larger tokens (>64 bits)
+ * - Updated iw_params (disable, flags) and use it for NWID
+ * - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ * - Add PM capability to range structure
+ * - Add PM modifier : MAX/MIN/RELATIVE
+ * - Add encoding option : IW_ENCODE_NOKEY
+ * - Add TxPower ioctls (work like TxRate)
+ *
+ * V10 to V11
+ * ----------
+ * - Add WE version in range (help backward/forward compatibility)
+ * - Add retry ioctls (work like PM)
+ *
+ * V11 to V12
+ * ----------
+ * - Add SIOCSIWSTATS to get /proc/net/wireless programatically
+ * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
+ * - Add new statistics (frag, retry, beacon)
+ * - Add average quality (for user space calibration)
+ *
+ * V12 to V13
+ * ----------
+ * - Document creation of new driver API.
+ * - Extract union iwreq_data from struct iwreq (for new driver API).
+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
+ *
+ * V13 to V14
+ * ----------
+ * - Wireless Events support : define struct iw_event
+ * - Define additional specific event numbers
+ * - Add "addr" and "param" fields in union iwreq_data
+ * - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ * - Make struct iw_freq signed (both m & e), add explicit padding
+ * - Add IWEVCUSTOM for driver specific event/scanning token
+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ * - Reshuffle struct iw_range for increases, add filler
+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+ *
+ * V16 to V17
+ * ----------
+ * - Add flags to frequency -> auto/fixed
+ * - Document (struct iw_quality *)->updated, add new flags (INVALID)
+ * - Wireless Event capability in struct iw_range
+ * - Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen )
+ * ----------
+ * - Add support for WPA/WPA2
+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
+ * SIOCGIWENCODEEXT)
+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
+ * - Add SIOCSIWMLME
+ * - Add SIOCSIWPMKSA
+ * - Add struct iw_range bit field for supported encoding capabilities
+ * - Add optional scan request parameters for SIOCSIWSCAN
+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ * related parameters (extensible up to 4096 parameter values)
+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
+ *
+ * V18 to V19
+ * ----------
+ * - Remove (struct iw_point *)->pointer from events and streams
+ * - Remove header includes to help user space
+ * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64
+ * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
+ * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
+ * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
+ *
+ * V19 to V20
+ * ----------
+ * - RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ * - Remove (struct net_device *)->get_wireless_stats()
+ * - Change length in ESSID and NICK to strlen() instead of strlen()+1
+ * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ * - Power/Retry relative values no longer * 100000
+ * - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
+ *
+ * V21 to V22
+ * ----------
+ * - Prevent leaking of kernel space in stream on 64 bits.
+ */
+
+/**************************** CONSTANTS ****************************/
+
+/* -------------------------- IOCTL LIST -------------------------- */
+
+/* Wireless Identification */
+const SIOCSIWCOMMIT = 0x8B00 /* Commit pending changes to driver */
+const SIOCGIWNAME = 0x8B01 /* get name == wireless protocol */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+const SIOCSIWNWID = 0x8B02 /* set network id (pre-802.11) */
+const SIOCGIWNWID = 0x8B03 /* get network id (the cell) */
+const SIOCSIWFREQ = 0x8B04 /* set channel/frequency (Hz) */
+const SIOCGIWFREQ = 0x8B05 /* get channel/frequency (Hz) */
+const SIOCSIWMODE = 0x8B06 /* set operation mode */
+const SIOCGIWMODE = 0x8B07 /* get operation mode */
+const SIOCSIWSENS = 0x8B08 /* set sensitivity (dBm) */
+const SIOCGIWSENS = 0x8B09 /* get sensitivity (dBm) */
+
+/* Informative stuff */
+const SIOCSIWRANGE = 0x8B0A /* Unused */
+const SIOCGIWRANGE = 0x8B0B /* Get range of parameters */
+const SIOCSIWPRIV = 0x8B0C /* Unused */
+const SIOCGIWPRIV = 0x8B0D /* get private ioctl interface info */
+const SIOCSIWSTATS = 0x8B0E /* Unused */
+const SIOCGIWSTATS = 0x8B0F /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
+
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
+const SIOCSIWSPY = 0x8B10 /* set spy addresses */
+const SIOCGIWSPY = 0x8B11 /* get spy info (quality of link) */
+const SIOCSIWTHRSPY = 0x8B12 /* set spy threshold (spy event) */
+const SIOCGIWTHRSPY = 0x8B13 /* get spy threshold */
+
+/* Access Point manipulation */
+const SIOCSIWAP = 0x8B14 /* set access point MAC addresses */
+const SIOCGIWAP = 0x8B15 /* get access point MAC addresses */
+const SIOCGIWAPLIST = 0x8B17 /* Deprecated in favor of scanning */
+const SIOCSIWSCAN = 0x8B18 /* trigger scanning (list cells) */
+const SIOCGIWSCAN = 0x8B19 /* get scanning results */
+
+/* 802.11 specific support */
+const SIOCSIWESSID = 0x8B1A /* set ESSID (network name) */
+const SIOCGIWESSID = 0x8B1B /* get ESSID */
+const SIOCSIWNICKN = 0x8B1C /* set node name/nickname */
+const SIOCGIWNICKN = 0x8B1D /* get node name/nickname */
+/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
+ * within the 'iwreq' structure, so we need to use the 'data' member to
+ * point to a string in user space, like it is done for RANGE... */
+
+/* Other parameters useful in 802.11 and some other devices */
+const SIOCSIWRATE = 0x8B20 /* set default bit rate (bps) */
+const SIOCGIWRATE = 0x8B21 /* get default bit rate (bps) */
+const SIOCSIWRTS = 0x8B22 /* set RTS/CTS threshold (bytes) */
+const SIOCGIWRTS = 0x8B23 /* get RTS/CTS threshold (bytes) */
+const SIOCSIWFRAG = 0x8B24 /* set fragmentation thr (bytes) */
+const SIOCGIWFRAG = 0x8B25 /* get fragmentation thr (bytes) */
+const SIOCSIWTXPOW = 0x8B26 /* set transmit power (dBm) */
+const SIOCGIWTXPOW = 0x8B27 /* get transmit power (dBm) */
+const SIOCSIWRETRY = 0x8B28 /* set retry limits and lifetime */
+const SIOCGIWRETRY = 0x8B29 /* get retry limits and lifetime */
+
+/* Encoding stuff (scrambling, hardware security, WEP...) */
+const SIOCSIWENCODE = 0x8B2A /* set encoding token & mode */
+const SIOCGIWENCODE = 0x8B2B /* get encoding token & mode */
+/* Power saving stuff (power management, unicast and multicast) */
+const SIOCSIWPOWER = 0x8B2C /* set Power Management settings */
+const SIOCGIWPOWER = 0x8B2D /* get Power Management settings */
+
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+const SIOCSIWGENIE = 0x8B30 /* set generic IE */
+const SIOCGIWGENIE = 0x8B31 /* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+const SIOCSIWMLME = 0x8B16 /* request MLME operation; uses
+ * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+const SIOCSIWAUTH = 0x8B32 /* set authentication mode params */
+const SIOCGIWAUTH = 0x8B33 /* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+const SIOCSIWENCODEEXT = 0x8B34 /* set encoding token & mode */
+const SIOCGIWENCODEEXT = 0x8B35 /* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+const SIOCSIWPMKSA = 0x8B36 /* PMKSA cache operation */
+
+/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
+
+/* These 32 ioctl are wireless device private, for 16 commands.
+ * Each driver is free to use them for whatever purpose it chooses,
+ * however the driver *must* export the description of those ioctls
+ * with SIOCGIWPRIV and *must* use arguments as defined below.
+ * If you don't follow those rules, DaveM is going to hate you (reason :
+ * it make mixed 32/64bit operation impossible).
+ */
+const SIOCIWFIRSTPRIV = 0x8BE0
+const SIOCIWLASTPRIV = 0x8BFF
+
+/* Previously, we were using SIOCDEVPRIVATE, but we now have our
+ * separate range because of collisions with other tools such as
+ * 'mii-tool'.
+ * We now have 32 commands, so a bit more space ;-).
+ * Also, all 'even' commands are only usable by root and don't return the
+ * content of ifr/iwr to user (but you are not obliged to use the set/get
+ * convention, just use every other two command). More details in iwpriv.c.
+ * And I repeat : you are not forced to use them with iwpriv, but you
+ * must be compliant with it.
+ */
+
+/* ------------------------- IOCTL STUFF ------------------------- */
+
+/* The first and the last (range) */
+const SIOCIWFIRST = 0x8B00
+const SIOCIWLAST = SIOCIWLASTPRIV /* 0x8BFF */
+//const IW_IOCTL_IDX(cmd) = ((cmd) - SIOCIWFIRST)
+//const IW_HANDLER(id, = func) [IW_IOCTL_IDX(id)] = func
+
+// What is this stuff?
+// Odd is right.
+/* Odd : get (world access), even : set (root access) */
+func IW_IS_SET(cmd uint32) bool {
+ return !(((cmd) & 0x1) != 0)
+}
+func IW_IS_GET(cmd uint32) bool {
+ return ((cmd) & 0x1) != 0
+}
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/* Those are *NOT* ioctls, do not issue request on them !!! */
+/* Most events use the same identifier as ioctl requests */
+
+const IWEVTXDROP = 0x8C00 /* Packet dropped to excessive retry */
+const IWEVQUAL = 0x8C01 /* Quality part of statistics (scan) */
+const IWEVCUSTOM = 0x8C02 /* Driver specific ascii string */
+const IWEVREGISTERED = 0x8C03 /* Discovered a new node (AP mode) */
+const IWEVEXPIRED = 0x8C04 /* Expired a node (AP mode) */
+const IWEVGENIE = 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
+ * (scan results); This includes id and
+ * length fields. One IWEVGENIE may
+ * contain more than one IE. Scan
+ * results may contain one or more
+ * IWEVGENIE events. */
+const IWEVMICHAELMICFAILURE = 0x8C06 /* Michael MIC failure
+ * (struct iw_michaelmicfailure)
+ */
+const IWEVASSOCREQIE = 0x8C07 /* IEs used in (Re)Association Request.
+ * The data includes id and length
+ * fields and may contain more than one
+ * IE. This event is required in
+ * Managed mode if the driver
+ * generates its own WPA/RSN IE. This
+ * should be sent just before
+ * IWEVREGISTERED event for the
+ * association. */
+const IWEVASSOCRESPIE = 0x8C08 /* IEs used in (Re)Association
+ * Response. The data includes id and
+ * length fields and may contain more
+ * than one IE. This may be sent
+ * between IWEVASSOCREQIE and
+ * IWEVREGISTERED events for the
+ * association. */
+const IWEVPMKIDCAND = 0x8C09 /* PMKID candidate for RSN
+ * pre-authentication
+ * (struct iw_pmkid_cand) */
+
+const IWEVFIRST = 0x8C00
+
+func IW_EVENT_IDX(cmd uint32) uint32 {
+ return cmd - IWEVFIRST
+}
+
+/* ------------------------- PRIVATE INFO ------------------------- */
+/*
+ * The following is used with SIOCGIWPRIV. It allow a driver to define
+ * the interface (name, type of data) for its private ioctl.
+ * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
+ */
+
+const IW_PRIV_TYPE_MASK = 0x7000 /* Type of arguments */
+const IW_PRIV_TYPE_NONE = 0x0000
+const IW_PRIV_TYPE_BYTE = 0x1000 /* Char as number */
+const IW_PRIV_TYPE_CHAR = 0x2000 /* Char as character */
+const IW_PRIV_TYPE_INT = 0x4000 /* 32 bits int */
+const IW_PRIV_TYPE_FLOAT = 0x5000 /* struct iw_freq */
+const IW_PRIV_TYPE_ADDR = 0x6000 /* struct sockaddr */
+
+const IW_PRIV_SIZE_FIXED = 0x0800 /* Variable or fixed number of args */
+
+const IW_PRIV_SIZE_MASK = 0x07FF /* Max number of those args */
+
+/*
+ * Note : if the number of args is fixed and the size < 16 octets,
+ * instead of passing a pointer we will put args in the iwreq struct...
+ */
+
+/* ----------------------- OTHER CONSTANTS ----------------------- */
+
+/* Maximum frequencies in the range struct */
+const IW_MAX_FREQUENCIES = 32
+
+/* Note : if you have something like 80 frequencies,
+ * don't increase this constant and don't fill the frequency list.
+ * The user will be able to set by channel anyway... */
+
+/* Maximum bit rates in the range struct */
+const IW_MAX_BITRATES = 32
+
+/* Maximum tx powers in the range struct */
+const IW_MAX_TXPOWER = 8
+
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
+
+/* Maximum of address that you may set with SPY */
+const IW_MAX_SPY = 8
+
+/* Maximum of address that you may get in the
+ list of access points in range */
+const IW_MAX_AP = 64
+
+/* Maximum size of the ESSID and NICKN strings */
+const IW_ESSID_MAX_SIZE = 32
+
+/* Modes of operation */
+const IW_MODE_AUTO = 0 /* Let the driver decides */
+const IW_MODE_ADHOC = 1 /* Single cell network */
+const IW_MODE_INFRA = 2 /* Multi cell network, roaming, ... */
+const IW_MODE_MASTER = 3 /* Synchronisation master or Access Point */
+const IW_MODE_REPEAT = 4 /* Wireless Repeater (forwarder) */
+const IW_MODE_SECOND = 5 /* Secondary master/repeater (backup) */
+const IW_MODE_MONITOR = 6 /* Passive monitor (listen only) */
+const IW_MODE_MESH = 7 /* Mesh (IEEE 802.11s) network */
+
+/* Statistics flags (bitmask in updated) */
+const IW_QUAL_QUAL_UPDATED = 0x01 /* Value was updated since last read */
+const IW_QUAL_LEVEL_UPDATED = 0x02
+const IW_QUAL_NOISE_UPDATED = 0x04
+const IW_QUAL_ALL_UPDATED = 0x07
+const IW_QUAL_DBM = 0x08 /* Level + Noise are dBm */
+const IW_QUAL_QUAL_INVALID = 0x10 /* Driver doesn't provide value */
+const IW_QUAL_LEVEL_INVALID = 0x20
+const IW_QUAL_NOISE_INVALID = 0x40
+const IW_QUAL_RCPI = 0x80 /* Level + Noise are 802.11k RCPI */
+const IW_QUAL_ALL_INVALID = 0x70
+
+/* Frequency flags */
+const IW_FREQ_AUTO = 0x00 /* Let the driver decides */
+const IW_FREQ_FIXED = 0x01 /* Force a specific value */
+
+/* Maximum number of size of encoding token available
+ * they are listed in the range structure */
+const IW_MAX_ENCODING_SIZES = 8
+
+/* Maximum size of the encoding token in bytes */
+const IW_ENCODING_TOKEN_MAX = 64 /* 512 bits (for now) */
+
+/* Flags for encoding (along with the token) */
+const IW_ENCODE_INDEX = 0x00FF /* Token index (if needed) */
+const IW_ENCODE_FLAGS = 0xFF00 /* Flags defined below */
+const IW_ENCODE_MODE = 0xF000 /* Modes defined below */
+const IW_ENCODE_DISABLED = 0x8000 /* Encoding disabled */
+const IW_ENCODE_ENABLED = 0x0000 /* Encoding enabled */
+const IW_ENCODE_RESTRICTED = 0x4000 /* Refuse non-encoded packets */
+const IW_ENCODE_OPEN = 0x2000 /* Accept non-encoded packets */
+const IW_ENCODE_NOKEY = 0x0800 /* Key is write only, so not present */
+const IW_ENCODE_TEMP = 0x0400 /* Temporary key */
+
+/* Power management flags available (along with the value, if any) */
+const IW_POWER_ON = 0x0000 /* No details... */
+const IW_POWER_TYPE = 0xF000 /* Type of parameter */
+const IW_POWER_PERIOD = 0x1000 /* Value is a period/duration of */
+const IW_POWER_TIMEOUT = 0x2000 /* Value is a timeout (to go asleep) */
+const IW_POWER_MODE = 0x0F00 /* Power Management mode */
+const IW_POWER_UNICAST_R = 0x0100 /* Receive only unicast messages */
+const IW_POWER_MULTICAST_R = 0x0200 /* Receive only multicast messages */
+const IW_POWER_ALL_R = 0x0300 /* Receive all messages though PM */
+const IW_POWER_FORCE_S = 0x0400 /* Force PM procedure for sending unicast */
+const IW_POWER_REPEATER = 0x0800 /* Repeat broadcast messages in PM period */
+const IW_POWER_MODIFIER = 0x000F /* Modify a parameter */
+const IW_POWER_MIN = 0x0001 /* Value is a minimum */
+const IW_POWER_MAX = 0x0002 /* Value is a maximum */
+const IW_POWER_RELATIVE = 0x0004 /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+const IW_TXPOW_TYPE = 0x00FF /* Type of value */
+const IW_TXPOW_DBM = 0x0000 /* Value is in dBm */
+const IW_TXPOW_MWATT = 0x0001 /* Value is in mW */
+const IW_TXPOW_RELATIVE = 0x0002 /* Value is in arbitrary units */
+const IW_TXPOW_RANGE = 0x1000 /* Range of value between min/max */
+
+/* Retry limits and lifetime flags available */
+const IW_RETRY_ON = 0x0000 /* No details... */
+const IW_RETRY_TYPE = 0xF000 /* Type of parameter */
+const IW_RETRY_LIMIT = 0x1000 /* Maximum number of retries*/
+const IW_RETRY_LIFETIME = 0x2000 /* Maximum duration of retries in us */
+const IW_RETRY_MODIFIER = 0x00FF /* Modify a parameter */
+const IW_RETRY_MIN = 0x0001 /* Value is a minimum */
+const IW_RETRY_MAX = 0x0002 /* Value is a maximum */
+const IW_RETRY_RELATIVE = 0x0004 /* Value is not in seconds/ms/us */
+const IW_RETRY_SHORT = 0x0010 /* Value is for short packets */
+const IW_RETRY_LONG = 0x0020 /* Value is for long packets */
+
+/* Scanning request flags */
+const IW_SCAN_DEFAULT = 0x0000 /* Default scan of the driver */
+const IW_SCAN_ALL_ESSID = 0x0001 /* Scan all ESSIDs */
+const IW_SCAN_THIS_ESSID = 0x0002 /* Scan only this ESSID */
+const IW_SCAN_ALL_FREQ = 0x0004 /* Scan all Frequencies */
+const IW_SCAN_THIS_FREQ = 0x0008 /* Scan only this Frequency */
+const IW_SCAN_ALL_MODE = 0x0010 /* Scan all Modes */
+const IW_SCAN_THIS_MODE = 0x0020 /* Scan only this Mode */
+const IW_SCAN_ALL_RATE = 0x0040 /* Scan all Bit-Rates */
+const IW_SCAN_THIS_RATE = 0x0080 /* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+const IW_SCAN_TYPE_ACTIVE = 0
+const IW_SCAN_TYPE_PASSIVE = 1
+
+/* Maximum size of returned data */
+const IW_SCAN_MAX_DATA = 4096 /* In bytes */
+
+/* Scan capability flags - in (struct iw_range *)->scan_capa */
+const IW_SCAN_CAPA_NONE = 0x00
+const IW_SCAN_CAPA_ESSID = 0x01
+const IW_SCAN_CAPA_BSSID = 0x02
+const IW_SCAN_CAPA_CHANNEL = 0x04
+const IW_SCAN_CAPA_MODE = 0x08
+const IW_SCAN_CAPA_RATE = 0x10
+const IW_SCAN_CAPA_TYPE = 0x20
+const IW_SCAN_CAPA_TIME = 0x40
+
+/* Max number of char in custom event - use multiple of them if needed */
+const IW_CUSTOM_MAX = 256 /* In bytes */
+
+/* Generic information element */
+const IW_GENERIC_IE_MAX = 1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+const IW_MLME_DEAUTH = 0
+const IW_MLME_DISASSOC = 1
+const IW_MLME_AUTH = 2
+const IW_MLME_ASSOC = 3
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+const IW_AUTH_INDEX = 0x0FFF
+const IW_AUTH_FLAGS = 0xF000
+
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+const IW_AUTH_WPA_VERSION = 0
+const IW_AUTH_CIPHER_PAIRWISE = 1
+const IW_AUTH_CIPHER_GROUP = 2
+const IW_AUTH_KEY_MGMT = 3
+const IW_AUTH_TKIP_COUNTERMEASURES = 4
+const IW_AUTH_DROP_UNENCRYPTED = 5
+const IW_AUTH_80211_AUTH_ALG = 6
+const IW_AUTH_WPA_ENABLED = 7
+const IW_AUTH_RX_UNENCRYPTED_EAPOL = 8
+const IW_AUTH_ROAMING_CONTROL = 9
+const IW_AUTH_PRIVACY_INVOKED = 10
+const IW_AUTH_CIPHER_GROUP_MGMT = 11
+const IW_AUTH_MFP = 12
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+const IW_AUTH_WPA_VERSION_DISABLED = 0x00000001
+const IW_AUTH_WPA_VERSION_WPA = 0x00000002
+const IW_AUTH_WPA_VERSION_WPA2 = 0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT
+ * values (bit field) */
+const IW_AUTH_CIPHER_NONE = 0x00000001
+const IW_AUTH_CIPHER_WEP40 = 0x00000002
+const IW_AUTH_CIPHER_TKIP = 0x00000004
+const IW_AUTH_CIPHER_CCMP = 0x00000008
+const IW_AUTH_CIPHER_WEP104 = 0x00000010
+const IW_AUTH_CIPHER_AES_CMAC = 0x00000020
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+const IW_AUTH_KEY_MGMT_802_1X = 1
+const IW_AUTH_KEY_MGMT_PSK = 2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+const IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
+const IW_AUTH_ALG_SHARED_KEY = 0x00000002
+const IW_AUTH_ALG_LEAP = 0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+const IW_AUTH_ROAMING_ENABLE = 0 /* driver/firmware based roaming */
+const IW_AUTH_ROAMING_DISABLE = 1 /* user space program used for roaming
+ * control */
+
+/* IW_AUTH_MFP (management frame protection) values */
+const IW_AUTH_MFP_DISABLED = 0 /* MFP disabled */
+const IW_AUTH_MFP_OPTIONAL = 1 /* MFP optional */
+const IW_AUTH_MFP_REQUIRED = 2 /* MFP required */
+
+/* SIOCSIWENCODEEXT definitions */
+const IW_ENCODE_SEQ_MAX_SIZE = 8
+
+/* struct iw_encode_ext ->alg */
+const IW_ENCODE_ALG_NONE = 0
+const IW_ENCODE_ALG_WEP = 1
+const IW_ENCODE_ALG_TKIP = 2
+const IW_ENCODE_ALG_CCMP = 3
+const IW_ENCODE_ALG_PMK = 4
+const IW_ENCODE_ALG_AES_CMAC = 5
+
+/* struct iw_encode_ext ->ext_flags */
+const IW_ENCODE_EXT_TX_SEQ_VALID = 0x00000001
+const IW_ENCODE_EXT_RX_SEQ_VALID = 0x00000002
+const IW_ENCODE_EXT_GROUP_KEY = 0x00000004
+const IW_ENCODE_EXT_SET_TX_KEY = 0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+const IW_MICFAILURE_KEY_ID = 0x00000003 /* Key ID 0..3 */
+const IW_MICFAILURE_GROUP = 0x00000004
+const IW_MICFAILURE_PAIRWISE = 0x00000008
+const IW_MICFAILURE_STAKEY = 0x00000010
+const IW_MICFAILURE_COUNT = 0x00000060 /* 1 or 2 (0 = count not supported)
+ */
+
+/* Bit field values for enc_capa in struct iw_range */
+const IW_ENC_CAPA_WPA = 0x00000001
+const IW_ENC_CAPA_WPA2 = 0x00000002
+const IW_ENC_CAPA_CIPHER_TKIP = 0x00000004
+const IW_ENC_CAPA_CIPHER_CCMP = 0x00000008
+const IW_ENC_CAPA_4WAY_HANDSHAKE = 0x00000010
+
+/* Event capability macros - in (struct iw_range *)->event_capa
+ * Because we have more than 32 possible events, we use an array of
+ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
+func IW_EVENT_CAPA_BASE(cmd uint32) uint32 {
+ if cmd >= SIOCIWFIRSTPRIV {
+ return cmd - SIOCIWFIRSTPRIV + 0x60
+ }
+ return cmd - SIOCIWFIRST
+}
+func IW_EVENT_CAPA_INDEX(cmd uint32) uint32 {
+ return IW_EVENT_CAPA_BASE(cmd) >> 5
+}
+func IW_EVENT_CAPA_MASK(cmd uint32) uint32 {
+ return (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
+}
+
+/* Event capability constants - event autogenerated by the kernel
+ * This list is valid for most 802.11 devices, customise as needed... */
+var IW_EVENT_CAPA_K_0 = (IW_EVENT_CAPA_MASK(0x8B04) | IW_EVENT_CAPA_MASK(0x8B06) | IW_EVENT_CAPA_MASK(0x8B1A))
+var IW_EVENT_CAPA_K_1 = (IW_EVENT_CAPA_MASK(0x8B2A))
+
+/* "Easy" macro to set events in iw_range (less efficient) */
+func IW_EVENT_CAPA_SET(event_capa []uint32, cmd uint32) {
+ event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)
+}
+
+func IW_EVENT_CAPA_SET_KERNEL(event_capa []uint32) {
+ event_capa[0] |= IW_EVENT_CAPA_K_0
+ event_capa[1] |= IW_EVENT_CAPA_K_1
+}
+
+/****************************** TYPES ******************************/
+
+/* --------------------------- SUBTYPES --------------------------- */
+/*
+ * Generic format for most parameters that fit in an int
+ */
+type iw_param struct {
+ value int32 /* The value of the parameter itself */
+ fixed uint8 /* Hardware should not use auto select */
+ disabled uint8 /* Disable the feature */
+ flags uint16 /* Various specifc flags (if any) */
+}
+
+/*
+ * For all data larger than 16 octets, we need to use a
+ * pointer to memory allocated in user space.
+ */
+type iw_point struct {
+ pointer unsafe.Pointer /* Pointer to the data (in user space) */
+ length uint16 /* number of fields or size in bytes */
+ flags uint16 /* Optional params */
+}
+
+/*
+ * A frequency
+ * For numbers lower than 10^9, we encode the number in 'm' and
+ * set 'e' to 0
+ * For number greater than 10^9, we divide it by the lowest power
+ * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
+ * The power of 10 is in 'e', the result of the division is in 'm'.
+ */
+type iw_freq struct {
+ m int32 /* Mantissa */
+ e int16 /* Exponent */
+ i uint8 /* List index (when in range struct) */
+ flags uint8 /* Flags (fixed/auto) */
+}
+
+/*
+ * Quality of the link
+ */
+type iw_quality struct {
+ qual uint8 /* link quality (%retries, SNR,
+ %missed beacons or better...) */
+ level uint8 /* signal level (dBm) */
+ noise uint8 /* noise level (dBm) */
+ updated uint8 /* Flags to know if updated */
+}
+
+/*
+ * Packet discarded in the wireless adapter due to
+ * "wireless" specific problems...
+ * Note : the list of counter and statistics in net_device_stats
+ * is already pretty exhaustive, and you should use that first.
+ * This is only additional stats...
+ */
+type iw_discarded struct {
+ nwid uint32 /* Rx : Wrong nwid/essid */
+ code uint32 /* Rx : Unable to code/decode (WEP) */
+ fragment uint32 /* Rx : Can't perform MAC reassembly */
+ retries uint32 /* Tx : Max MAC retries num reached */
+ misc uint32 /* Others cases */
+}
+
+/*
+ * Packet/Time period missed in the wireless adapter due to
+ * "wireless" specific problems...
+ */
+type iw_missed struct {
+ beacon uint32 /* Missed beacons/superframe */
+}
+
+type sockaddr []byte
+
+/*
+ * Quality range (for spy threshold)
+ */
+type iw_thrspy struct {
+ addr sockaddr /* Source address (hw/mac) */
+ qual iw_quality /* Quality of the link */
+ low iw_quality /* Low threshold */
+ high iw_quality /* High threshold */
+}
+
+/*
+ * Optional data for scan request
+ *
+ * Note: these optional parameters are controlling parameters for the
+ * scanning behavior, these do not apply to getting scan results
+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ * provide a merged results with all BSSes even if the previous scan
+ * request limited scanning to a subset, e.g., by specifying an SSID.
+ * Especially, scan results are required to include an entry for the
+ * current BSS if the driver is in Managed mode and associated with an AP.
+ */
+type iw_scan_req struct {
+ scan_type uint8 /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+ essid_len uint8
+ num_channels uint8 /* num entries in channel_list uint8
+ * 0 = scan all allowed channels */
+ flags uint8 /* reserved as padding uint8 use zero, this may
+ * be used in the future for adding flags
+ * to request different scan behavior */
+ bssid sockaddr /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+ * individual address of a specific BSS */
+
+ /*
+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+ * the current ESSID. This allows scan requests for specific ESSID
+ * without having to change the current ESSID and potentially breaking
+ * the current association.
+ */
+ essid [IW_ESSID_MAX_SIZE]uint8
+ /*
+ * Optional parameters for changing the default scanning behavior.
+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
+ * reasonable default values. min_channel_time defines the time that
+ * will be used to wait for the first reply on each channel. If no
+ * replies are received, next channel will be scanned after this. If
+ * replies are received, total time waited on the channel is defined by
+ * max_channel_time.
+ */
+ min_channel_time uint32 /* in TU */
+ max_channel_time uint32 /* in TU */
+
+ channel_list [IW_MAX_FREQUENCIES]iw_freq
+}
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ * Extended data structure for get/set encoding (this is used with
+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ * only the data contents changes (key data -> this structure, including
+ * key data).
+ *
+ * If the new key is the first group key, it will be set as the default
+ * TX key. Otherwise, default TX key index is only changed if
+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ * special "change TX key index" operation which is indicated by setting
+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ * tx_seq/rx_seq are only used when respective
+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ * used only by an Authenticator (AP or an IBSS station) to get the
+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ * debugging/testing.
+ */
+type iw_encode_ext struct {
+ ext_flags uint32 /* IW_ENCODE_EXT_* */
+ tx_seq [IW_ENCODE_SEQ_MAX_SIZE]uint8 /* LSB first */
+ rx_seq [IW_ENCODE_SEQ_MAX_SIZE]uint8 /* LSB first */
+ addr sockaddr /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+ * (group) keys or unicast address for
+ * individual keys */
+ alg uint16 /* IW_ENCODE_ALG_* */
+ key_len uint16
+ key []uint8
+}
+
+/* SIOCSIWMLME data */
+type iw_mlme struct {
+ cmd uint16 /* IW_MLME_* */
+ reason_code uint16
+ addr sockaddr
+}
+
+/* SIOCSIWPMKSA data */
+const IW_PMKSA_ADD = 1
+const IW_PMKSA_REMOVE = 2
+const IW_PMKSA_FLUSH = 3
+
+const IW_PMKID_LEN = 16
+
+type iw_pmksa struct {
+ cmd uint32 /* IW_PMKSA_* */
+ bssid sockaddr
+ pmkid [IW_PMKID_LEN]uint8
+}
+
+/* IWEVMICHAELMICFAILURE data */
+type iw_michaelmicfailure struct {
+ flags uint32
+ src_addr sockaddr
+ tsc [IW_ENCODE_SEQ_MAX_SIZE]uint8 /* LSB first */
+}
+
+/* IWEVPMKIDCAND data */
+const IW_PMKID_CAND_PREAUTH = 0x00000001 /* RNS pre-authentication enabled */
+type iw_pmkid_cand struct {
+ flags uint32 /* IW_PMKID_CAND_* */
+ index uint32 /* the smaller the index, the higher the
+ * priority */
+ bssid sockaddr
+}
+
+/* ------------------------ WIRELESS STATS ------------------------ */
+/*
+ * Wireless statistics (used for /proc/net/wireless)
+ */
+type iw_statistics struct {
+ status uint16 /* Status
+ * - device dependent for now */
+
+ qual iw_quality /* Quality of the link
+ * (instant/mean/max) */
+ discard iw_quality /* Packet discarded counts */
+ miss iw_quality /* Packet missed counts */
+}
+
+/* ------------------------ IOCTL REQUEST ------------------------ */
+/*
+ * This structure defines the payload of an ioctl, and is used
+ * below.
+ *
+ * Note that this structure should fit on the memory footprint
+ * of iwreq (which is the same as ifreq), which mean a max size of
+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
+ * You should check this when increasing the structures defined
+ * above in this file...
+ *
+union iwreq_data {
+ /* Config - generic *
+ char name[IFNAMSIZ];
+ /* Name : used to verify the presence of wireless extensions.
+ * Name of the protocol/provider... *
+
+ iw_point essid; /* Extended network name *
+ iw_param nwid; /* network id (or domain - the cell) *
+ iw_freq freq; /* frequency or channel :
+ * 0-1000 = channel
+ * > 1000 = frequency in Hz *
+
+ iw_param sens; /* signal level threshold *
+ iw_param bitrate; /* default bit rate *
+ iw_param txpower; /* default transmit power *
+ iw_param rts; /* RTS threshold threshold *
+ iw_param frag; /* Fragmentation threshold *
+mode uint32 /* Operation mode *
+ iw_param retry; /* Retry limits & lifetime *
+
+ iw_point encoding; /* Encoding stuff : tokens *
+ iw_param power; /* PM duration/timeout *
+ iw_quality qual; /* Quality part of statistics *
+
+ sockaddr ap_addr; /* Access point address *
+ sockaddr addr; /* Destination address (hw/mac) *
+
+ iw_param param; /* Other small parameters *
+ iw_point data; /* Other large parameters *
+};
+
+/*
+ * The structure to exchange data for ioctl.
+ * This structure is the same as 'struct ifreq', but (re)defined for
+ * convenience...
+ * Do I need to remind you about structure size (32 octets) ?
+*/
+type iwreq struct {
+ //union
+ //{
+ // char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
+ // } ifr_ifrn;
+
+ /* Data part (defined just above) *
+ union iwreq_data u;
+ */
+}
+
+/* -------------------------- IOCTL DATA -------------------------- */
+/*
+ * For those ioctl which want to exchange mode data that what could
+ * fit in the above structure...
+ */
+
+/*
+ * Range of parameters
+ */
+
+type IWRange struct {
+ /* Informative stuff (to choose between different interface) */
+ throughput uint32 /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ min_nwid uint32 /* Minimal NWID we are able to set */
+ max_nwid uint32 /* Maximal NWID we are able to set */
+
+ /* Old Frequency (backward compat - moved lower ) */
+ old_num_channels uint16
+ old_num_frequency uint8
+
+ /* Scan capabilities */
+ scan_capa uint8 /* IW_SCAN_CAPA_* bit field */
+
+ /* Wireless event capability bitmasks */
+ event_capa [6]uint32
+
+ /* signal level threshold range */
+ sensitivity int32
+
+ /* Quality of link & SNR stuff */
+ /* Quality range (link, level, noise)
+ * If the quality is absolute, it will be in the range [0 ; max_qual],
+ * if the quality is dBm, it will be in the range [max_qual ; 0].
+ * Don't forget that we use 8 bit arithmetics... */
+ max_qual iw_quality /* Quality of the link */
+ /* This should contain the average/typical values of the quality
+ * indicator. This should be the threshold between a "good" and
+ * a "bad" link (example : monitor going from green to orange).
+ * Currently, user space apps like quality monitors don't have any
+ * way to calibrate the measurement. With this, they can split
+ * the range between 0 and max_qual in different quality level
+ * (using a geometric subdivision centered on the average).
+ * I expect that people doing the user space apps will feedback
+ * us on which value we need to put in each driver... */
+ avg_qual iw_quality /* Quality of the link */
+
+ /* Rates */
+ num_bitrates uint8 /* Number of entries in the list */
+ bitrate [IW_MAX_BITRATES]int32 /* list, in bps */
+
+ /* RTS threshold */
+ min_rts int32 /* Minimal RTS threshold */
+ max_rts int32 /* Maximal RTS threshold */
+
+ /* Frag threshold */
+ min_frag int32 /* Minimal frag threshold */
+ max_frag int32 /* Maximal frag threshold */
+
+ /* Power Management duration & timeout */
+ min_pmp int32 /* Minimal PM period */
+ max_pmp int32 /* Maximal PM period */
+ min_pmt int32 /* Minimal PM timeout */
+ max_pmt int32 /* Maximal PM timeout */
+ pmp_flags uint16 /* How to decode max/min PM period */
+ pmt_flags uint16 /* How to decode max/min PM timeout */
+ pm_capa uint16 /* What PM options are supported */
+
+ /* Encoder stuff */
+ encoding_size [IW_MAX_ENCODING_SIZES]uint16 /* Different token sizes */
+ num_encoding_sizes uint8 /* Number of entry in the list */
+ max_encoding_tokens uint8 /* Max number of tokens */
+ /* For drivers that need a "login/passwd" form */
+ encoding_login_index uint8 /* token index for login token */
+
+ /* Transmit power */
+ txpower_capa uint16 /* What options are supported */
+ num_txpower uint8 /* Number of entries in the list */
+ txpower [IW_MAX_TXPOWER]int32 /* list, in bps */
+
+ /* Wireless Extension version info */
+ we_version_compiled uint8 /* Must be WIRELESS_EXT */
+ we_version_source uint8 /* Last update of source */
+
+ /* Retry limits and lifetime */
+ retry_capa uint16 /* What retry options are supported */
+ retry_flags uint16 /* How to decode max/min retry limit */
+ r_time_flags uint16 /* How to decode max/min retry life */
+ min_retry int32 /* Minimal number of retries */
+ max_retry int32 /* Maximal number of retries */
+ min_r_time int32 /* Minimal retry lifetime */
+ max_r_time int32 /* Maximal retry lifetime */
+
+ /* Frequency */
+ num_channels uint16 /* Number of channels [0; num - 1] */
+ num_frequency uint8 /* Number of entry in the list */
+ freq [IW_MAX_FREQUENCIES]iw_freq /* list */
+ /* Note : this frequency list doesn't need to fit channel numbers,
+ * because each entry contain its channel index */
+
+ enc_capa uint32 /* IW_ENC_CAPA_* bit field */
+}
+
+/*
+ * Private ioctl interface information
+ */
+const IFNAMSIZ = 16
+
+type iw_priv_args struct {
+ cmd uint32 /* Number of the ioctl to issue */
+ set_args uint16 /* Type and number of args */
+ get_args uint16 /* Type and number of args */
+ name [IFNAMSIZ]byte /* Name of the extension */
+}
+
+/* ----------------------- WIRELESS EVENTS ----------------------- */
+/*
+ * Wireless events are carried through the rtnetlink socket to user
+ * space. They are encapsulated in the IFLA_WIRELESS field of
+ * a RTM_NEWLINK message.
+ */
+
+/*
+ * A Wireless Event. Contains basically the same data as the ioctl...
+ */
+type iw_event struct {
+ len uint16 /* Real length of this stuff */
+ cmd uint16 /* Wireless IOCTL */
+ //union iwreq_data u; /* IOCTL fixed payload */
+}
+
+// stupid sizeof tricks for the inevitable binary interface.
+/* Size of the Event prefix (including padding and alignement junk) *
+const IW_EV_LCP_LEN = (sizeof(struct iw_event) - sizeof(union iwreq_data))
+/* Size of the various events *
+const IW_EV_CHAR_LEN = (IW_EV_LCP_LEN + IFNAMSIZ)
+const IW_EV_UINT_LEN = (IW_EV_LCP_LEN + sizeof(uint32))
+const IW_EV_FREQ_LEN = (IW_EV_LCP_LEN + sizeof(struct iw_freq))
+const IW_EV_PARAM_LEN = (IW_EV_LCP_LEN + sizeof(struct iw_param))
+const IW_EV_ADDR_LEN = (IW_EV_LCP_LEN + sizeof(struct sockaddr))
+const IW_EV_QUAL_LEN = (IW_EV_LCP_LEN + sizeof(struct iw_quality))
+
+/* iw_point events are special. First, the payload (extra data) come at
+ * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
+ * we omit the pointer, so start at an offset. *
+const IW_EV_POINT_OFF = (((char *) &(((struct iw_point *) NULL)->length)) - (char *) NULL)
+const IW_EV_POINT_LEN = (IW_EV_LCP_LEN + sizeof(struct iw_point) - IW_EV_POINT_OFF)
+
+
+/* Size of the Event prefix when packed in stream */
+const IW_EV_LCP_PK_LEN = (4)
+
+/* Size of the various events when packed in stream *
+const IW_EV_CHAR_PK_LEN = (IW_EV_LCP_PK_LEN + IFNAMSIZ)
+const IW_EV_UINT_PK_LEN = (IW_EV_LCP_PK_LEN + sizeof(uint32))
+const IW_EV_FREQ_PK_LEN = (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
+const IW_EV_PARAM_PK_LEN = (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
+const IW_EV_ADDR_PK_LEN = (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
+const IW_EV_QUAL_PK_LEN = (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
+*/
+const IW_EV_POINT_PK_LEN = (IW_EV_LCP_PK_LEN + 4)
diff --git a/nichrome/pkg/wpa/passphrase/passphrase.go b/nichrome/pkg/wpa/passphrase/passphrase.go
new file mode 100644
index 000000000..7617196e5
--- /dev/null
+++ b/nichrome/pkg/wpa/passphrase/passphrase.go
@@ -0,0 +1,48 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package passphrase
+
+import (
+ "crypto/sha1"
+ "encoding/hex"
+ "fmt"
+
+ "golang.org/x/crypto/pbkdf2"
+)
+
+const (
+ MinPassLen = 8
+ MaxPassLen = 63
+ ResultFormat = `network={
+ ssid="%s"
+ #psk="%s"
+ psk=%s
+}
+`
+)
+
+func errorCheck(essid string, pass string) error {
+ if len(pass) < MinPassLen || len(pass) > MaxPassLen {
+ return fmt.Errorf("Passphrase must be 8..63 characters")
+ }
+ if len(essid) == 0 {
+ return fmt.Errorf("essid cannot be empty")
+ }
+ return nil
+}
+
+func Run(essid string, pass string) ([]byte, error) {
+ if err := errorCheck(essid, pass); err != nil {
+ return nil, err
+ }
+
+ // There is a possible security bug here because the salt is the essid which is
+ // static and shared across access points. Thus this salt is not sufficiently random.
+ // This issue has been reported to the responsible parties. Since this matches the
+ // current implementation of wpa_passphrase.c, this will maintain until further notice.
+ pskBinary := pbkdf2.Key([]byte(pass), []byte(essid), 4096, 32, sha1.New)
+ pskHexString := hex.EncodeToString(pskBinary)
+ return []byte(fmt.Sprintf(ResultFormat, essid, pass, pskHexString)), nil
+}
diff --git a/nichrome/pkg/wpa/passphrase/passphrase_test.go b/nichrome/pkg/wpa/passphrase/passphrase_test.go
new file mode 100644
index 000000000..dcee75400
--- /dev/null
+++ b/nichrome/pkg/wpa/passphrase/passphrase_test.go
@@ -0,0 +1,71 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package passphrase
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+)
+
+type RunTestCase struct {
+ name string
+ essid string
+ pass string
+ out string
+ err error
+}
+
+var (
+ essidStub = "stub"
+ shortPass = "aaaaaaa" // 7 chars
+ longPass = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 64 chars
+ validPass = "aaaaaaaaaaaaaaaa" // 16 chars
+ correctOutput = `network={
+ ssid="stub"
+ #psk="aaaaaaaaaaaaaaaa"
+ psk=e270ba95a72c6d922e902f65dfa23315f7ba43b69debc75167254acd778f2fe9
+}
+`
+ runTestCases = []RunTestCase{
+ {
+ name: "No essid",
+ essid: "",
+ pass: validPass,
+ out: "",
+ err: fmt.Errorf("essid cannot be empty"),
+ },
+ {
+ name: "pass length is less than 8 chars",
+ essid: essidStub,
+ pass: shortPass,
+ out: "",
+ err: fmt.Errorf("Passphrase must be 8..63 characters"),
+ },
+ {
+ name: "pass length is more than 63 chars",
+ essid: essidStub,
+ pass: longPass,
+ out: "",
+ err: fmt.Errorf("Passphrase must be 8..63 characters"),
+ },
+ {
+ name: "Correct Input",
+ essid: essidStub,
+ pass: validPass,
+ out: correctOutput,
+ err: nil,
+ },
+ }
+)
+
+func TestRun(t *testing.T) {
+ for _, test := range runTestCases {
+ out, err := Run(test.essid, test.pass)
+ if !reflect.DeepEqual(err, test.err) || string(out) != test.out {
+ t.Errorf("TEST %s\ngot:[%v, %v]\nwant:[%v, %v]", test.name, err, string(out), test.err, string(test.out))
+ }
+ }
+}
diff --git a/nichrome/rootfs/etc/asound.conf b/nichrome/rootfs/etc/asound.conf
new file mode 100644
index 000000000..4112055d4
--- /dev/null
+++ b/nichrome/rootfs/etc/asound.conf
@@ -0,0 +1,6 @@
+pcm.!default {
+ type hw
+ card 0
+ device 3
+}
+
diff --git a/nichrome/rootfs/etc/group b/nichrome/rootfs/etc/group
new file mode 100644
index 000000000..fea6c3e06
--- /dev/null
+++ b/nichrome/rootfs/etc/group
@@ -0,0 +1 @@
+staff::1:root,user
diff --git a/nichrome/rootfs/lib/ld-2.17.so b/nichrome/rootfs/lib/ld-2.17.so
new file mode 100755
index 000000000..1398643ac
Binary files /dev/null and b/nichrome/rootfs/lib/ld-2.17.so differ
diff --git a/nichrome/rootfs/lib/ld-2.24.so b/nichrome/rootfs/lib/ld-2.24.so
new file mode 100755
index 000000000..0bd81a2ef
Binary files /dev/null and b/nichrome/rootfs/lib/ld-2.24.so differ
diff --git a/nichrome/rootfs/lib/ld-linux-x86-64.so.2 b/nichrome/rootfs/lib/ld-linux-x86-64.so.2
new file mode 120000
index 000000000..6b1a56f03
--- /dev/null
+++ b/nichrome/rootfs/lib/ld-linux-x86-64.so.2
@@ -0,0 +1 @@
+ld-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libanl-2.24.so b/nichrome/rootfs/lib/libanl-2.24.so
new file mode 100755
index 000000000..91968f7f9
Binary files /dev/null and b/nichrome/rootfs/lib/libanl-2.24.so differ
diff --git a/nichrome/rootfs/lib/libanl.so.1 b/nichrome/rootfs/lib/libanl.so.1
new file mode 120000
index 000000000..8dc3b3602
--- /dev/null
+++ b/nichrome/rootfs/lib/libanl.so.1
@@ -0,0 +1 @@
+libanl-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libblkid.so.1 b/nichrome/rootfs/lib/libblkid.so.1
new file mode 120000
index 000000000..e4f69c72c
--- /dev/null
+++ b/nichrome/rootfs/lib/libblkid.so.1
@@ -0,0 +1 @@
+libblkid.so.1.1.0
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libblkid.so.1.1.0 b/nichrome/rootfs/lib/libblkid.so.1.1.0
new file mode 100755
index 000000000..cfd20b5b5
Binary files /dev/null and b/nichrome/rootfs/lib/libblkid.so.1.1.0 differ
diff --git a/nichrome/rootfs/lib/libc-2.17.so b/nichrome/rootfs/lib/libc-2.17.so
new file mode 100755
index 000000000..2bb449627
Binary files /dev/null and b/nichrome/rootfs/lib/libc-2.17.so differ
diff --git a/nichrome/rootfs/lib/libc-2.24.so b/nichrome/rootfs/lib/libc-2.24.so
new file mode 100755
index 000000000..39f5b3441
Binary files /dev/null and b/nichrome/rootfs/lib/libc-2.24.so differ
diff --git a/nichrome/rootfs/lib/libc.so.6 b/nichrome/rootfs/lib/libc.so.6
new file mode 120000
index 000000000..77d3c6de5
--- /dev/null
+++ b/nichrome/rootfs/lib/libc.so.6
@@ -0,0 +1 @@
+libc-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libcom_err.so.2 b/nichrome/rootfs/lib/libcom_err.so.2
new file mode 120000
index 000000000..e989efb0b
--- /dev/null
+++ b/nichrome/rootfs/lib/libcom_err.so.2
@@ -0,0 +1 @@
+libcom_err.so.2.1
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libcom_err.so.2.1 b/nichrome/rootfs/lib/libcom_err.so.2.1
new file mode 100755
index 000000000..e3c8cf34c
Binary files /dev/null and b/nichrome/rootfs/lib/libcom_err.so.2.1 differ
diff --git a/nichrome/rootfs/lib/libcrypt-2.24.so b/nichrome/rootfs/lib/libcrypt-2.24.so
new file mode 100755
index 000000000..935d473b2
Binary files /dev/null and b/nichrome/rootfs/lib/libcrypt-2.24.so differ
diff --git a/nichrome/rootfs/lib/libcrypt.so.1 b/nichrome/rootfs/lib/libcrypt.so.1
new file mode 120000
index 000000000..1adb36c5d
--- /dev/null
+++ b/nichrome/rootfs/lib/libcrypt.so.1
@@ -0,0 +1 @@
+libcrypt-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libdl-2.17.so b/nichrome/rootfs/lib/libdl-2.17.so
new file mode 100755
index 000000000..694ecf8bd
Binary files /dev/null and b/nichrome/rootfs/lib/libdl-2.17.so differ
diff --git a/nichrome/rootfs/lib/libdl-2.24.so b/nichrome/rootfs/lib/libdl-2.24.so
new file mode 100755
index 000000000..8afc4ea2b
Binary files /dev/null and b/nichrome/rootfs/lib/libdl-2.24.so differ
diff --git a/nichrome/rootfs/lib/libdl.so.2 b/nichrome/rootfs/lib/libdl.so.2
new file mode 120000
index 000000000..5b0e60612
--- /dev/null
+++ b/nichrome/rootfs/lib/libdl.so.2
@@ -0,0 +1 @@
+libdl-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libe2p.so.2 b/nichrome/rootfs/lib/libe2p.so.2
new file mode 120000
index 000000000..177bc5cb1
--- /dev/null
+++ b/nichrome/rootfs/lib/libe2p.so.2
@@ -0,0 +1 @@
+libe2p.so.2.3
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libe2p.so.2.3 b/nichrome/rootfs/lib/libe2p.so.2.3
new file mode 100755
index 000000000..a4dbcbb42
Binary files /dev/null and b/nichrome/rootfs/lib/libe2p.so.2.3 differ
diff --git a/nichrome/rootfs/lib/libext2fs.so.2 b/nichrome/rootfs/lib/libext2fs.so.2
new file mode 120000
index 000000000..60d5fb9ff
--- /dev/null
+++ b/nichrome/rootfs/lib/libext2fs.so.2
@@ -0,0 +1 @@
+libext2fs.so.2.4
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libext2fs.so.2.4 b/nichrome/rootfs/lib/libext2fs.so.2.4
new file mode 100755
index 000000000..76378ddad
Binary files /dev/null and b/nichrome/rootfs/lib/libext2fs.so.2.4 differ
diff --git a/nichrome/rootfs/lib/libm-2.24.so b/nichrome/rootfs/lib/libm-2.24.so
new file mode 100755
index 000000000..48412cbba
Binary files /dev/null and b/nichrome/rootfs/lib/libm-2.24.so differ
diff --git a/nichrome/rootfs/lib/libm.so.6 b/nichrome/rootfs/lib/libm.so.6
new file mode 120000
index 000000000..c3a11f38d
--- /dev/null
+++ b/nichrome/rootfs/lib/libm.so.6
@@ -0,0 +1 @@
+libm-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libnsl-2.24.so b/nichrome/rootfs/lib/libnsl-2.24.so
new file mode 100755
index 000000000..98147dfdb
Binary files /dev/null and b/nichrome/rootfs/lib/libnsl-2.24.so differ
diff --git a/nichrome/rootfs/lib/libnsl.so.1 b/nichrome/rootfs/lib/libnsl.so.1
new file mode 120000
index 000000000..2287f72ee
--- /dev/null
+++ b/nichrome/rootfs/lib/libnsl.so.1
@@ -0,0 +1 @@
+libnsl-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libnss_compat-2.17.so b/nichrome/rootfs/lib/libnss_compat-2.17.so
new file mode 100755
index 000000000..4073f72c3
Binary files /dev/null and b/nichrome/rootfs/lib/libnss_compat-2.17.so differ
diff --git a/nichrome/rootfs/lib/libnss_compat-2.24.so b/nichrome/rootfs/lib/libnss_compat-2.24.so
new file mode 100755
index 000000000..14480162e
Binary files /dev/null and b/nichrome/rootfs/lib/libnss_compat-2.24.so differ
diff --git a/nichrome/rootfs/lib/libnss_compat.so.2 b/nichrome/rootfs/lib/libnss_compat.so.2
new file mode 120000
index 000000000..fd755dc39
--- /dev/null
+++ b/nichrome/rootfs/lib/libnss_compat.so.2
@@ -0,0 +1 @@
+libnss_compat-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libnss_dns-2.17.so b/nichrome/rootfs/lib/libnss_dns-2.17.so
new file mode 100755
index 000000000..c3a78ccd9
Binary files /dev/null and b/nichrome/rootfs/lib/libnss_dns-2.17.so differ
diff --git a/nichrome/rootfs/lib/libnss_dns-2.24.so b/nichrome/rootfs/lib/libnss_dns-2.24.so
new file mode 100755
index 000000000..8f89a8276
Binary files /dev/null and b/nichrome/rootfs/lib/libnss_dns-2.24.so differ
diff --git a/nichrome/rootfs/lib/libnss_dns.so.2 b/nichrome/rootfs/lib/libnss_dns.so.2
new file mode 120000
index 000000000..662a31a81
--- /dev/null
+++ b/nichrome/rootfs/lib/libnss_dns.so.2
@@ -0,0 +1 @@
+libnss_dns-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libnss_files-2.17.so b/nichrome/rootfs/lib/libnss_files-2.17.so
new file mode 100755
index 000000000..a1d68771e
Binary files /dev/null and b/nichrome/rootfs/lib/libnss_files-2.17.so differ
diff --git a/nichrome/rootfs/lib/libnss_files-2.24.so b/nichrome/rootfs/lib/libnss_files-2.24.so
new file mode 100755
index 000000000..f15e7e5f9
Binary files /dev/null and b/nichrome/rootfs/lib/libnss_files-2.24.so differ
diff --git a/nichrome/rootfs/lib/libnss_files.so.2 b/nichrome/rootfs/lib/libnss_files.so.2
new file mode 120000
index 000000000..225033d71
--- /dev/null
+++ b/nichrome/rootfs/lib/libnss_files.so.2
@@ -0,0 +1 @@
+libnss_files-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libpthread-2.17.so b/nichrome/rootfs/lib/libpthread-2.17.so
new file mode 100755
index 000000000..c881b362c
Binary files /dev/null and b/nichrome/rootfs/lib/libpthread-2.17.so differ
diff --git a/nichrome/rootfs/lib/libpthread-2.24.so b/nichrome/rootfs/lib/libpthread-2.24.so
new file mode 100755
index 000000000..82caa63ff
Binary files /dev/null and b/nichrome/rootfs/lib/libpthread-2.24.so differ
diff --git a/nichrome/rootfs/lib/libpthread.so.0 b/nichrome/rootfs/lib/libpthread.so.0
new file mode 120000
index 000000000..b195df275
--- /dev/null
+++ b/nichrome/rootfs/lib/libpthread.so.0
@@ -0,0 +1 @@
+libpthread-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libresolv-2.24.so b/nichrome/rootfs/lib/libresolv-2.24.so
new file mode 100755
index 000000000..6371925e1
Binary files /dev/null and b/nichrome/rootfs/lib/libresolv-2.24.so differ
diff --git a/nichrome/rootfs/lib/libresolv.so.2 b/nichrome/rootfs/lib/libresolv.so.2
new file mode 120000
index 000000000..6a4db655d
--- /dev/null
+++ b/nichrome/rootfs/lib/libresolv.so.2
@@ -0,0 +1 @@
+libresolv-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/librt-2.17.so b/nichrome/rootfs/lib/librt-2.17.so
new file mode 100755
index 000000000..981750894
Binary files /dev/null and b/nichrome/rootfs/lib/librt-2.17.so differ
diff --git a/nichrome/rootfs/lib/librt-2.24.so b/nichrome/rootfs/lib/librt-2.24.so
new file mode 100755
index 000000000..b0844e681
Binary files /dev/null and b/nichrome/rootfs/lib/librt-2.24.so differ
diff --git a/nichrome/rootfs/lib/librt.so.1 b/nichrome/rootfs/lib/librt.so.1
new file mode 120000
index 000000000..dffcece8b
--- /dev/null
+++ b/nichrome/rootfs/lib/librt.so.1
@@ -0,0 +1 @@
+librt-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libutil-2.24.so b/nichrome/rootfs/lib/libutil-2.24.so
new file mode 100755
index 000000000..c8b1c1b92
Binary files /dev/null and b/nichrome/rootfs/lib/libutil-2.24.so differ
diff --git a/nichrome/rootfs/lib/libutil.so.1 b/nichrome/rootfs/lib/libutil.so.1
new file mode 120000
index 000000000..e08b86f19
--- /dev/null
+++ b/nichrome/rootfs/lib/libutil.so.1
@@ -0,0 +1 @@
+libutil-2.24.so
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libuuid.so.1 b/nichrome/rootfs/lib/libuuid.so.1
new file mode 120000
index 000000000..774fbfec2
--- /dev/null
+++ b/nichrome/rootfs/lib/libuuid.so.1
@@ -0,0 +1 @@
+libuuid.so.1.3.0
\ No newline at end of file
diff --git a/nichrome/rootfs/lib/libuuid.so.1.3.0 b/nichrome/rootfs/lib/libuuid.so.1.3.0
new file mode 100755
index 000000000..2fb40f1b1
Binary files /dev/null and b/nichrome/rootfs/lib/libuuid.so.1.3.0 differ
diff --git a/nichrome/rootfs/lib/udev/firmware.sh b/nichrome/rootfs/lib/udev/firmware.sh
new file mode 100755
index 000000000..d90164345
--- /dev/null
+++ b/nichrome/rootfs/lib/udev/firmware.sh
@@ -0,0 +1,27 @@
+#!/bin/sh -e
+
+FIRMWARE_DIRS="/lib/firmware /usr/local/lib/firmware"
+
+err() {
+ echo "$@" >&2
+ if [ -x /usr/bin/logger ]; then
+ /usr/bin/logger -t "${0##*/}[$$]" "$@"
+ fi
+}
+
+if [ ! -e /sys$DEVPATH/loading ]; then
+ err "udev firmware loader misses sysfs directory"
+ exit 1
+fi
+
+for DIR in $FIRMWARE_DIRS; do
+ [ -e "$DIR/$FIRMWARE" ] || continue
+ echo 1 > /sys$DEVPATH/loading
+ cat "$DIR/$FIRMWARE" > /sys$DEVPATH/data
+ echo 0 > /sys$DEVPATH/loading
+ exit 0
+done
+
+echo -1 > /sys$DEVPATH/loading
+err "Cannot find firmware file '$FIRMWARE'"
+exit 1
diff --git a/nichrome/rootfs/lib/udev/pcmcia-check-broken-cis b/nichrome/rootfs/lib/udev/pcmcia-check-broken-cis
new file mode 100755
index 000000000..c47063090
Binary files /dev/null and b/nichrome/rootfs/lib/udev/pcmcia-check-broken-cis differ
diff --git a/nichrome/rootfs/lib/udev/pcmcia-socket-startup b/nichrome/rootfs/lib/udev/pcmcia-socket-startup
new file mode 100755
index 000000000..dc4b17835
Binary files /dev/null and b/nichrome/rootfs/lib/udev/pcmcia-socket-startup differ
diff --git a/nichrome/rootfs/lib/x86_64-linux-gnu/libc.so.6 b/nichrome/rootfs/lib/x86_64-linux-gnu/libc.so.6
new file mode 100755
index 000000000..c45a753fd
Binary files /dev/null and b/nichrome/rootfs/lib/x86_64-linux-gnu/libc.so.6 differ
diff --git a/nichrome/rootfs/lib/x86_64-linux-gnu/libm.so.6 b/nichrome/rootfs/lib/x86_64-linux-gnu/libm.so.6
new file mode 100644
index 000000000..9a15b1c82
Binary files /dev/null and b/nichrome/rootfs/lib/x86_64-linux-gnu/libm.so.6 differ
diff --git a/nichrome/rootfs/usr/lib/libanl.so b/nichrome/rootfs/usr/lib/libanl.so
new file mode 120000
index 000000000..1aa73a4ba
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libanl.so
@@ -0,0 +1 @@
+../../lib/libanl.so.1
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libblkid.so b/nichrome/rootfs/usr/lib/libblkid.so
new file mode 120000
index 000000000..b567a5e43
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libblkid.so
@@ -0,0 +1 @@
+../../lib/libblkid.so.1.1.0
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libcom_err.so b/nichrome/rootfs/usr/lib/libcom_err.so
new file mode 120000
index 000000000..7f20c97fb
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libcom_err.so
@@ -0,0 +1 @@
+/lib/libcom_err.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libcrypt.so b/nichrome/rootfs/usr/lib/libcrypt.so
new file mode 120000
index 000000000..f2c4c80f7
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libcrypt.so
@@ -0,0 +1 @@
+../../lib/libcrypt.so.1
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libdl.so b/nichrome/rootfs/usr/lib/libdl.so
new file mode 120000
index 000000000..7afa95af6
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libdl.so
@@ -0,0 +1 @@
+../../lib/libdl.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libe2p.so b/nichrome/rootfs/usr/lib/libe2p.so
new file mode 120000
index 000000000..241a46d0c
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libe2p.so
@@ -0,0 +1 @@
+/lib/libe2p.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libext2fs.so b/nichrome/rootfs/usr/lib/libext2fs.so
new file mode 120000
index 000000000..f015752f6
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libext2fs.so
@@ -0,0 +1 @@
+/lib/libext2fs.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libfuse.so.2 b/nichrome/rootfs/usr/lib/libfuse.so.2
new file mode 100644
index 000000000..005de8829
Binary files /dev/null and b/nichrome/rootfs/usr/lib/libfuse.so.2 differ
diff --git a/nichrome/rootfs/usr/lib/libgcc_s.so b/nichrome/rootfs/usr/lib/libgcc_s.so
new file mode 100644
index 000000000..c8e92242f
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libgcc_s.so
@@ -0,0 +1,4 @@
+/* GNU ld script
+ Use the shared library, but some functions are only in
+ the static library. */
+GROUP ( libgcc_s.so.1 -lgcc )
diff --git a/nichrome/rootfs/usr/lib/libgcc_s.so.1 b/nichrome/rootfs/usr/lib/libgcc_s.so.1
new file mode 100644
index 000000000..14f25745f
Binary files /dev/null and b/nichrome/rootfs/usr/lib/libgcc_s.so.1 differ
diff --git a/nichrome/rootfs/usr/lib/libnsl.so b/nichrome/rootfs/usr/lib/libnsl.so
new file mode 120000
index 000000000..37b57e4e5
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libnsl.so
@@ -0,0 +1 @@
+../../lib/libnsl.so.1
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libnss_compat.so b/nichrome/rootfs/usr/lib/libnss_compat.so
new file mode 120000
index 000000000..88fb049cd
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libnss_compat.so
@@ -0,0 +1 @@
+../../lib/libnss_compat.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libnss_dns.so b/nichrome/rootfs/usr/lib/libnss_dns.so
new file mode 120000
index 000000000..350021a2d
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libnss_dns.so
@@ -0,0 +1 @@
+../../lib/libnss_dns.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libnss_files.so b/nichrome/rootfs/usr/lib/libnss_files.so
new file mode 120000
index 000000000..0d5d219d0
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libnss_files.so
@@ -0,0 +1 @@
+../../lib/libnss_files.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libresolv.so b/nichrome/rootfs/usr/lib/libresolv.so
new file mode 120000
index 000000000..c1959f955
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libresolv.so
@@ -0,0 +1 @@
+../../lib/libresolv.so.2
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/librt.so b/nichrome/rootfs/usr/lib/librt.so
new file mode 120000
index 000000000..75d37e95f
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/librt.so
@@ -0,0 +1 @@
+../../lib/librt.so.1
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libstdc++.so b/nichrome/rootfs/usr/lib/libstdc++.so
new file mode 120000
index 000000000..4217476cb
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libstdc++.so
@@ -0,0 +1 @@
+libstdc++.so.6.0.22
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libstdc++.so.6 b/nichrome/rootfs/usr/lib/libstdc++.so.6
new file mode 120000
index 000000000..4217476cb
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libstdc++.so.6
@@ -0,0 +1 @@
+libstdc++.so.6.0.22
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libstdc++.so.6.0.22 b/nichrome/rootfs/usr/lib/libstdc++.so.6.0.22
new file mode 100755
index 000000000..3f0e8b73e
Binary files /dev/null and b/nichrome/rootfs/usr/lib/libstdc++.so.6.0.22 differ
diff --git a/nichrome/rootfs/usr/lib/libsudo_noexec.so b/nichrome/rootfs/usr/lib/libsudo_noexec.so
new file mode 120000
index 000000000..1f882bc4b
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libsudo_noexec.so
@@ -0,0 +1 @@
+sudo_noexec.so
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libsysfs.so b/nichrome/rootfs/usr/lib/libsysfs.so
new file mode 120000
index 000000000..c1a12d2ea
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libsysfs.so
@@ -0,0 +1 @@
+libsysfs.so.2.0.1
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libsysfs.so.2 b/nichrome/rootfs/usr/lib/libsysfs.so.2
new file mode 120000
index 000000000..c1a12d2ea
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libsysfs.so.2
@@ -0,0 +1 @@
+libsysfs.so.2.0.1
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libsysfs.so.2.0.1 b/nichrome/rootfs/usr/lib/libsysfs.so.2.0.1
new file mode 100755
index 000000000..7f71f22ed
Binary files /dev/null and b/nichrome/rootfs/usr/lib/libsysfs.so.2.0.1 differ
diff --git a/nichrome/rootfs/usr/lib/libutil.so b/nichrome/rootfs/usr/lib/libutil.so
new file mode 120000
index 000000000..2d450b0fa
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libutil.so
@@ -0,0 +1 @@
+../../lib/libutil.so.1
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libuuid.so b/nichrome/rootfs/usr/lib/libuuid.so
new file mode 120000
index 000000000..464fe3d9b
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libuuid.so
@@ -0,0 +1 @@
+../../lib/libuuid.so.1.3.0
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libz.so b/nichrome/rootfs/usr/lib/libz.so
new file mode 120000
index 000000000..2bfad1b2a
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libz.so
@@ -0,0 +1 @@
+libz.so.1.2.8
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libz.so.1 b/nichrome/rootfs/usr/lib/libz.so.1
new file mode 120000
index 000000000..2bfad1b2a
--- /dev/null
+++ b/nichrome/rootfs/usr/lib/libz.so.1
@@ -0,0 +1 @@
+libz.so.1.2.8
\ No newline at end of file
diff --git a/nichrome/rootfs/usr/lib/libz.so.1.2.8 b/nichrome/rootfs/usr/lib/libz.so.1.2.8
new file mode 100755
index 000000000..c5205a34e
Binary files /dev/null and b/nichrome/rootfs/usr/lib/libz.so.1.2.8 differ
diff --git a/nichrome/rootfs/usr/sound.sh b/nichrome/rootfs/usr/sound.sh
new file mode 100755
index 000000000..a529ccbe2
--- /dev/null
+++ b/nichrome/rootfs/usr/sound.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Use this script to back up your /etc and /tcz directories to the stateful
+# partition on your local hard drive. Makes testing sound configuration easier.
+# It assumes you have installed the three main ALSA tcz packages already.
+
+# make sure the first arg is only save or load
+if [ -n $1 ] && ([ $1 = "save" ] || [ $1 = "load" ]); then
+ # if the mount directory does not exist, make it
+ if [ ! -d /mnt ]; then
+ mkdir mnt
+ fi
+ # if the mount directory is empy, mount partition 1 to it
+ if [ -z "$(ls -a /mnt)" ]; then
+ mount -t ext4 /dev/mmcblk*p1 /mnt/
+ fi
+ # if the user requested to save, save
+ if [ $1 = "save" ]; then
+ cp -r /tcz /mnt
+ cp -r /etc /mnt
+ # if the user requested to load, load and install alsa tcz packages.
+ elif [ $1 = "load" ]; then
+ cp -r /mnt/tcz /
+ cp -r /mnt/etc /
+ tcz -i alsa-config alsa-plugins alsa
+ fi
+ # otherwise, print usage
+else
+ echo "Usage: ./usr/sound.sh [save load]"
+fi
diff --git a/nichrome/rootfs/usr/user.cpio b/nichrome/rootfs/usr/user.cpio
new file mode 100644
index 000000000..f8e85732c
Binary files /dev/null and b/nichrome/rootfs/usr/user.cpio differ
diff --git a/nichrome/scripts/.gitignore b/nichrome/scripts/.gitignore
new file mode 100644
index 000000000..567609b12
--- /dev/null
+++ b/nichrome/scripts/.gitignore
@@ -0,0 +1 @@
+build/
diff --git a/nichrome/scripts/base_image_util.sh b/nichrome/scripts/base_image_util.sh
new file mode 100755
index 000000000..e6c87e5a9
--- /dev/null
+++ b/nichrome/scripts/base_image_util.sh
@@ -0,0 +1,286 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+. "toolchain_utils.sh" || exit 1
+. "common.sh" || exit 1
+CHROMEOS_MASTER_CONFIG_FILE="${BOARD_ROOT}/usr/share/chromeos-config/config.dtb"
+BUILD_DIR="build"
+BUILD_LIBRARY_DIR="."
+SCRIPTS_DIR="."
+echo "HERE"
+. "${BUILD_LIBRARY_DIR}/disk_layout_util.sh" || exit 1
+echo "HERE"
+. "${BUILD_LIBRARY_DIR}/mount_gpt_util.sh" || exit 1
+echo "HERE"
+. "${BUILD_LIBRARY_DIR}/build_image_util.sh" || exit 1
+echo "HERE"
+
+
+check_full_disk() {
+ local prev_ret=$?
+
+ # Disable die on error.
+ set +e
+
+ # See if we ran out of space. Only show if we errored out via a trap.
+ if [[ ${prev_ret} -ne 0 ]]; then
+ local df=$(df -B 1M "${root_fs_dir}")
+ if [[ ${df} == *100%* ]]; then
+ error "Here are the biggest [partially-]extracted files (by disk usage):"
+ # Send final output to stderr to match `error` behavior.
+ sudo find "${root_fs_dir}" -xdev -type f -printf '%b %P\n' | \
+ awk '$1 > 16 { $1 = $1 * 512; print }' | sort -n | tail -100 1>&2
+ error "Target image has run out of space:"
+ error "${df}"
+ fi
+ fi
+
+ # Turn die on error back on.
+ set -e
+}
+
+zero_free_space() {
+ local fs_mount_point=$1
+
+ if ! mountpoint -q "${fs_mount_point}"; then
+ info "Not zeroing freespace in ${fs_mount_point} since it isn't a mounted" \
+ "filesystem. This is normal for squashfs and ubifs partitions."
+ return 0
+ fi
+
+ info "Zeroing freespace in ${fs_mount_point}"
+ # dd is a silly thing and will produce a "No space left on device" message
+ # that cannot be turned off and is confusing to unsuspecting victims.
+ info "${fs_mount_point}/filler"
+ ( sudo dd if=/dev/zero of="${fs_mount_point}/filler" bs=4096 conv=fdatasync \
+ status=noxfer || true ) 2>&1 | grep -v "No space left on device"
+ sudo rm "${fs_mount_point}/filler"
+}
+
+# create_dev_install_lists updates package lists used by
+# chromeos-base/dev-install
+create_dev_install_lists() {
+ local root_fs_dir=$1
+
+ info "Building dev-install package lists"
+
+ local pkgs=(
+ portage
+ virtual/target-os
+ virtual/target-os-dev
+ virtual/target-os-test
+ )
+
+ local pkgs_out=$(mktemp -d)
+
+ for pkg in "${pkgs[@]}" ; do
+ emerge-${BOARD} --color n --pretend --quiet --emptytree \
+ --root-deps=rdeps ${pkg} | \
+ egrep -o ' [[:alnum:]-]+/[^[:space:]/]+\b' | \
+ tr -d ' ' | \
+ sort > "${pkgs_out}/${pkg##*/}.packages"
+ local _pipestatus=${PIPESTATUS[*]}
+ [[ ${_pipestatus// } -eq 0 ]] || error "\`emerge-${BOARD} ${pkg}\` failed"
+ done
+
+ # bootstrap = portage - target-os
+ comm -13 "${pkgs_out}/target-os.packages" \
+ "${pkgs_out}/portage.packages" > "${pkgs_out}/bootstrap.packages"
+
+ # chromeos-base = target-os + portage - virtuals
+ sort -u "${pkgs_out}/target-os.packages" "${pkgs_out}/portage.packages" \
+ | grep -v "virtual/" \
+ > "${pkgs_out}/chromeos-base.packages"
+
+ # package.installable = target-os-dev + target-os-test - target-os + virtuals
+ comm -23 <(cat "${pkgs_out}/target-os-dev.packages" \
+ "${pkgs_out}/target-os-test.packages" | sort) \
+ "${pkgs_out}/target-os.packages" \
+ > "${pkgs_out}/package.installable"
+ grep "virtual/" "${pkgs_out}/target-os.packages" \
+ >> "${pkgs_out}/package.installable"
+
+ # Add dhcp to the list of packages installed since its installation will not
+ # complete (can not add dhcp group since /etc is not writeable). Bootstrap it
+ # instead.
+ grep "net-misc/dhcp-" "${pkgs_out}/target-os-dev.packages" \
+ >> "${pkgs_out}/chromeos-base.packages" || true
+ grep "net-misc/dhcp-" "${pkgs_out}/target-os-dev.packages" \
+ >> "${pkgs_out}/bootstrap.packages" || true
+
+ sudo mkdir -p \
+ "${root_fs_dir}/usr/share/dev-install/portage/make.profile/package.provided"
+ sudo cp "${pkgs_out}/bootstrap.packages" \
+ "${root_fs_dir}/usr/share/dev-install/portage"
+ sudo cp "${pkgs_out}/package.installable" \
+ "${root_fs_dir}/usr/share/dev-install/portage/make.profile"
+ sudo cp "${pkgs_out}/chromeos-base.packages" \
+ "${root_fs_dir}/usr/share/dev-install/portage/make.profile/package.provided"
+
+ rm -r "${pkgs_out}"
+}
+
+install_libc() {
+ root_fs_dir="$1"
+ # We need to install libc manually from the cross toolchain.
+ # TODO: Improve this? It would be ideal to use emerge to do this.
+ libc_version="$(get_variable "${BOARD_ROOT}/${SYSROOT_SETTINGS_FILE}" \
+ "LIBC_VERSION")"
+ PKGDIR="/var/lib/portage/pkgs"
+ local libc_atom="cross-${CHOST}/glibc-${libc_version}"
+ LIBC_PATH="${PKGDIR}/${libc_atom}.tbz2"
+
+ if [[ ! -e ${LIBC_PATH} ]]; then
+ sudo emerge --nodeps -gf "=${libc_atom}"
+ fi
+
+ # Strip out files we don't need in the final image at runtime.
+ local libc_excludes=(
+ # Compile-time headers.
+ 'usr/include' 'sys-include'
+ # Link-time objects.
+ '*.[ao]'
+ # Debug commands not used by normal runtime code.
+ 'usr/bin/'{getent,ldd}
+ # LD_PRELOAD objects for debugging.
+ 'lib*/lib'{memusage,pcprofile,SegFault}.so 'usr/lib*/audit'
+ # We only use files & dns with nsswitch, so throw away the others.
+ 'lib*/libnss_'{compat,db,hesiod,nis,nisplus}'*.so*'
+ # This is only for very old packages which we don't have.
+ 'lib*/libBrokenLocale*.so*'
+ )
+ pbzip2 -dc --ignore-trailing-garbage=1 "${LIBC_PATH}" | \
+ sudo tar xpf - -C "${root_fs_dir}" ./usr/${CHOST} \
+ --strip-components=3 "${libc_excludes[@]/#/--exclude=}"
+}
+
+create_base_image() {
+ local image_name=$1
+ local rootfs_verification_enabled=$2
+ local bootcache_enabled=$3
+ local output_dev=$4
+ local image_type="usb"
+
+ BUILD_DIR="build"
+ check_valid_layout "base"
+ check_valid_layout "${image_type}"
+
+ echo "Using image type ${image_type}"
+ get_disk_layout_path
+ echo "Using disk layout ${DISK_LAYOUT_PATH}"
+
+ mkdir -p "$BUILD_DIR"
+
+ root_fs_dir="${BUILD_DIR}/rootfs"
+ stateful_fs_dir="${BUILD_DIR}/stateful"
+ esp_fs_dir="${BUILD_DIR}/esp"
+
+ mkdir "${root_fs_dir}" "${stateful_fs_dir}" "${esp_fs_dir}"
+ echo "Building GPT IMAGE"
+ build_gpt_image "${output_dev}" "${image_type}"
+
+ echo "Mounting GPT IMAGE"
+ mount_image "${output_dev}" "${root_fs_dir}" \
+ "${stateful_fs_dir}" "${esp_fs_dir}"
+
+ echo "Df- h command"
+ df -h "${root_fs_dir}"
+
+ # Create symlinks so that /usr/local/usr based directories are symlinked to
+ # /usr/local/ directories e.g. /usr/local/usr/bin -> /usr/local/bin, etc.
+
+ # INSTALL KERNEL ON PARTITION 2
+
+ local kernel_partition="2"
+ sudo dd if=kernels/linux.bin of=${output_dev}${kernel_partition}
+
+ "${VBOOT_SIGNING_DIR}"/insert_container_publickey.sh \
+ "${root_fs_dir}" \
+ "${VBOOT_DEVKEYS_DIR}"/cros-oci-container-pub.pem
+
+
+ "${GCLIENT_ROOT}/chromite/bin/cros_set_lsb_release" \
+ --sysroot="${root_fs_dir}" \
+ --board="${BOARD}" \
+ "${model_flags[@]}" \
+ ${builder_path} \
+ --version_string="${CHROMEOS_VERSION_STRING}" \
+ --auserver="${CHROMEOS_VERSION_AUSERVER}" \
+ --devserver="${CHROMEOS_VERSION_DEVSERVER}" \
+ ${official_flag} \
+ --buildbot_build="${BUILDBOT_BUILD:-"N/A"}" \
+ --track="${CHROMEOS_VERSION_TRACK:-"developer-build"}" \
+ --branch_number="${CHROMEOS_BRANCH}" \
+ --build_number="${CHROMEOS_BUILD}" \
+ --chrome_milestone="${CHROME_BRANCH}" \
+ --patch_number="${CHROMEOS_PATCH}" \
+ "${arc_flags[@]}"
+
+ # Set /etc/os-release on the image.
+ # Note: fields in /etc/os-release can come from different places:
+ # * /etc/os-release itself with docrashid
+ # * /etc/os-release.d for fields created with do_osrelease_field
+ sudo "${GCLIENT_ROOT}/chromite/bin/cros_generate_os_release" \
+ --root="${root_fs_dir}" \
+ --version="${CHROME_BRANCH}" \
+ --build_id="${CHROMEOS_VERSION_STRING}"
+
+ # Create the boot.desc file which stores the build-time configuration
+ # information needed for making the image bootable after creation with
+ # cros_make_image_bootable.
+ create_boot_desc "${image_type}"
+
+ # Write out the GPT creation script.
+ # This MUST be done before writing bootloader templates else we'll break
+ # the hash on the root FS.
+ write_partition_script "${image_type}" \
+ "${root_fs_dir}/${PARTITION_SCRIPT_PATH}"
+ sudo chown root:root "${root_fs_dir}/${PARTITION_SCRIPT_PATH}"
+
+ # Populates the root filesystem with legacy bootloader templates
+ # appropriate for the platform. The autoupdater and installer will
+ # use those templates to update the legacy boot partition (12/ESP)
+ # on update.
+ # (This script does not populate vmlinuz.A and .B needed by syslinux.)
+ # Factory install shims may be booted from USB by legacy EFI BIOS, which does
+ # not support verified boot yet (see create_legacy_bootloader_templates.sh)
+ # so rootfs verification is disabled if we are building with --factory_install
+ local enable_rootfs_verification=
+ if [[ ${rootfs_verification_enabled} -eq ${FLAGS_TRUE} ]]; then
+ enable_rootfs_verification="--enable_rootfs_verification"
+ fi
+ local enable_bootcache=
+ if [[ ${bootcache_enabled} -eq ${FLAGS_TRUE} ]]; then
+ enable_bootcache="--enable_bootcache"
+ fi
+
+ create_legacy_bootloader_templates.sh \
+ --arch=${ARCH} \
+ --board=${BOARD} \
+ --image_type="${image_type}" \
+ --to="${root_fs_dir}"/boot \
+ --boot_args="${FLAGS_boot_args}" \
+ --enable_serial="${FLAGS_enable_serial}" \
+ --loglevel="${FLAGS_loglevel}" \
+ ${enable_rootfs_verification} \
+ ${enable_bootcache}
+
+
+
+ # Zero rootfs free space to make it more compressible so auto-update
+ # payloads become smaller
+ zero_free_space "${root_fs_dir}"
+
+ unmount_image
+ trap - EXIT
+
+ USE_DEV_KEYS="--use_dev_keys"
+
+ if [[ ${skip_kernelblock_install} -ne 1 ]]; then
+ # Place flags before positional args.
+ ${SCRIPTS_DIR}/bin/cros_make_image_bootable "${BUILD_DIR}" \
+ ${output_dev} ${USE_DEV_KEYS} --adjust_part="${FLAGS_adjust_part}"
+ fi
+}
+create_base_image $1 $2 $3 $4
diff --git a/nichrome/scripts/bin/cros_get_chrome_version b/nichrome/scripts/bin/cros_get_chrome_version
new file mode 100755
index 000000000..80267c552
--- /dev/null
+++ b/nichrome/scripts/bin/cros_get_chrome_version
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Returns the version of Chrome running on a remote machine.
+
+# --- BEGIN COMMON.SH BOILERPLATE ---
+# Load common CrOS utilities. Inside the chroot this file is installed in
+# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
+# location.
+find_common_sh() {
+ local common_paths=("$(dirname "$(readlink -f "$0")")/.." /usr/lib/crosutils)
+ local path
+
+ SCRIPT_ROOT="${common_paths[0]}"
+ for path in "${common_paths[@]}"; do
+ if [ -r "${path}/common.sh" ]; then
+ SCRIPT_ROOT="${path}"
+ break
+ fi
+ done
+}
+
+find_common_sh
+. "${SCRIPT_ROOT}/common.sh" || exit 1
+# --- END COMMON.SH BOILERPLATE ---
+
+. "${SCRIPT_ROOT}/remote_access.sh" || exit 1
+
+FLAGS "$@" || exit 1
+
+switch_to_strict_mode
+
+# TMP necessary for remote_access_init.
+TMP=$(mktemp -d /tmp/cros_check_chrome_version.XXXX)
+trap "rm -rf ${TMP}" EXIT
+
+remote_access_init &> /dev/null
+
+remote_sh "/opt/google/chrome/chrome --version"
+CHROME_VERSION=$(echo ${REMOTE_OUT} | \
+ sed 's/.* \([0-9]\+.[0-9]\+.[0-9]\+.[0-9]\+\).*/\1/')
+echo "${CHROME_VERSION}"
diff --git a/nichrome/scripts/bin/cros_make_image_bootable b/nichrome/scripts/bin/cros_make_image_bootable
new file mode 100755
index 000000000..aeb5f4b41
--- /dev/null
+++ b/nichrome/scripts/bin/cros_make_image_bootable
@@ -0,0 +1,448 @@
+#!/bin/bash
+#
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Script which ensures that a given image has an up-to-date
+# kernel partition, rootfs integrity hashes, and legacy bootloader configs.
+
+# --- BEGIN COMMON.SH BOILERPLATE ---
+# Load common CrOS utilities. Inside the chroot this file is installed in
+# /usr/lib/crosutils. Outside the chroot we find it relative to the script's
+# location.
+find_common_sh() {
+ local common_paths=("$(dirname "$(readlink -f "$0")")/.." /usr/lib/crosutils)
+ local path
+
+ SCRIPT_ROOT="${common_paths[0]}"
+ for path in "${common_paths[@]}"; do
+ if [ -r "${path}/common.sh" ]; then
+ SCRIPT_ROOT="${path}"
+ break
+ fi
+ done
+}
+
+find_common_sh
+. "${SCRIPT_ROOT}/common.sh" || exit 1
+# --- END COMMON.SH BOILERPLATE ---
+
+# Need to be inside the chroot to load chromeos-common.sh
+
+# Load functions and constants for chromeos-install
+. chromeos-common.sh || exit 1
+. "build_image_util.sh" || exit 1
+. "disk_layout_util.sh" || exit 1
+. "mount_gpt_util.sh" || exit 1
+
+switch_to_strict_mode
+
+if [ $# -lt 2 ]; then
+ echo "Usage: ${0} /PATH/TO/IMAGE IMAGE.BIN [shflags overrides]"
+ exit 1
+fi
+
+IMAGE_DIR="$(readlink -f "${1}")"
+IMAGE="${2}"
+shift
+shift
+FLAG_OVERRIDES=( "$@" )
+
+if get_boot_desc "${IMAGE_DIR}/boot.desc"; then
+ info "Boot-time configuration for ${IMAGE_DIR}:"
+ for flag in "${boot_desc_flags[@]}"; do
+ info " ${flag}"
+ done
+else
+ warn "Falling back to command line parsing."
+fi
+
+if [ ! -r "${IMAGE}" ]; then
+ die "${IMAGE} cannot be read!"
+fi
+
+
+set +e
+
+# Now parse the build settings from ${OUTPUT_DIR}/boot.desc
+DEFINE_string adjust_part "" \
+ "Adjustments to apply to the partition table"
+DEFINE_string board "${DEFAULT_BOARD}" \
+ "Board we're building for."
+DEFINE_string image_type "base" \
+ "Type of image we're building for (base/factory_install)."
+DEFINE_string output_dir "/tmp" \
+ "Directory to place output in."
+DEFINE_string image "chromiumos_base.img" \
+ "Full path to the chromiumos image to make bootable."
+DEFINE_string arch "x86" \
+ "Architecture to make bootable for: arm, mips, x86, or amd64"
+DEFINE_boolean cleanup_dirs ${FLAGS_TRUE} \
+ "Whether the mount dirs should be removed on completion."
+
+DEFINE_string boot_args "noinitrd" \
+ "Additional boot arguments to pass to the commandline"
+
+DEFINE_integer rootfs_size 720 \
+ "rootfs filesystem size in MBs."
+# ceil(0.1 * rootfs_size) is a good minimum.
+DEFINE_integer rootfs_hash_pad 8 \
+ "MBs reserved at the end of the rootfs image."
+
+DEFINE_string rootfs_hash "/tmp/rootfs.hash" \
+ "Path where the rootfs hash should be stored."
+# TODO(taysom): when we turn on boot cache, both verification and
+# bootcache should have their default be FLAGS_TRUE.
+DEFINE_boolean enable_rootfs_verification ${FLAGS_TRUE} \
+ "Default all bootloaders to NOT use kernel-based root fs integrity checking."
+DEFINE_boolean enable_bootcache ${FLAGS_FALSE} \
+ "Default all bootloaders to NOT use bootcache."
+DEFINE_integer verity_error_behavior 3 \
+ "Kernel verified boot error behavior (0: I/O errors, 1: reboot, 2: nothing)"
+DEFINE_integer verity_max_ios -1 \
+ "Number of outstanding I/O operations dm-verity caps at."
+DEFINE_string verity_algorithm "sha1" \
+ "Cryptographic hash algorithm used for kernel vboot."
+DEFINE_string verity_salt "" \
+ "Salt for rootfs hash tree."
+
+DEFINE_string keys_dir "${VBOOT_DEVKEYS_DIR}" \
+ "Directory containing the signing keys."
+
+DEFINE_string rootfs_mountpoint "/tmp/rootfs" \
+ "Path where the rootfs can be safely mounted"
+DEFINE_string statefulfs_mountpoint "/tmp/statefulfs" \
+ "Path where the statefulfs can be safely mounted"
+DEFINE_string espfs_mountpoint "/tmp/espfs" \
+ "Path where the espfs can be safely mounted"
+
+DEFINE_boolean use_dev_keys ${FLAGS_FALSE} \
+ "Use developer keys for signing. (Default: false)"
+
+DEFINE_boolean fsck_rootfs ${FLAGS_FALSE} \
+ "Check integrity of the rootfs on the modified image."
+
+# TODO(pkumar): Remove once known that no images are using this flag
+DEFINE_boolean crosbug12352_arm_kernel_signing ${FLAGS_FALSE} \
+ "This flag is deprecated but the bots still need parse old images."
+
+# TODO(sosa): Remove once known images no longer use this in their config.
+DEFINE_string arm_extra_bootargs "" "DEPRECATED FLAG. Do not use."
+
+DEFINE_boolean force_developer_mode ${FLAGS_FALSE} \
+ "Add cros_debug to boot args."
+
+DEFINE_string enable_serial "" \
+ "Enable serial port for printks. Example values: ttyS0"
+DEFINE_integer loglevel 7 \
+ "The loglevel to add to the kernel command line."
+
+# Parse the boot.desc and any overrides
+set -- "${boot_desc_flags[@]}" "${FLAG_OVERRIDES[@]}"
+FLAGS "${@}" || exit 1
+
+[ -z "${FLAGS_verity_salt}" ] && FLAGS_verity_salt=$(make_salt)
+
+# Only now can we die on error. shflags functions leak non-zero error codes,
+# so will die prematurely if 'switch_to_strict_mode' is specified before now.
+switch_to_strict_mode -u
+
+append_boot_flag() {
+ local file="$1"
+ local pattern="$2"
+ local base_pattern="$3"
+
+ [ -f "${file}" ] || return ${FLAGS_TRUE}
+ grep -wq "${pattern}" "${file}" && return ${FLAGS_TRUE}
+ sudo sed -i "s/\b${base_pattern}\b/& ${pattern}/g" "${file}"
+}
+
+check_kernel_size() {
+ local kernel_image_size="$1"
+ local kernel_part="$2"
+ local kernel_slot="$3"
+ local kernel_partition_size=$(get_partition_size ${FLAGS_image_type} \
+ ${kernel_part})
+ local kernel_partition_size_90=$(( kernel_partition_size * 90 / 100 ))
+ info "Kernel partition ${kernel_slot} size is ${kernel_partition_size} bytes."
+ if [[ ${kernel_image_size} -gt ${kernel_partition_size} ]]; then
+ die "Kernel image won't fit in partition ${kernel_slot}!"
+ elif [[ ${kernel_image_size} -gt ${kernel_partition_size_90} ]]; then
+ warn "Kernel partition ${kernel_slot} is more than 90% full!"
+ fi
+}
+
+build_img() {
+ local image_name="$1"
+ local root_dev="$2"
+ local root_dev_size="$3"
+ local keyblock="$4"
+ local private="$5"
+ local public="$6"
+ local vblock=${7:-""}
+
+ # Default to non-verified
+ local enable_rootfs_verification_flag=--noenable_rootfs_verification
+ if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
+ enable_rootfs_verification_flag=--enable_rootfs_verification
+ fi
+ local enable_bootcache_flag=--noenable_bootcache
+ if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then
+ enable_bootcache_flag=--enable_bootcache
+ fi
+
+ if [[ -n "${vblock}" ]]; then
+ vblock=--hd_vblock="${FLAGS_output_dir}/${vblock}"
+ fi
+
+ ./build_kernel_image.sh \
+ --board="${FLAGS_board}" \
+ --arch="${FLAGS_arch}" \
+ --to="${FLAGS_output_dir}/${image_name}" \
+ --vmlinuz="${FLAGS_rootfs_mountpoint}/boot/vmlinuz" \
+ --working_dir="${FLAGS_output_dir}" \
+ --boot_args="${FLAGS_boot_args}" \
+ --keep_work \
+ --rootfs_image=${root_dev} \
+ --rootfs_image_size=${root_dev_size} \
+ --rootfs_hash=${FLAGS_rootfs_hash} \
+ --verity_hash_alg=${FLAGS_verity_algorithm} \
+ --verity_max_ios=${FLAGS_verity_max_ios} \
+ --verity_error_behavior=${FLAGS_verity_error_behavior} \
+ --verity_salt=${FLAGS_verity_salt} \
+ --keys_dir="${FLAGS_keys_dir}" \
+ --keyblock="${keyblock}" \
+ --private="${private}" \
+ --public="${public}" \
+ --enable_serial="${FLAGS_enable_serial}" \
+ ${vblock} \
+ ${enable_rootfs_verification_flag} \
+ ${enable_bootcache_flag}
+}
+
+make_image_bootable() {
+ local image="$1"
+
+ # Update legacy boot config templates (in rootfs) before rootfs is locked.
+ # This is required because postinst will copy new legacy boot configurations
+ # from rootfs partition instead of modifying existing entries in EFI
+ # partition.
+ if [ ${FLAGS_force_developer_mode} -eq ${FLAGS_TRUE} ]; then
+ trap "unmount_image ; die 'cros_make_image_bootable failed.'" EXIT
+ mount_image "${image}" "${FLAGS_rootfs_mountpoint}" \
+ "${FLAGS_statefulfs_mountpoint}" "" ""
+
+ append_boot_flag "${FLAGS_rootfs_mountpoint}/boot/syslinux/root.A.cfg" \
+ "cros_debug" "cros_legacy"
+ append_boot_flag "${FLAGS_rootfs_mountpoint}/boot/syslinux/root.B.cfg" \
+ "cros_debug" "cros_legacy"
+ append_boot_flag "${FLAGS_rootfs_mountpoint}/boot/syslinux/usb.A.cfg" \
+ "cros_debug" "cros_legacy"
+ append_boot_flag "${FLAGS_rootfs_mountpoint}/boot/efi/boot/grub.cfg" \
+ "cros_debug" "cros_efi"
+
+ unmount_image
+ trap - EXIT
+ fi
+
+ # Make the filesystem un-mountable as read-write.
+ # mount_gpt_image.sh will undo this as needed.
+ # TODO(wad) make sure there is parity in the signing scripts.
+ if [ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]; then
+ # TODO(wad) this would be a good place to reset any other ext2 metadata.
+ warn "Disabling r/w mount of the root filesystem"
+ local rootfs_offset="$(partoffset ${image} 3)"
+ disable_rw_mount "${image}" "$(( rootfs_offset * 512 ))"
+ fi
+
+ trap "unmount_image ; die 'cros_make_image_bootable failed.'" EXIT
+ mount_image "${image}" "${FLAGS_rootfs_mountpoint}" \
+ "${FLAGS_statefulfs_mountpoint}" "" "--safe"
+
+ # Newer `mount` will decode the filename backing the loop device,
+ # so we need to dig deeper and find the answer ourselves.
+ root_dev=$(awk -v mnt="${FLAGS_rootfs_mountpoint}" \
+ '$2 == mnt { print $1 }' /proc/mounts)
+ if [[ -z "${root_dev}" ]]; then
+ # If the read-only rootfs is not mounted via the kernel using a real block
+ # device and we need to create one here. So far, all the filesystems we
+ # use in the rootfs can be mounted read-only by the kernel (including
+ # squashfs) so we just exit if that's the case.
+ die "Didn't find the rootfs block device device after mounting it."
+ fi
+
+ # We sign the image with the recovery_key, because this is what goes onto the
+ # USB key. We can only boot from the USB drive in recovery mode.
+ # For dev install shim, we need to use the installer keyblock instead of
+ # the recovery keyblock because of the difference in flags.
+ local keyblock
+ if [ ${FLAGS_use_dev_keys} -eq ${FLAGS_TRUE} ]; then
+ keyblock=installer_kernel.keyblock
+ info "DEBUG: use dev install keyblock"
+ else
+ keyblock=recovery_kernel.keyblock
+ info "DEBUG: use recovery keyblock"
+ fi
+
+ if [ ${FLAGS_force_developer_mode} -eq ${FLAGS_TRUE} ]; then
+ FLAGS_boot_args="${FLAGS_boot_args} cros_debug"
+ fi
+
+ # Builds the kernel partition image.
+ local partition_num_root_a="$(get_layout_partition_number \
+ "${FLAGS_image_type}" ROOT-A)"
+ local rootfs_fs_size=$(get_filesystem_size "${FLAGS_image_type}" \
+ "${partition_num_root_a}")
+ #build_img "vmlinuz.image" "${root_dev}" "${rootfs_fs_size}" "${keyblock}" \
+ # "recovery_kernel_data_key.vbprivk" "recovery_key.vbpubk"
+ #build_img "hd_vmlinuz.image" "${root_dev}" "${rootfs_fs_size}" \
+ # "kernel.keyblock" "kernel_data_key.vbprivk" "kernel_subkey.vbpubk" \
+ # "vmlinuz_hd.vblock"
+
+ # Check the size of kernel image and issue warning when image size is
+ # near the limit.
+ local kernel_image_size_A=$(stat -c '%s' kernels/linux.bin)
+ info "Kernel image A size is ${kernel_image_size_A} bytes."
+ local kernel_image_size_B=$(stat -c '%s' kernels/linux.bin)
+ info "Kernel image B size is ${kernel_image_size_B} bytes."
+ local partition_num_kern_a="$(get_layout_partition_number \
+ "${FLAGS_image_type}" KERN-A)"
+ check_kernel_size ${kernel_image_size_A} ${partition_num_kern_a} A
+ local partition_num_kern_b="$(get_layout_partition_number \
+ "${FLAGS_image_type}" KERN-B)"
+ check_kernel_size ${kernel_image_size_B} ${partition_num_kern_b} B
+
+# local rootfs_hash_size=$(stat -c '%s' ${FLAGS_rootfs_hash})
+# local rootfs_partition_size=$(get_partition_size ${FLAGS_image_type} \
+# ${partition_num_root_a})
+# local rootfs_hash_pad=$(( rootfs_partition_size - rootfs_fs_size ))
+# info "Appending rootfs.hash (${rootfs_hash_size} bytes) to the root fs"
+# if [[ ${rootfs_hash_size} -gt ${rootfs_hash_pad} ]]
+# then
+# die "rootfs_partition_size - rootfs_fs_size is less than the needed " \
+# "rootfs_hash_size (${rootfs_hash_size}), update your disk layout " \
+# "configuration"
+# fi
+# # Unfortunately, mount_gpt_image uses mount and not losetup to create the
+# # loop devices. This means that they are not the correct size. We have to
+# # write directly to the image to append the hash tree data.
+# local hash_offset="$(partoffset ${image} ${partition_num_root_a})"
+# hash_offset=$((hash_offset + (${rootfs_fs_size} / 512)))
+# sudo dd bs=512 \
+# seek=${hash_offset} \
+# if="${FLAGS_rootfs_hash}" \
+# of="${image}" \
+# conv=notrunc \
+# status=none
+#
+# # Move the verification block needed for the hard disk install to the
+# # stateful partition. Mount stateful fs, copy file, and umount fs.
+# # In original CL: http://codereview.chromium.org/2868044, this was done in
+# # create_base_image(). However, it could break the build if it is a clean
+# # build because vmlinuz_hd.vblock hasn't been created by build_kernel_image.sh
+# # In some builds that don't use vboot to verify the kernel, this file might
+# # not get created as part of the build, so only copy them if they were.
+# if [ -f "${FLAGS_output_dir}/vmlinuz_hd.vblock" ]; then
+# sudo cp "${FLAGS_output_dir}/vmlinuz_hd.vblock" \
+# "${FLAGS_statefulfs_mountpoint}"
+# fi
+
+ # Install the kernel to both slots A and B so there will always be a regular
+ # kernel in slot B on recovery and non-recovery images.
+ local koffset="$(partoffset ${image} ${partition_num_kern_a})"
+ sudo dd if="kernels/linux.bin" of="${image}" \
+ conv=notrunc bs=512 seek=${koffset} status=none
+ koffset="$(partoffset ${image} ${partition_num_kern_b})"
+ sudo dd if="kernels/linux.bin" of="${image}" \
+ conv=notrunc bs=512 seek=${koffset} status=none
+
+ # Update the bootloaders. The EFI system partition will be updated.
+# local kernel_part=
+#
+# # We should update the esp in place in the image.
+# local bootloader_to="${image}"
+# local partition_num_efi_system="$(get_layout_partition_number \
+# "${FLAGS_image_type}" EFI-SYSTEM)"
+# local esp_offset="$(partoffset ${image} ${partition_num_efi_system})"
+# esp_offset=$((esp_offset * 512)) # sectors to bytes
+# local esp_size="$(partsize ${image} ${partition_num_efi_system})"
+# esp_size=$((esp_size * 512)) # sectors to bytes
+# local bootloader_to_flags="--to_offset=${esp_offset} --to_size=${esp_size}"
+#
+# if [[ "${FLAGS_arch}" = "x86" || "${FLAGS_arch}" = "amd64" ]]; then
+# # Use the kernel partition to acquire configuration flags.
+# kernel_part="--kernel_partition='${FLAGS_output_dir}/vmlinuz.image'"
+# # Install syslinux on the EFI System Partition.
+# kernel_part="${kernel_part} --install_syslinux"
+# elif [[ "${FLAGS_arch}" = "arm" || "${FLAGS_arch}" = "mips" ]]; then
+# # These flags are not used for ARM / MIPS update_bootloaders.sh
+# kernel_part=""
+# fi
+#
+# if [[ ${esp_size} -gt 0 ]]; then
+# # Update EFI partition
+# ./update_bootloaders.sh \
+# --arch="${FLAGS_arch}" \
+# --image_type="${FLAGS_image_type}" \
+# --to="${bootloader_to}" \
+# --from="${FLAGS_rootfs_mountpoint}"/boot \
+# --vmlinuz="${FLAGS_rootfs_mountpoint}"/boot/vmlinuz \
+# ${bootloader_to_flags} \
+# ${kernel_part}
+# fi
+#
+# # We don't need to keep these files around anymore.
+# sudo rm -f "${FLAGS_rootfs_hash}" "${FLAGS_output_dir}/vmlinuz.image" \
+# "${FLAGS_output_dir}/hd_vmlinuz.image" \
+# "${FLAGS_output_dir}/vmlinuz_hd.vblock"
+#
+ unmount_image
+ trap - EXIT
+}
+
+verify_image_rootfs() {
+ local image=$1
+ local partition_num_root_a="$(get_layout_partition_number \
+ "${FLAGS_image_type}" ROOT-A)"
+ local rootfs_offset="$(partoffset ${image} ${partition_num_root_a})"
+
+ local rootfs_tmp_file=$(mktemp)
+ trap "rm ${rootfs_tmp_file}" EXIT
+ sudo dd if="${image}" of="${rootfs_tmp_file}" bs=512 skip="${rootfs_offset}" \
+ status=none
+
+ # This flips the read-only compatibility flag, so that
+ # e2fsck does not complain about unknown file system capabilities.
+ enable_rw_mount "${rootfs_tmp_file}"
+ info "Running e2fsck to check root file system for errors"
+ sudo e2fsck -fn "${rootfs_tmp_file}" ||
+ die "Root file system has errors, please ensure boot.desc and/or \
+command line parameters are correct"
+}
+
+# Store output and temporary files next to image.
+FLAGS_output_dir="${IMAGE_DIR}"
+FLAGS_rootfs_hash="${IMAGE_DIR}/rootfs.hash"
+FLAGS_rootfs_mountpoint="${IMAGE_DIR}/rootfs_dir"
+FLAGS_statefulfs_mountpoint="${IMAGE_DIR}/stateful_dir"
+FLAGS_espfs_mountpoint="${IMAGE_DIR}/esp"
+
+# Create the directories if they don't exist.
+mkdir -p ${FLAGS_rootfs_mountpoint}
+mkdir -p ${FLAGS_statefulfs_mountpoint}
+mkdir -p ${FLAGS_espfs_mountpoint}
+
+make_image_bootable "${IMAGE}"
+if type -p board_make_image_bootable; then
+ board_make_image_bootable "${IMAGE}"
+fi
+if [ ${FLAGS_fsck_rootfs} -eq ${FLAGS_TRUE} ]; then
+ verify_image_rootfs "${IMAGE}"
+fi
+
+if [ ${FLAGS_cleanup_dirs} -eq ${FLAGS_TRUE} ]; then
+ rmdir ${FLAGS_rootfs_mountpoint}
+ rmdir ${FLAGS_statefulfs_mountpoint}
+ rmdir ${FLAGS_espfs_mountpoint}
+fi
diff --git a/nichrome/scripts/bin/cros_start_vm b/nichrome/scripts/bin/cros_start_vm
new file mode 100755
index 000000000..ffb9f59ae
--- /dev/null
+++ b/nichrome/scripts/bin/cros_start_vm
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Simple wrapper script to start a vm using the vm lib.
+. "$(dirname "$0")/../common.sh" || exit 1
+
+. "${SCRIPTS_DIR}/lib/cros_vm_lib.sh" || die "Unable to load cros_vm_lib.sh"
+. "${SCRIPTS_DIR}/lib/cros_vm_constants.sh" || \
+ die "Unable to load cros_vm_constants.sh"
+
+DEFINE_string board "${DEFAULT_BOARD}" \
+ "Board for VM image (unnecessary if path given)"
+DEFINE_string image_path "" "Full path of the VM image"
+
+set -e
+
+# Parse command line.
+FLAGS "$@" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+# Use latest if not specified.
+if [ -z "${FLAGS_image_path}" ]; then
+ LATEST_IMAGE="$(${SCRIPTS_DIR}/get_latest_image.sh \
+ --board=${FLAGS_board})/${DEFAULT_QEMU_IMAGE}"
+ info "Using latest vm image ${LATEST_IMAGE}"
+ FLAGS_image_path=${LATEST_IMAGE}
+fi
+
+[ -e "${FLAGS_image_path}" ] || die "Image ${FLAGS_image_path} does not exist."
+
+start_kvm "${FLAGS_image_path}" "${FLAGS_board}"
+
+echo "ssh root@localhost -p ${FLAGS_ssh_port} -o StrictHostKeyChecking=no"
diff --git a/nichrome/scripts/bin/cros_stop_vm b/nichrome/scripts/bin/cros_stop_vm
new file mode 100755
index 000000000..7811bee50
--- /dev/null
+++ b/nichrome/scripts/bin/cros_stop_vm
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Simple wrapper script to stop a vm specified from a pid file.
+. "$(dirname "$0")/../common.sh" || exit 1
+
+. "${SCRIPTS_DIR}/lib/cros_vm_lib.sh" || die "Unable to load cros_vm_lib.sh"
+
+set -e
+
+# Parse command line.
+FLAGS "$@" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+# Requires pid file to be set.
+if [ -z "${FLAGS_kvm_pid}" ]; then
+ die "Must specify file with pid of kvm to kill."
+fi
+
+KVM_PID_FILE="${FLAGS_kvm_pid}"
+stop_kvm
diff --git a/nichrome/scripts/bin/proxy-gw b/nichrome/scripts/bin/proxy-gw
new file mode 100755
index 000000000..19fe3da6b
--- /dev/null
+++ b/nichrome/scripts/bin/proxy-gw
@@ -0,0 +1,63 @@
+#!/bin/bash
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# $1 = hostname, $2 = port
+#
+# Use socat to connect to the specified host and port via one of the proxies
+# defined in the environment, if the target host does not appear in the
+# no_proxy environment variable.
+
+DEST_HOST="$1"
+DEST_PORT="$2"
+
+# Determine whether the destination host is in the "no_proxy" list.
+use_proxy="true"
+GLOBIGNORE="*"
+for a_host in ${no_proxy//,/ } ; do
+ case "${a_host}" in
+ "*") # A "*" matches all hosts.
+ use_proxy="false"
+ break
+ ;;
+ .*) # Items of the form ".some.fqdn" imply match-at-end.
+ if [[ "${DEST_HOST}" == *"${a_host}" ]]; then
+ use_proxy="false"
+ break
+ fi
+ ;;
+ ${DEST_HOST}) # Items of the form "some.fqdn" imply exact-match.
+ use_proxy="false"
+ break
+ ;;
+ esac
+done
+
+if [[ -n "${all_proxy}" ]]; then
+ PROXY="${all_proxy}"
+ TYPE=SOCKS4
+ PORT_ATTR=socksport
+elif [[ -n "${https_proxy}" ]]; then
+ PROXY="${https_proxy}"
+ TYPE=PROXY
+ PORT_ATTR=proxyport
+elif [[ -n "${http_proxy}" ]]; then
+ PROXY="${http_proxy}"
+ TYPE=PROXY
+ PORT_ATTR=proxyport
+else
+ use_proxy="false"
+fi
+
+if [[ "${use_proxy}" == "true" ]]; then
+ PROXY="${PROXY#*://}"
+ PROXY="${PROXY%%/*}"
+ PROXY_HOST="${PROXY%%:*}"
+ PROXY_PORT="${PROXY##*:}"
+ PARMS="${PROXY_HOST}:${DEST_HOST}:${DEST_PORT},${PORT_ATTR}=${PROXY_PORT}"
+ socat_args=( "${TYPE}:${PARMS}" )
+else
+ socat_args=( TCP:"${DEST_HOST}":"${DEST_PORT}" )
+fi
+exec socat STDIO "${socat_args[@]}"
diff --git a/nichrome/scripts/board_options.sh b/nichrome/scripts/board_options.sh
new file mode 100755
index 000000000..50f6243fa
--- /dev/null
+++ b/nichrome/scripts/board_options.sh
@@ -0,0 +1,25 @@
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if [[ -z "${FLAGS_board}" ]]; then
+ if [[ -z "${SRC_IMAGE}" ]]; then
+ die "--board or SRC_IMAGE are required."
+ fi
+
+ # If --board is not set, get the board name from the image.
+ FLAGS_board="$(
+ . "${BUILD_LIBRARY_DIR}/mount_gpt_util.sh"
+ get_board_from_image "${SRC_IMAGE}"
+ )"
+fi
+
+BOARD="${FLAGS_board}"
+BOARD_ROOT="/build/${BOARD}"
+
+if [[ ! -d "${BOARD_ROOT}" ]]; then
+ die_notrace "The board has not been set up: ${BOARD}"
+fi
+
+# What cross-build are we targeting?
+. "${BOARD_ROOT}/etc/make.conf.board_setup"
diff --git a/nichrome/scripts/build_image_util.sh b/nichrome/scripts/build_image_util.sh
new file mode 100755
index 000000000..9dd17e9d5
--- /dev/null
+++ b/nichrome/scripts/build_image_util.sh
@@ -0,0 +1,326 @@
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Shell library for functions and initialization private to
+# build_image, and not specific to any particular kind of image.
+#
+# TODO(jrbarnette): There's nothing holding this code together in
+# one file aside from its lack of anywhere else to go. Probably,
+# this file should get broken up or otherwise reorganized.
+
+# Use canonical path since some tools (e.g. mount) do not like symlinks.
+# Append build attempt to output directory.
+IMAGE_SUBDIR="R${CHROME_BRANCH}"
+if [ -z "${FLAGS_version}" ]; then
+ IMAGE_SUBDIR="${IMAGE_SUBDIR}-${CHROMEOS_VERSION_STRING}-a\
+${FLAGS_build_attempt}"
+else
+ IMAGE_SUBDIR="${IMAGE_SUBDIR}-${FLAGS_version}"
+fi
+
+if [ -n "${FLAGS_output_suffix}" ]; then
+ IMAGE_SUBDIR="${IMAGE_SUBDIR}-${FLAGS_output_suffix}"
+fi
+
+BUILD_DIR="${FLAGS_build_root}/${BOARD}/${IMAGE_SUBDIR}"
+OUTPUT_DIR="${FLAGS_output_root}/${BOARD}/${IMAGE_SUBDIR}"
+OUTSIDE_OUTPUT_DIR="../build/images/${BOARD}/${IMAGE_SUBDIR}"
+IMAGES_TO_BUILD=
+
+EMERGE_BOARD_CMD="$GCLIENT_ROOT/chromite/bin/parallel_emerge"
+EMERGE_BOARD_CMD="$EMERGE_BOARD_CMD --board=$BOARD"
+
+export INSTALL_MASK="${DEFAULT_INSTALL_MASK}"
+
+if [[ $FLAGS_jobs -ne -1 ]]; then
+ EMERGE_JOBS="--jobs=$FLAGS_jobs"
+fi
+
+# Populates list of IMAGES_TO_BUILD from args passed in.
+# Arguments should be the shortnames of images we want to build.
+get_images_to_build() {
+ local image_to_build
+ for image_to_build in $*; do
+ # Shflags leaves "'"s around ARGV.
+ case ${image_to_build} in
+ \'base\' )
+ IMAGES_TO_BUILD="${IMAGES_TO_BUILD} ${CHROMEOS_BASE_IMAGE_NAME}"
+ ;;
+ \'dev\' )
+ IMAGES_TO_BUILD="${IMAGES_TO_BUILD} ${CHROMEOS_DEVELOPER_IMAGE_NAME}"
+ ;;
+ \'test\' )
+ IMAGES_TO_BUILD="${IMAGES_TO_BUILD} ${CHROMEOS_TEST_IMAGE_NAME}"
+ ;;
+ \'factory_install\' )
+ IMAGES_TO_BUILD="${IMAGES_TO_BUILD} \
+ ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}"
+ ;;
+ * )
+ die "${image_to_build} is not an image specification."
+ ;;
+ esac
+ done
+
+ # Set default if none specified.
+ if [ -z "${IMAGES_TO_BUILD}" ]; then
+ IMAGES_TO_BUILD=${CHROMEOS_DEVELOPER_IMAGE_NAME}
+ fi
+
+ info "The following images will be built ${IMAGES_TO_BUILD}."
+}
+
+# Look at flags to determine which image types we should build.
+parse_build_image_args() {
+ get_images_to_build ${FLAGS_ARGV}
+ if should_build_image ${CHROMEOS_BASE_IMAGE_NAME} \
+ ${CHROMEOS_DEVELOPER_IMAGE_NAME} ${CHROMEOS_TEST_IMAGE_NAME} && \
+ should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then
+ die_notrace \
+ "Can't build ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME} with any other" \
+ "image."
+ fi
+ if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then
+ # For factory, force rootfs verification and bootcache off
+ FLAGS_enable_rootfs_verification=${FLAGS_FALSE}
+ FLAGS_enable_bootcache=${FLAGS_FALSE}
+ FLAGS_bootcache_use_board_default=${FLAGS_FALSE}
+ fi
+}
+
+check_blacklist() {
+ info "Verifying that the base image does not contain a blacklisted package."
+ info "Generating list of packages for ${BASE_PACKAGE}."
+ local package_blacklist_file="${BUILD_LIBRARY_DIR}/chromeos_blacklist"
+ if [ ! -e "${package_blacklist_file}" ]; then
+ warn "Missing blacklist file."
+ return
+ fi
+ local blacklisted_packages=$(${SCRIPTS_DIR}/get_package_list \
+ --board="${BOARD}" "${BASE_PACKAGE}" \
+ | grep -x -f "${package_blacklist_file}")
+ if [ -n "${blacklisted_packages}" ]; then
+ die "Blacklisted packages found: ${blacklisted_packages}."
+ fi
+ info "No blacklisted packages found."
+}
+
+make_salt() {
+ # It is not important that the salt be cryptographically strong; it just needs
+ # to be different for each release. The purpose of the salt is just to ensure
+ # that if someone collides a block in one release, they can't reuse it in
+ # future releases.
+ xxd -l 32 -p -c 32 /dev/urandom
+}
+
+# Create a boot.desc file containing flags used to create this image.
+# The format is a bit fragile -- make sure get_boot_desc parses it back.
+create_boot_desc() {
+ local image_type=$1
+
+ local enable_rootfs_verification_flag=""
+ if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
+ enable_rootfs_verification_flag="--enable_rootfs_verification"
+ fi
+ local enable_bootcache_flag=""
+ if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then
+ enable_bootcache_flag=--enable_bootcache
+ fi
+
+ [ -z "${FLAGS_verity_salt}" ] && FLAGS_verity_salt=$(make_salt)
+ cat < ${BUILD_DIR}/boot.desc
+ --board=${BOARD}
+ --image_type=${image_type}
+ --arch="${ARCH}"
+ --keys_dir="${VBOOT_DEVKEYS_DIR}"
+ --boot_args="${FLAGS_boot_args}"
+ --nocleanup_dirs
+ --verity_algorithm=sha1
+ --enable_serial="${FLAGS_enable_serial}"
+ --loglevel="${FLAGS_loglevel}"
+ ${enable_rootfs_verification_flag}
+ ${enable_bootcache_flag}
+EOF
+}
+
+# Extract flags saved in boot.desc and return it via the boot_desc_flags array.
+get_boot_desc() {
+ local boot_desc_file=$1
+ local line
+
+ if [[ ! -r ${boot_desc_file} ]]; then
+ warn "${boot_desc_file}: cannot be read"
+ return 1
+ fi
+
+ # Do not mark this local as it is the return value.
+ boot_desc_flags=()
+ while read line; do
+ if [[ -z ${line} ]]; then
+ continue
+ fi
+
+ # Hand extract the quotes to deal with random content in the value.
+ # e.g. When you pass --boot_args="foo=\"\$bar'" to build_image, we write it
+ # out in the file as --boot_args="foo="$bar'" which is a parse error if we
+ # tried to eval it directly.
+ line=$(echo "${line}" | sed -r \
+ -e 's:^\s+::;s:\s+$::' -e "s:^(--[^=]+=)([\"'])(.*)\2$:\1\3:")
+ boot_desc_flags+=( "${line}" )
+ done <"${boot_desc_file}"
+}
+
+# Utility function for moving the build directory to the output root.
+move_image() {
+ local source="$1"
+ local destination="$2"
+ # If the output_root isn't the same as the build_root, move the resulting
+ # image to the correct place in output_root.
+ if [[ "${source}" != "${destination}" ]]; then
+ info "Moving the image to: ${destination}."
+ mkdir -p "${destination}"
+ mv "${source}"/* "${destination}"
+ rmdir "${source}"
+ fi
+}
+
+delete_prompt() {
+ echo "An error occurred in your build so your latest output directory" \
+ "is invalid."
+
+ # Only prompt if both stdin and stdout are a tty. If either is not a tty,
+ # then the user may not be present, so we shouldn't bother prompting.
+ if [ -t 0 -a -t 1 -a "${USER}" != 'chrome-bot' ]; then
+ read -p "Would you like to delete the output directory (y/N)? " SURE
+ SURE="${SURE:0:1}" # Get just the first character.
+ else
+ SURE="y"
+ echo "Running in non-interactive mode so deleting output directory."
+ fi
+ if [ "${SURE}" == "y" ] ; then
+ sudo rm -rf "${BUILD_DIR}"
+ echo "Deleted ${BUILD_DIR}"
+ else
+ move_image "${BUILD_DIR}" "${OUTPUT_DIR}"
+ echo "Not deleting ${OUTPUT_DIR}."
+ fi
+}
+
+# Basic command to emerge binary packages into the target image.
+# Arguments to this command are passed as addition options/arguments
+# to the basic emerge command.
+emerge_to_image() {
+ sudo -E ${EMERGE_BOARD_CMD} --root-deps=rdeps --usepkgonly -v \
+ "$@" ${EMERGE_JOBS}
+}
+
+# Create the /etc/shadow file with all the right entries.
+SHARED_USER_NAME="chronos"
+SHARED_USER_PASSWD_FILE="/etc/shared_user_passwd.txt"
+setup_etc_shadow() {
+ local root=$1
+ local shadow="${root}/etc/shadow"
+ local passwd="${root}/etc/passwd"
+ local line
+ local cmds
+
+ # Remove the file completely so we know it is fully initialized
+ # with the correct permissions. Note: we're just making it writable
+ # here to simplify scripting; permission fixing happens at the end.
+ cmds=(
+ "rm -f '${shadow}'"
+ "install -m 666 /dev/null '${shadow}'"
+ )
+ sudo_multi "${cmds[@]}"
+
+ # Create shadow entries for all accounts in /etc/passwd that says
+ # they expect it. Otherwise, pam will not let people even log in
+ # via ssh keyauth. http://crbug.com/361864
+ while read -r line; do
+ local acct=$(cut -d: -f1 <<<"${line}")
+ local pass=$(cut -d: -f2 <<<"${line}")
+
+ # For the special shared user account, load the shared user password
+ # if one has been set.
+ if [[ ${acct} == "${SHARED_USER_NAME}" &&
+ -e "${SHARED_USER_PASSWD_FILE}" ]]; then
+ pass=$(<"${SHARED_USER_PASSWD_FILE}")
+ fi
+
+ case ${pass} in
+ # Login is disabled -> do nothing.
+ '!') ;;
+ # Password will be set later by tools.
+ '*') ;;
+ # Password is shadowed.
+ 'x')
+ echo "${acct}:*:::::::" >> "${shadow}"
+ ;;
+ # Password is set directly.
+ *)
+ echo "${acct}:${pass}:::::::" >> "${shadow}"
+ ;;
+ esac
+ done <"${passwd}"
+
+ # Now make the settings sane.
+ cmds=(
+ "chown 0:0 '${shadow}'"
+ "chmod 600 '${shadow}'"
+ )
+ sudo_multi "${cmds[@]}"
+}
+
+# ldconfig cannot generate caches for non-native arches.
+# Use qemu & the native ldconfig to work around that.
+# http://crbug.com/378377
+run_ldconfig() {
+ local root_fs_dir=$1
+ case ${ARCH} in
+ arm)
+ sudo qemu-arm "${root_fs_dir}"/sbin/ldconfig -r "${root_fs_dir}";;
+ mips)
+ sudo qemu-mipsel "${root_fs_dir}"/sbin/ldconfig -r "${root_fs_dir}";;
+ x86|amd64)
+ sudo ldconfig -r "${root_fs_dir}";;
+ *)
+ die "Unable to run ldconfig for ARCH ${ARCH}"
+ esac
+}
+
+# Runs "depmod" to recalculate the kernel module dependencies.
+# Args:
+# board_root: root of the build output for the board
+# root_fs_dir: target root file system mount point
+run_depmod() {
+ local board_root="$1"
+ local root_fs_dir="$2"
+
+ local root_fs_modules_path="${root_fs_dir}/lib/modules"
+ if [[ ! -d "${root_fs_modules_path}" ]]; then
+ return
+ fi
+
+ local kernel_path
+ for kernel_path in "${root_fs_modules_path}/"*; do
+ local kernel_release="$(basename ${kernel_path})"
+ local kernel_out_dir="${board_root}/lib/modules/${kernel_release}/build"
+ local system_map="${kernel_out_dir}/System.map"
+
+ if [[ -r "${system_map}" ]]; then
+ sudo depmod -ae -F "${system_map}" -b "${root_fs_dir}" "${kernel_release}"
+ fi
+ done
+}
+
+# Newer udev versions do not pay attention to individual *.hwdb files
+# but require up to date /etc/udev/hwdb.bin. Let's [re]generate it as
+# part of build process.
+#
+# Since hwdb is a generic "key/value database based on modalias strings"
+# the version of udevadm found on the host should suffice.
+run_udevadm_hwdb() {
+ local root_fs_dir="$1"
+ sudo udevadm hwdb --update -r "${root_fs_dir}"
+}
diff --git a/nichrome/scripts/cgpt b/nichrome/scripts/cgpt
new file mode 100755
index 000000000..13cc4e357
Binary files /dev/null and b/nichrome/scripts/cgpt differ
diff --git a/nichrome/scripts/cgpt.py b/nichrome/scripts/cgpt.py
new file mode 100755
index 000000000..5f00937b3
--- /dev/null
+++ b/nichrome/scripts/cgpt.py
@@ -0,0 +1,1558 @@
+#!/usr/bin/env python2
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Parse and operate based on disk layout files."""
+
+from __future__ import print_function
+
+import argparse
+import copy
+import json
+import math
+import os
+import re
+import sys
+
+
+class ConfigNotFound(Exception):
+ """Config Not Found"""
+
+class PartitionNotFound(Exception):
+ """Partition Not Found"""
+
+class InvalidLayout(Exception):
+ """Invalid Layout"""
+
+class InvalidAdjustment(Exception):
+ """Invalid Adjustment"""
+
+class InvalidSize(Exception):
+ """Invalid Size"""
+
+class ConflictingOptions(Exception):
+ """Conflicting Options"""
+
+class ConflictingPartitionOrder(Exception):
+ """The partition order in the parent and child layout don't match."""
+
+class MismatchedRootfsFormat(Exception):
+ """Rootfs partitions in different formats"""
+
+class MismatchedRootfsBlocks(Exception):
+ """Rootfs partitions have different numbers of reserved erase blocks"""
+
+class MissingEraseBlockField(Exception):
+ """Partition has reserved erase blocks but not other fields needed"""
+
+class ExcessFailureProbability(Exception):
+ """Chances are high that the partition will have too many bad blocks"""
+
+class UnalignedPartition(Exception):
+ """Partition size does not divide erase block size"""
+
+class ExpandNandImpossible(Exception):
+ """Partition is raw NAND and marked with the incompatible expand feature"""
+
+class ExcessPartitionSize(Exception):
+ """Partitions sum to more than the size of the whole device"""
+
+COMMON_LAYOUT = 'common'
+BASE_LAYOUT = 'base'
+# Blocks of the partition entry array.
+SIZE_OF_PARTITION_ENTRY_ARRAY = 32
+SIZE_OF_PMBR = 1
+SIZE_OF_GPT_HEADER = 1
+
+
+def ParseHumanNumber(operand):
+ """Parse a human friendly number
+
+ This handles things like 4GiB and 4MB and such. See the usage string for
+ full details on all the formats supported.
+
+ Args:
+ operand: The number to parse (may be an int or string)
+
+ Returns:
+ An integer
+ """
+ operand = str(operand)
+ negative = -1 if operand.startswith('-') else 1
+ if negative == -1:
+ operand = operand[1:]
+ operand_digits = re.sub(r'\D', r'', operand)
+
+ size_factor = block_factor = 1
+ suffix = operand[len(operand_digits):].strip()
+ if suffix:
+ size_factors = {'B': 0, 'K': 1, 'M': 2, 'G': 3, 'T': 4,}
+ try:
+ size_factor = size_factors[suffix[0].upper()]
+ except KeyError:
+ raise InvalidAdjustment('Unknown size type %s' % suffix)
+ if size_factor == 0 and len(suffix) > 1:
+ raise InvalidAdjustment('Unknown size type %s' % suffix)
+ block_factors = {'': 1024, 'B': 1000, 'IB': 1024,}
+ try:
+ block_factor = block_factors[suffix[1:].upper()]
+ except KeyError:
+ raise InvalidAdjustment('Unknown size type %s' % suffix)
+
+ return int(operand_digits) * pow(block_factor, size_factor) * negative
+
+
+def ProduceHumanNumber(number):
+ """A simple reverse of ParseHumanNumber, converting a number to human form.
+
+ Args:
+ number: A number (int) to be converted to human form.
+
+ Returns:
+ A string, such as "1 KiB", that satisfies the condition
+ ParseHumanNumber(ProduceHumanNumber(i)) == i.
+ """
+ scales = [
+ (2**40, 'Ti'),
+ (10**12, 'T'),
+ (2**30, 'Gi'),
+ (10**9, 'G'),
+ (2**20, 'Mi'),
+ (10**6, 'M'),
+ (2**10, 'Ki'),
+ (10**3, 'K')
+ ]
+ for denom, suffix in scales:
+ if (number % denom) == 0:
+ return '%d %sB' % (number // denom, suffix)
+ return str(number)
+
+
+def ParseRelativeNumber(max_number, number):
+ """Return the number that is relative to |max_number| by |number|
+
+ We support three forms:
+ 90% - |number| is a percentage of |max_number|
+ 100 - |number| is the answer already (and |max_number| is ignored)
+ -90 - |number| is subtracted from |max_number|
+
+ Args:
+ max_number: The limit to use when |number| is negative or a percent
+ number: The (possibly relative) number to parse (may be an int or string)
+ """
+ max_number = int(max_number)
+ number = str(number)
+ if number.endswith('%'):
+ percent = float(number[:-1]) / 100
+ return int(max_number * percent)
+ else:
+ number = ParseHumanNumber(number)
+ if number < 0:
+ return max_number + number
+ else:
+ return number
+
+
+def _ApplyLayoutOverrides(layout_to_override, layout):
+ """Applies |layout| overrides on to |layout_to_override|.
+
+ First add missing partition from layout to layout_to_override.
+ Then, update partitions in layout_to_override with layout information.
+ """
+ # First check that all the partitions defined in both layouts are defined in
+ # the same order in each layout. Otherwise, the order in which they end up
+ # in the merged layout doesn't match what the user sees in the child layout.
+ common_nums = set.intersection(
+ {part['num'] for part in layout_to_override if 'num' in part},
+ {part['num'] for part in layout if 'num' in part})
+ layout_to_override_order = [part['num'] for part in layout_to_override
+ if part.get('num') in common_nums]
+ layout_order = [part['num'] for part in layout
+ if part.get('num') in common_nums]
+ if layout_order != layout_to_override_order:
+ raise ConflictingPartitionOrder(
+ 'Layouts share partitions %s but they are in different order: '
+ 'layout_to_override: %s, layout: %s' % (
+ sorted(common_nums),
+ [part.get('num') for part in layout_to_override],
+ [part.get('num') for part in layout]))
+
+ # Merge layouts with the partitions in the same order they are in both
+ # layouts.
+ part_index = 0
+ for part_to_apply in layout:
+ num = part_to_apply.get('num')
+
+ if part_index == len(layout_to_override):
+ # The part_to_apply is past the list of partitions to override, this
+ # means that is a new partition added at the end.
+ # Need of deepcopy, in case we change layout later.
+ layout_to_override.append(copy.deepcopy(part_to_apply))
+ elif layout_to_override[part_index].get('num') is None and num is None:
+ # Allow modifying gaps after a partition.
+ # TODO(deymo): Drop support for "gap" partitions and use alignment
+ # instead.
+ layout_to_override[part_index].update(part_to_apply)
+ elif num in common_nums:
+ while layout_to_override[part_index].get('num') != num:
+ part_index += 1
+ layout_to_override[part_index].update(part_to_apply)
+ else:
+ # Need of deepcopy, in case we change layout later.
+ layout_to_override.insert(part_index, copy.deepcopy(part_to_apply))
+ part_index += 1
+
+
+def LoadJSONWithComments(filename):
+ """Loads a JSON file ignoring lines with comments.
+
+ RFC 7159 doesn't allow comments on the file JSON format. This functions loads
+ a JSON file removing all the comment lines. A comment line is any line
+ starting with # and optionally indented with whitespaces. Note that inline
+ comments are not supported.
+
+ Args:
+ filename: The input filename.
+
+ Returns:
+ The parsed JSON object.
+ """
+ regex = re.compile(r'^\s*#.*')
+ with open(filename) as f:
+ source = ''.join(regex.sub('', line) for line in f)
+ return json.loads(source)
+
+
+def _LoadStackedPartitionConfig(filename):
+ """Loads a partition table and its possible parent tables.
+
+ This does very little validation. It's just enough to walk all of the parent
+ files and merges them with the current config. Overall validation is left to
+ the caller.
+
+ Args:
+ filename: Filename to load into object.
+
+ Returns:
+ Object containing disk layout configuration
+ """
+ if not os.path.exists(filename):
+ raise ConfigNotFound('Partition config %s was not found!' % filename)
+ config = LoadJSONWithComments(filename)
+
+ # Let's first apply our new configs onto base.
+ common_layout = config['layouts'].setdefault(COMMON_LAYOUT, [])
+ for layout_name, layout in config['layouts'].iteritems():
+ # Don't apply on yourself.
+ if layout_name == COMMON_LAYOUT or layout_name == '_comment':
+ continue
+
+ # Need to copy a list of dicts so make a deep copy.
+ working_layout = copy.deepcopy(common_layout)
+ _ApplyLayoutOverrides(working_layout, layout)
+ config['layouts'][layout_name] = working_layout
+
+ dirname = os.path.dirname(filename)
+ # Now let's inherit the values from all our parents.
+ for parent in config.get('parent', '').split():
+ parent_filename = os.path.join(dirname, parent)
+ if not os.path.exists(parent_filename):
+ # Try loading the parent file from the cgpt.py directory (global config).
+ parent_filename = os.path.join(os.path.join(os.path.dirname(__file__),
+ parent))
+ parent_config = _LoadStackedPartitionConfig(parent_filename)
+
+ # First if the parent is missing any fields the new config has, fill them
+ # in.
+ for key in config.keys():
+ if key == 'parent':
+ continue
+ elif key == 'metadata':
+ # We handle this especially to allow for inner metadata fields to be
+ # added / modified.
+ parent_config.setdefault(key, {})
+ parent_config[key].update(config[key])
+ else:
+ parent_config.setdefault(key, config[key])
+
+ # The overrides work by taking the parent_config, apply the new config
+ # layout info, and return the resulting config which is stored in the parent
+ # config.
+
+ # So there's an issue where an inheriting layout file may contain new
+ # layouts not previously defined in the parent layout. Since we are
+ # building these layout files based on the parent configs and overriding
+ # new values, we first add the new layouts not previously defined in the
+ # parent config using a copy of the base layout from that parent config.
+ parent_layouts = set(parent_config['layouts'])
+ config_layouts = set(config['layouts'])
+ new_layouts = config_layouts - parent_layouts
+
+ # Actually add the copy. Use a copy such that each is unique.
+ parent_cmn_layout = parent_config['layouts'].setdefault(COMMON_LAYOUT, [])
+ for layout_name in new_layouts:
+ parent_config['layouts'][layout_name] = copy.deepcopy(parent_cmn_layout)
+
+ # Iterate through each layout in the parent config and apply the new layout.
+ common_layout = config['layouts'].setdefault(COMMON_LAYOUT, [])
+ for layout_name, parent_layout in parent_config['layouts'].iteritems():
+ if layout_name == '_comment':
+ continue
+
+ layout_override = config['layouts'].setdefault(layout_name, [])
+ if layout_name != COMMON_LAYOUT:
+ _ApplyLayoutOverrides(parent_layout, common_layout)
+
+ _ApplyLayoutOverrides(parent_layout, layout_override)
+
+ config = parent_config
+
+ config.pop('parent', None)
+ return config
+
+
+def LoadPartitionConfig(filename):
+ """Loads a partition tables configuration file into a Python object.
+
+ Args:
+ filename: Filename to load into object
+
+ Returns:
+ Object containing disk layout configuration
+ """
+
+ valid_keys = set(('_comment', 'metadata', 'layouts', 'parent'))
+ valid_layout_keys = set((
+ '_comment', 'num', 'blocks', 'block_size', 'fs_blocks', 'fs_block_size',
+ 'uuid', 'label', 'format', 'fs_format', 'type', 'features',
+ 'size', 'fs_size', 'fs_options', 'erase_block_size', 'hybrid_mbr',
+ 'reserved_erase_blocks', 'max_bad_erase_blocks', 'external_gpt',
+ 'page_size', 'size_min', 'fs_size_min'))
+ valid_features = set(('expand',))
+
+ config = _LoadStackedPartitionConfig(filename)
+ try:
+ metadata = config['metadata']
+ for key in ('block_size', 'fs_block_size'):
+ metadata[key] = ParseHumanNumber(metadata[key])
+
+ unknown_keys = set(config.keys()) - valid_keys
+ if unknown_keys:
+ raise InvalidLayout('Unknown items: %r' % unknown_keys)
+
+ if len(config['layouts']) <= 0:
+ raise InvalidLayout('Missing "layouts" entries')
+
+ if not BASE_LAYOUT in config['layouts'].keys():
+ raise InvalidLayout('Missing "base" config in "layouts"')
+
+ for layout_name, layout in config['layouts'].iteritems():
+ if layout_name == '_comment':
+ continue
+
+ for part in layout:
+ unknown_keys = set(part.keys()) - valid_layout_keys
+ if unknown_keys:
+ raise InvalidLayout('Unknown items in layout %s: %r' %
+ (layout_name, unknown_keys))
+
+ if part.get('num') == 'metadata' and 'type' not in part:
+ part['type'] = 'blank'
+
+ if part['type'] != 'blank':
+ for s in ('num', 'label'):
+ if not s in part:
+ raise InvalidLayout('Layout "%s" missing "%s"' % (layout_name, s))
+
+ if 'size' in part:
+ if 'blocks' in part:
+ raise ConflictingOptions(
+ '%s: Conflicting settings are used. '
+ 'Found section sets both \'blocks\' and \'size\'.' %
+ part['label'])
+ part['bytes'] = ParseHumanNumber(part['size'])
+ if 'size_min' in part:
+ size_min = ParseHumanNumber(part['size_min'])
+ if part['bytes'] < size_min:
+ part['bytes'] = size_min
+ part['blocks'] = part['bytes'] / metadata['block_size']
+
+ if part['bytes'] % metadata['block_size'] != 0:
+ raise InvalidSize(
+ 'Size: "%s" (%s bytes) is not an even number of block_size: %s'
+ % (part['size'], part['bytes'], metadata['block_size']))
+
+ if 'fs_size' in part:
+ part['fs_bytes'] = ParseHumanNumber(part['fs_size'])
+ if 'fs_size_min' in part:
+ fs_size_min = ParseHumanNumber(part['fs_size_min'])
+ if part['fs_bytes'] < fs_size_min:
+ part['fs_bytes'] = fs_size_min
+ if part['fs_bytes'] <= 0:
+ raise InvalidSize(
+ 'File system size "%s" must be positive' %
+ part['fs_size'])
+ if part['fs_bytes'] > part['bytes']:
+ raise InvalidSize(
+ 'Filesystem may not be larger than partition: %s %s: %d > %d' %
+ (layout_name, part['label'], part['fs_bytes'], part['bytes']))
+ if part['fs_bytes'] % metadata['fs_block_size'] != 0:
+ raise InvalidSize(
+ 'File system size: "%s" (%s bytes) is not an even number of '
+ 'fs blocks: %s' %
+ (part['fs_size'], part['fs_bytes'], metadata['fs_block_size']))
+ if part.get('format') == 'ubi':
+ part_meta = GetMetadataPartition(layout)
+ page_size = ParseHumanNumber(part_meta['page_size'])
+ eb_size = ParseHumanNumber(part_meta['erase_block_size'])
+ ubi_eb_size = eb_size - 2 * page_size
+ if (part['fs_bytes'] % ubi_eb_size) != 0:
+ # Trim fs_bytes to multiple of UBI eraseblock size.
+ fs_bytes = part['fs_bytes'] - (part['fs_bytes'] % ubi_eb_size)
+ raise InvalidSize(
+ 'File system size: "%s" (%d bytes) is not a multiple of UBI '
+ 'erase block size (%d). Please set "fs_size" to "%s" in the '
+ '"common" layout instead.' %
+ (part['fs_size'], part['fs_bytes'], ubi_eb_size,
+ ProduceHumanNumber(fs_bytes)))
+
+ if 'blocks' in part:
+ part['blocks'] = ParseHumanNumber(part['blocks'])
+ part['bytes'] = part['blocks'] * metadata['block_size']
+
+ if 'fs_blocks' in part:
+ max_fs_blocks = part['bytes'] / metadata['fs_block_size']
+ part['fs_blocks'] = ParseRelativeNumber(max_fs_blocks,
+ part['fs_blocks'])
+ part['fs_bytes'] = part['fs_blocks'] * metadata['fs_block_size']
+
+ if part['fs_bytes'] > part['bytes']:
+ raise InvalidLayout(
+ 'Filesystem may not be larger than partition: %s %s: %d > %d' %
+ (layout_name, part['label'], part['fs_bytes'], part['bytes']))
+ if 'erase_block_size' in part:
+ part['erase_block_size'] = ParseHumanNumber(part['erase_block_size'])
+ if 'page_size' in part:
+ part['page_size'] = ParseHumanNumber(part['page_size'])
+
+ part.setdefault('features', [])
+ unknown_features = set(part['features']) - valid_features
+ if unknown_features:
+ raise InvalidLayout('%s: Unknown features: %s' %
+ (part['label'], unknown_features))
+ except KeyError as e:
+ raise InvalidLayout('Layout is missing required entries: %s' % e)
+
+ return config
+
+
+def _GetPrimaryEntryArrayLBA(config):
+ """Return the start LBA of the primary partition entry array.
+
+ Normally this comes after the primary GPT header but can be adjusted by
+ setting the "primary_entry_array_lba" key under "metadata" in the config.
+
+ Args:
+ config: The config dictionary.
+
+ Returns:
+ The position of the primary partition entry array.
+ """
+
+ pmbr_and_header_size = SIZE_OF_PMBR + SIZE_OF_GPT_HEADER
+ entry_array = config['metadata'].get('primary_entry_array_lba',
+ pmbr_and_header_size)
+ if entry_array < pmbr_and_header_size:
+ raise InvalidLayout('Primary entry array (%d) must be at least %d.' %
+ entry_array, pmbr_and_header_size)
+ return entry_array
+
+
+def _HasBadEraseBlocks(partitions):
+ return 'max_bad_erase_blocks' in GetMetadataPartition(partitions)
+
+
+def _HasExternalGpt(partitions):
+ return GetMetadataPartition(partitions).get('external_gpt', False)
+
+
+def _GetStartSector(config, partitions):
+ """Return the first usable location (LBA) for partitions.
+
+ This value is the first LBA after the PMBR, the primary GPT header, and
+ partition entry array.
+
+ We round it up to 64 to maintain the same layout as before in the normal (no
+ padding between the primary GPT header and its partition entry array) case.
+
+ Args:
+ config: The config dictionary.
+ partitions: List of partitions to process
+
+ Returns:
+ A suitable LBA for partitions, at least 64.
+ """
+
+ if _HasExternalGpt(partitions):
+ # If the GPT is external, then the offset of the partitions' actual data
+ # will be 0, and we don't need to make space at the beginning for the GPT.
+ return 0
+ else:
+ entry_array = _GetPrimaryEntryArrayLBA(config)
+ start_sector = max(entry_array + SIZE_OF_PARTITION_ENTRY_ARRAY, 64)
+ return start_sector
+
+
+def GetTableTotals(config, partitions):
+ """Calculates total sizes/counts for a partition table.
+
+ Args:
+ config: Partition configuration file object
+ partitions: List of partitions to process
+
+ Returns:
+ Dict containing totals data
+ """
+
+ start_sector = _GetStartSector(config, partitions)
+ ret = {
+ 'expand_count': 0,
+ 'expand_min': 0,
+ 'block_count': start_sector * config['metadata']['block_size']
+ }
+
+ # Total up the size of all non-expanding partitions to get the minimum
+ # required disk size.
+ for partition in partitions:
+ if partition.get('num') == 'metadata':
+ continue
+ if 'expand' in partition['features']:
+ ret['expand_count'] += 1
+ ret['expand_min'] += partition['blocks']
+ else:
+ ret['block_count'] += partition['blocks']
+
+ # At present, only one expanding partition is permitted.
+ # Whilst it'd be possible to have two, we don't need this yet
+ # and it complicates things, so it's been left out for now.
+ if ret['expand_count'] > 1:
+ raise InvalidLayout('1 expand partition allowed, %d requested'
+ % ret['expand_count'])
+
+ ret['min_disk_size'] = ret['block_count'] + ret['expand_min']
+
+ return ret
+
+
+def GetPartitionTable(options, config, image_type):
+ """Generates requested image_type layout from a layout configuration.
+
+ This loads the base table and then overlays the requested layout over
+ the base layout.
+
+ Args:
+ options: Flags passed to the script
+ config: Partition configuration file object
+ image_type: Type of image eg base/test/dev/factory_install
+
+ Returns:
+ Object representing a selected partition table
+ """
+
+ # We make a deep copy so that changes to the dictionaries in this list do not
+ # persist across calls.
+ partitions = copy.deepcopy(config['layouts'][image_type])
+ metadata = config['metadata']
+
+ # Convert fs_options to a string.
+ for partition in partitions:
+ fs_options = partition.get('fs_options', '')
+ if isinstance(fs_options, dict):
+ fs_format = partition.get('fs_format')
+ fs_options = fs_options.get(fs_format, '')
+ elif not isinstance(fs_options, basestring):
+ raise InvalidLayout('Partition number %s: fs_format must be a string or '
+ 'dict, not %s' % (partition.get('num'),
+ type(fs_options)))
+ if '"' in fs_options or "'" in fs_options:
+ raise InvalidLayout('Partition number %s: fs_format cannot have quotes' %
+ partition.get('num'))
+ partition['fs_options'] = fs_options
+
+ for adjustment_str in options.adjust_part.split():
+ adjustment = adjustment_str.split(':')
+ if len(adjustment) < 2:
+ raise InvalidAdjustment('Adjustment "%s" is incomplete' % adjustment_str)
+
+ label = adjustment[0]
+ operator = adjustment[1][0]
+ operand = adjustment[1][1:]
+ ApplyPartitionAdjustment(partitions, metadata, label, operator, operand)
+
+ return partitions
+
+
+def ApplyPartitionAdjustment(partitions, metadata, label, operator, operand):
+ """Applies an adjustment to a partition specified by label
+
+ Args:
+ partitions: Partition table to modify
+ metadata: Partition table metadata
+ label: The label of the partition to adjust
+ operator: Type of adjustment (+/-/=)
+ operand: How much to adjust by
+ """
+
+ partition = GetPartitionByLabel(partitions, label)
+
+ operand_bytes = ParseHumanNumber(operand)
+ if operand_bytes % metadata['block_size'] == 0:
+ operand_blocks = operand_bytes / metadata['block_size']
+ else:
+ raise InvalidAdjustment('Adjustment size %s not divisible by block size %s'
+ % (operand_bytes, metadata['block_size']))
+
+ if operator == '+':
+ partition['blocks'] += operand_blocks
+ partition['bytes'] += operand_bytes
+ elif operator == '-':
+ partition['blocks'] -= operand_blocks
+ partition['bytes'] -= operand_bytes
+ elif operator == '=':
+ partition['blocks'] = operand_blocks
+ partition['bytes'] = operand_bytes
+ else:
+ raise ValueError('unknown operator %s' % operator)
+
+ if partition['type'] == 'rootfs':
+ # If we're adjusting a rootFS partition, we assume the full partition size
+ # specified is being used for the filesytem, minus the space reserved for
+ # the hashpad.
+ partition['fs_bytes'] = partition['bytes']
+ partition['fs_blocks'] = partition['fs_bytes'] / metadata['fs_block_size']
+ partition['blocks'] = int(partition['blocks'] * 1.15)
+ partition['bytes'] = partition['blocks'] * metadata['block_size']
+
+
+def GetPartitionTableFromConfig(options, layout_filename, image_type):
+ """Loads a partition table and returns a given partition table type
+
+ Args:
+ options: Flags passed to the script
+ layout_filename: The filename to load tables from
+ image_type: The type of partition table to return
+ """
+
+ config = LoadPartitionConfig(layout_filename)
+ partitions = GetPartitionTable(options, config, image_type)
+
+ return partitions
+
+
+def GetScriptShell():
+ """Loads and returns the skeleton script for our output script.
+
+ Returns:
+ A string containing the skeleton script
+ """
+
+ script_shell_path = os.path.join(os.path.dirname(__file__), 'cgpt_shell.sh')
+ with open(script_shell_path, 'r') as f:
+ script_shell = ''.join(f.readlines())
+
+ # Before we return, insert the path to this tool so somebody reading the
+ # script later can tell where it was generated.
+ script_shell = script_shell.replace('@SCRIPT_GENERATOR@', script_shell_path)
+
+ return script_shell
+
+
+def GetFullPartitionSize(partition, metadata):
+ """Get the size of the partition including metadata/reserved space in bytes.
+
+ The partition only has to be bigger for raw NAND devices. Formula:
+ - Add UBI per-block metadata (2 pages) if partition is UBI
+ - Round up to erase block size
+ - Add UBI per-partition metadata (4 blocks) if partition is UBI
+ - Add reserved erase blocks
+ """
+
+ erase_block_size = metadata.get('erase_block_size', 0)
+ size = partition['bytes']
+
+ if erase_block_size == 0:
+ return size
+
+ # See "Flash space overhead" in
+ # http://www.linux-mtd.infradead.org/doc/ubi.html
+ # for overhead calculations.
+ is_ubi = partition.get('format') == 'ubi'
+ reserved_erase_blocks = partition.get('reserved_erase_blocks', 0)
+ page_size = metadata.get('page_size', 0)
+
+ if is_ubi:
+ ubi_block_size = erase_block_size - 2 * page_size
+ erase_blocks = (size + ubi_block_size - 1) // ubi_block_size
+ size += erase_blocks * 2 * page_size
+
+ erase_blocks = (size + erase_block_size - 1) // erase_block_size
+ size = erase_blocks * erase_block_size
+
+ if is_ubi:
+ size += erase_block_size * 4
+
+ size += reserved_erase_blocks * erase_block_size
+ return size
+
+
+def WriteLayoutFunction(options, sfile, func, image_type, config):
+ """Writes a shell script function to write out a given partition table.
+
+ Args:
+ options: Flags passed to the script
+ sfile: File handle we're writing to
+ func: function of the layout:
+ for removable storage device: 'partition',
+ for the fixed storage device: 'base'
+ image_type: Type of image eg base/test/dev/factory_install
+ config: Partition configuration file object
+ """
+
+ partitions = GetPartitionTable(options, config, image_type)
+ metadata = GetMetadataPartition(partitions)
+ partition_totals = GetTableTotals(config, partitions)
+
+ lines = [
+ 'write_%s_table() {' % func,
+ ]
+
+ if _HasExternalGpt(partitions):
+ # Read GPT from device to get size, then wipe it out and operate
+ # on GPT in tmpfs. We don't rely on cgpt's ability to deal
+ # directly with the GPT on SPI NOR flash because rewriting the
+ # table so many times would take a long time (>30min).
+ # Also, wiping out the previous GPT with create_image won't work
+ # for NAND and there's no equivalent via cgpt.
+ lines += [
+ 'gptfile=$(mktemp)',
+ 'flashrom -r -iRW_GPT:${gptfile}',
+ 'gptsize=$(stat ${gptfile} --format %s)',
+ 'dd if=/dev/zero of=${gptfile} bs=${gptsize} count=1',
+ 'target="-D %d ${gptfile}"' % metadata['bytes'],
+ ]
+ else:
+ lines += [
+ 'local target="$1"',
+ 'create_image "${target}" %d %s' % (
+ partition_totals['min_disk_size'],
+ config['metadata']['block_size']),
+ ]
+
+ # ${target} is referenced unquoted because it may expand into multiple
+ # arguments in the case of NAND
+ lines += [
+ 'local curr=%d' % _GetStartSector(config, partitions),
+ '# Create the GPT headers and tables. Pad the primary ones.',
+ './cgpt create -p %d ${target}' % (_GetPrimaryEntryArrayLBA(config) -
+ (SIZE_OF_PMBR + SIZE_OF_GPT_HEADER)),
+ ]
+
+ metadata = GetMetadataPartition(partitions)
+ # Pass 1: Set up the expanding partition size.
+ for partition in partitions:
+ if partition.get('num') == 'metadata':
+ continue
+ partition['var'] = (GetFullPartitionSize(partition, metadata) /
+ config['metadata']['block_size'])
+
+ if (partition.get('type') != 'blank' and partition['num'] == 1 and
+ 'expand' in partition['features']):
+ lines += [
+ 'local stateful_size=%s' % partition['blocks'],
+ 'if [ -b "${target}" ]; then',
+ ' stateful_size=$(( $(numsectors "${target}") - %d))' % (
+ partition_totals['block_count']),
+ 'fi',
+ ': $(( stateful_size -= (stateful_size %% %d) ))' % (
+ config['metadata']['fs_block_size']),
+ ]
+ partition['var'] = '${stateful_size}'
+
+ # Pass 2: Write out all the cgpt add commands.
+ for partition in partitions:
+ if partition.get('num') == 'metadata':
+ continue
+ if partition['type'] != 'blank':
+ lines += [
+ './cgpt add -i %d -b ${curr} -s %s -t %s -l "%s" ${target}' % (
+ partition['num'], str(partition['var']), partition['type'],
+ partition['label']),
+ ]
+
+ # Increment the curr counter ready for the next partition.
+ if partition['var'] != 0 and partition.get('num') != 'metadata':
+ lines += [
+ ': $(( curr += %s ))' % partition['var'],
+ ]
+
+ # Set default priorities and retry counter on kernel partitions.
+ tries = 15
+ prio = 15
+ # The order of partition numbers in this loop matters.
+ # Make sure partition #2 is the first one, since it will be marked as
+ # default bootable partition.
+ for partition in GetPartitionsByType(partitions, 'kernel'):
+ lines += [
+ './cgpt add -i %s -S 0 -T %i -P %i ${target}' %
+ (partition['num'], tries, prio)
+ ]
+ prio = 0
+ # When not writing 'base' function, make sure the other partitions are
+ # marked as non-bootable (retry count == 0), since the USB layout
+ # doesn't have any valid data in slots B & C. But with base function,
+ # called by chromeos-install script, the KERNEL A partition is replicated
+ # into both slots A & B, so we should leave both bootable for error
+ # recovery in this case.
+ if func != 'base':
+ tries = 0
+
+ efi_partitions = GetPartitionsByType(partitions, 'efi')
+ if efi_partitions:
+ lines += [
+ './cgpt boot -p -b $2 -i %d ${target}' % efi_partitions[0]['num'],
+ './cgpt add -i %s -B 1 ${target}' % efi_partitions[0]['num'],
+ ]
+ else:
+ # Provide a PMBR all the time for boot loaders (like u-boot)
+ # that expect one to always be there.
+ lines += [
+ './cgpt boot -p -b $2 ${target}',
+ ]
+
+ if metadata.get('hybrid_mbr'):
+ lines += ['install_hybrid_mbr ${target}']
+ lines += ['./cgpt show ${target}']
+
+ if _HasExternalGpt(partitions):
+ lines += ['flashrom -w -iRW_GPT:${gptfile} --fast-verify']
+
+ sfile.write('%s\n}\n' % '\n '.join(lines))
+
+
+def WritePartitionSizesFunction(options, sfile, func, image_type, config):
+ """Writes out the partition size variable that can be extracted by a caller.
+
+ Args:
+ options: Flags passed to the script
+ sfile: File handle we're writing to
+ func: function of the layout:
+ for removable storage device: 'partition',
+ for the fixed storage device: 'base'
+ image_type: Type of image eg base/test/dev/factory_install
+ config: Partition configuration file object
+ """
+ func_name = 'load_%s_vars' % func
+ lines = [
+ '%s() {' % func_name,
+ 'DEFAULT_ROOTDEV="%s"' % config['metadata'].get('rootdev_%s' % func, ''),
+ ]
+
+ partitions = GetPartitionTable(options, config, image_type)
+ for partition in partitions:
+ if partition.get('num') == 'metadata':
+ continue
+ for key in ('label', 'num'):
+ if key in partition:
+ shell_label = str(partition[key]).replace('-', '_').upper()
+ part_bytes = partition['bytes']
+ reserved_ebs = partition.get('reserved_erase_blocks', 0)
+ fs_bytes = partition.get('fs_bytes', part_bytes)
+ part_format = partition.get('format', '')
+ fs_format = partition.get('fs_format', '')
+ fs_options = partition.get('fs_options', '')
+ partition_num = partition.get('num', '')
+ lines += [
+ 'PARTITION_SIZE_%s=%s' % (shell_label, part_bytes),
+ ' RESERVED_EBS_%s=%s' % (shell_label, reserved_ebs),
+ ' DATA_SIZE_%s=%s' % (shell_label, fs_bytes),
+ ' FORMAT_%s=%s' % (shell_label, part_format),
+ ' FS_FORMAT_%s=%s' % (shell_label, fs_format),
+ ' FS_OPTIONS_%s="%s"' % (shell_label, fs_options),
+ ' PARTITION_NUM_%s="%s"' % (shell_label, partition_num),
+ ]
+
+ sfile.write('%s\n}\n' % '\n '.join(lines))
+
+
+def GetPartitionByNumber(partitions, num):
+ """Given a partition table and number returns the partition object.
+
+ Args:
+ partitions: List of partitions to search in
+ num: Number of partition to find
+
+ Returns:
+ An object for the selected partition
+ """
+ for partition in partitions:
+ if partition.get('num') == int(num):
+ return partition
+
+ raise PartitionNotFound('Partition %s not found' % num)
+
+
+def GetPartitionsByType(partitions, typename):
+ """Given a partition table and type returns the partitions of the type.
+
+ Partitions are sorted in num order.
+
+ Args:
+ partitions: List of partitions to search in
+ typename: The type of partitions to select
+
+ Returns:
+ A list of partitions of the type
+ """
+ out = []
+ for partition in partitions:
+ if partition.get('type') == typename:
+ out.append(partition)
+ return sorted(out, key=lambda partition: partition.get('num'))
+
+
+def GetMetadataPartition(partitions):
+ """Given a partition table returns the metadata partition object.
+
+ Args:
+ partitions: List of partitions to search in
+
+ Returns:
+ An object for the metadata partition
+ """
+ for partition in partitions:
+ if partition.get('num') == 'metadata':
+ return partition
+
+ return {}
+
+
+def GetPartitionByLabel(partitions, label):
+ """Given a partition table and label returns the partition object.
+
+ Args:
+ partitions: List of partitions to search in
+ label: Label of partition to find
+
+ Returns:
+ An object for the selected partition
+ """
+ for partition in partitions:
+ if 'label' not in partition:
+ continue
+ if partition['label'] == label:
+ return partition
+
+ raise PartitionNotFound('Partition "%s" not found' % label)
+
+
+def WritePartitionScript(options, image_type, layout_filename, sfilename):
+ """Writes a shell script with functions for the base and requested layouts.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ sfilename: Filename to write the finished script to
+ """
+ config = LoadPartitionConfig(layout_filename)
+
+ with open(sfilename, 'w') as f:
+ script_shell = GetScriptShell()
+ f.write(script_shell)
+
+ for func, layout in (('base', BASE_LAYOUT), ('partition', image_type)):
+ WriteLayoutFunction(options, f, func, layout, config)
+ WritePartitionSizesFunction(options, f, func, layout, config)
+
+ # TODO: Backwards compat. Should be killed off once we update
+ # cros_generate_update_payload to use the new code.
+ partitions = GetPartitionTable(options, config, BASE_LAYOUT)
+ partition = GetPartitionByLabel(partitions, 'ROOT-A')
+ f.write('ROOTFS_PARTITION_SIZE=%s\n' % (partition['bytes'],))
+
+
+def GetBlockSize(_options, layout_filename):
+ """Returns the partition table block size.
+
+ Args:
+ options: Flags passed to the script
+ layout_filename: Path to partition configuration file
+
+ Returns:
+ Block size of all partitions in the layout
+ """
+
+ config = LoadPartitionConfig(layout_filename)
+ return config['metadata']['block_size']
+
+
+def GetFilesystemBlockSize(_options, layout_filename):
+ """Returns the filesystem block size.
+
+ This is used for all partitions in the table that have filesystems.
+
+ Args:
+ options: Flags passed to the script
+ layout_filename: Path to partition configuration file
+
+ Returns:
+ Block size of all filesystems in the layout
+ """
+
+ config = LoadPartitionConfig(layout_filename)
+ return config['metadata']['fs_block_size']
+
+
+def GetImageTypes(_options, layout_filename):
+ """Returns a list of all the image types in the layout.
+
+ Args:
+ options: Flags passed to the script
+ layout_filename: Path to partition configuration file
+
+ Returns:
+ List of all image types
+ """
+
+ config = LoadPartitionConfig(layout_filename)
+ return ' '.join(config['layouts'].keys())
+
+
+def GetType(options, image_type, layout_filename, num):
+ """Returns the type of a given partition for a given layout.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Type of the specified partition.
+ """
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+ return partition.get('type')
+
+
+def GetPartitions(options, image_type, layout_filename):
+ """Returns the partition numbers for the image_type.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+
+ Returns:
+ A space delimited string of partition numbers.
+ """
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ return ' '.join(str(p['num']) for p in partitions
+ if 'num' in p and p['num'] != 'metadata')
+
+
+def GetUUID(options, image_type, layout_filename, num):
+ """Returns the filesystem UUID of a given partition for a given layout type.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ UUID of specified partition. Defaults to random if not set.
+ """
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+ return partition.get('uuid', 'random')
+
+
+def GetPartitionSize(options, image_type, layout_filename, num):
+ """Returns the partition size of a given partition for a given layout type.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Size of selected partition in bytes
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+
+ return partition['bytes']
+
+
+def GetFilesystemFormat(options, image_type, layout_filename, num):
+ """Returns the filesystem format of a given partition for a given layout type.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Format of the selected partition's filesystem
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+
+ return partition.get('fs_format')
+
+
+def GetFormat(options, image_type, layout_filename, num):
+ """Returns the format of a given partition for a given layout type.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Format of the selected partition's filesystem
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+
+ return partition.get('format')
+
+
+def GetFilesystemOptions(options, image_type, layout_filename, num):
+ """Returns the filesystem options of a given partition and layout type.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ The selected partition's filesystem options
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+
+ return partition.get('fs_options')
+
+
+def GetFilesystemSize(options, image_type, layout_filename, num):
+ """Returns the filesystem size of a given partition for a given layout type.
+
+ If no filesystem size is specified, returns the partition size.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Size of selected partition filesystem in bytes
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+
+ if 'fs_bytes' in partition:
+ return partition['fs_bytes']
+ else:
+ return partition['bytes']
+
+
+def GetLabel(options, image_type, layout_filename, num):
+ """Returns the label for a given partition.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Label of selected partition, or 'UNTITLED' if none specified
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+
+ if 'label' in partition:
+ return partition['label']
+ else:
+ return 'UNTITLED'
+
+
+def GetNumber(options, image_type, layout_filename, label):
+ """Returns the partition number of a given label.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ label: Number of the partition you want to read from
+
+ Returns:
+ The number of the partition corresponding to the label.
+ """
+
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByLabel(partitions, label)
+ return partition['num']
+
+
+def GetReservedEraseBlocks(options, image_type, layout_filename, num):
+ """Returns the number of erase blocks reserved in the partition.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ num: Number of the partition you want to read from
+
+ Returns:
+ Number of reserved erase blocks
+ """
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ partition = GetPartitionByNumber(partitions, num)
+ if 'reserved_erase_blocks' in partition:
+ return partition['reserved_erase_blocks']
+ else:
+ return 0
+
+
+def DoDebugOutput(options, image_type, layout_filename):
+ """Prints out a human readable disk layout in on-disk order.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ """
+ config = LoadPartitionConfig(layout_filename)
+ partitions = GetPartitionTable(options, config, image_type)
+
+ label_len = max([len(x['label']) for x in partitions if 'label' in x])
+ type_len = max([len(x['type']) for x in partitions if 'type' in x])
+
+ msg = 'num:%4s label:%-*s type:%-*s size:%-10s fs_size:%-10s features:%s'
+
+ # Print out non-layout options first.
+ print('Config Data')
+ metadata_msg = 'field:%-14s value:%s'
+ for key in config.keys():
+ if key not in ('layouts', '_comment'):
+ print(metadata_msg % (key, config[key]))
+
+ print('\n%s Layout Data' % image_type.upper())
+ for partition in partitions:
+ if partition.get('num') == 'metadata':
+ continue
+
+ size = ProduceHumanNumber(partition['bytes'])
+ if 'fs_bytes' in partition.iterkeys():
+ fs_size = ProduceHumanNumber(partition['fs_bytes'])
+ else:
+ fs_size = 'auto'
+
+ print(msg % (
+ partition.get('num', 'auto'),
+ label_len,
+ partition.get('label', ''),
+ type_len,
+ partition.get('type', ''),
+ size,
+ fs_size,
+ partition.get('features', []),
+ ))
+
+
+def CheckRootfsPartitionsMatch(partitions):
+ """Checks that rootfs partitions are substitutable with each other.
+
+ This function asserts that either all rootfs partitions are in the same format
+ or none have a format, and it asserts that have the same number of reserved
+ erase blocks.
+ """
+ partition_format = None
+ reserved_erase_blocks = -1
+ for partition in partitions:
+ if partition.get('type') == 'rootfs':
+ new_format = partition.get('format', '')
+ new_reserved_erase_blocks = partition.get('reserved_erase_blocks', 0)
+
+ if partition_format is None:
+ partition_format = new_format
+ reserved_erase_blocks = new_reserved_erase_blocks
+
+ if new_format != partition_format:
+ raise MismatchedRootfsFormat(
+ 'mismatched rootfs formats: "%s" and "%s"' %
+ (partition_format, new_format))
+
+ if reserved_erase_blocks != new_reserved_erase_blocks:
+ raise MismatchedRootfsBlocks(
+ 'mismatched rootfs reserved erase block counts: %s and %s' %
+ (reserved_erase_blocks, new_reserved_erase_blocks))
+
+
+def Combinations(n, k):
+ """Calculate the binomial coefficient, i.e., "n choose k"
+
+ This calculates the number of ways that k items can be chosen from
+ a set of size n. For example, if there are n blocks and k of them
+ are bad, then this returns the number of ways that the bad blocks
+ can be distributed over the device.
+ See http://en.wikipedia.org/wiki/Binomial_coefficient
+
+ For convenience to the caller, this function allows impossible cases
+ as input and returns 0 for them.
+ """
+ if k < 0 or n < k:
+ return 0
+ return math.factorial(n) / (math.factorial(k) * math.factorial(n - k))
+
+
+def CheckReservedEraseBlocks(partitions):
+ """Checks that the reserved_erase_blocks in each partition is good.
+
+ This function checks that a reasonable value was given for the reserved
+ erase block count. In particular, it checks that there's a less than
+ 1 in 100k probability that, if the manufacturer's maximum bad erase
+ block count is met, and assuming bad blocks are uniformly randomly
+ distributed, then more bad blocks will fall in this partition than are
+ reserved. Smaller partitions need a larger reserve percentage.
+
+ We take the number of reserved blocks as a parameter in disk_layout.json
+ rather than just calculating the value so that it can be tweaked
+ explicitly along with others in squeezing the image onto flash. But
+ we check it so that users have an easy method for determining what's
+ acceptable--just try out a new value and do ./build_image.
+ """
+ for partition in partitions:
+ if ('reserved_erase_blocks' in partition or
+ partition.get('format') in ('ubi', 'nand')):
+ if partition.get('bytes', 0) == 0:
+ continue
+ metadata = GetMetadataPartition(partitions)
+ if (not _HasBadEraseBlocks(partitions)
+ or 'reserved_erase_blocks' not in partition
+ or 'bytes' not in metadata
+ or 'erase_block_size' not in metadata
+ or 'page_size' not in metadata):
+ raise MissingEraseBlockField(
+ 'unable to check if partition %s will have too many bad blocks due '
+ 'to missing metadata field' % partition['label'])
+
+ reserved = partition['reserved_erase_blocks']
+ erase_block_size = metadata['erase_block_size']
+ device_erase_blocks = metadata['bytes'] / erase_block_size
+ device_bad_blocks = metadata['max_bad_erase_blocks']
+ distributions = Combinations(device_erase_blocks, device_bad_blocks)
+ partition_erase_blocks = partition['bytes'] / erase_block_size
+ # The idea is to calculate the number of ways that there could be reserved
+ # or more bad blocks inside the partition, assuming that there are
+ # device_bad_blocks in the device in total (the worst case). To get the
+ # probability, we divide this count by the total number of ways that the
+ # bad blocks can be distributed on the whole device. To find the first
+ # number, we sum over increasing values for the count of bad blocks within
+ # the partition the number of ways that those bad blocks can be inside the
+ # partition, multiplied by the number of ways that the remaining blocks
+ # can be distributed outside of the partition.
+ ways_for_failure = sum(
+ Combinations(partition_erase_blocks, partition_bad_blocks) *
+ Combinations(device_erase_blocks - partition_erase_blocks,
+ device_bad_blocks - partition_bad_blocks)
+ for partition_bad_blocks
+ in range(reserved + 1, device_bad_blocks + 1))
+ probability = (1.0 * ways_for_failure) / distributions
+ if probability > 0.00001:
+ raise ExcessFailureProbability('excessive probability %f of too many '
+ 'bad blocks in partition %s'
+ % (probability, partition['label']))
+
+
+def CheckSimpleNandProperties(partitions):
+ """Checks that NAND partitions are erase-block-aligned and not expand"""
+ if not _HasBadEraseBlocks(partitions):
+ return
+ metadata = GetMetadataPartition(partitions)
+ for partition in partitions:
+ erase_block_size = metadata['erase_block_size']
+ if partition['bytes'] % erase_block_size != 0:
+ raise UnalignedPartition(
+ 'partition size %s does not divide erase block size %s' %
+ (partition['bytes'], erase_block_size))
+ if 'expand' in partition['features']:
+ raise ExpandNandImpossible(
+ 'expand partitions may not be used with raw NAND')
+
+
+def CheckTotalSize(partitions):
+ """Checks that the sum size of all partitions fits within the device"""
+ metadata = GetMetadataPartition(partitions)
+ if 'bytes' not in metadata:
+ return
+ capacity = metadata['bytes']
+ total = sum(GetFullPartitionSize(partition, metadata)
+ for partition in partitions if partition.get('num') != 'metadata')
+ if total > capacity:
+ raise ExcessPartitionSize('capacity = %d, total=%d' % (capacity, total))
+
+
+def Validate(options, image_type, layout_filename):
+ """Validates a layout file, used before reading sizes to check for errors.
+
+ Args:
+ options: Flags passed to the script
+ image_type: Type of image eg base/test/dev/factory_install
+ layout_filename: Path to partition configuration file
+ """
+ partitions = GetPartitionTableFromConfig(options, layout_filename, image_type)
+ CheckRootfsPartitionsMatch(partitions)
+ CheckTotalSize(partitions)
+ CheckSimpleNandProperties(partitions)
+ CheckReservedEraseBlocks(partitions)
+
+
+def main(argv):
+ action_map = {
+ 'write': {
+ 'usage': ['', '', ''],
+ 'func': WritePartitionScript,
+ },
+ 'readblocksize': {
+ 'usage': [''],
+ 'func': GetBlockSize,
+ },
+ 'readfsblocksize': {
+ 'usage': [''],
+ 'func': GetFilesystemBlockSize,
+ },
+ 'readpartsize': {
+ 'usage': ['', '', ''],
+ 'func': GetPartitionSize,
+ },
+ 'readformat': {
+ 'usage': ['', '', ''],
+ 'func': GetFormat,
+ },
+ 'readfsformat': {
+ 'usage': ['', '', ''],
+ 'func': GetFilesystemFormat,
+ },
+ 'readfssize': {
+ 'usage': ['', '', ''],
+ 'func': GetFilesystemSize,
+ },
+ 'readimagetypes': {
+ 'usage': [''],
+ 'func': GetImageTypes,
+ },
+ 'readfsoptions': {
+ 'usage': ['', '', ''],
+ 'func': GetFilesystemOptions,
+ },
+ 'readlabel': {
+ 'usage': ['', '', ''],
+ 'func': GetLabel,
+ },
+ 'readnumber': {
+ 'usage': ['', '', ''],
+ 'func': GetNumber,
+ },
+ 'readreservederaseblocks': {
+ 'usage': ['', '', ''],
+ 'func': GetReservedEraseBlocks,
+ },
+ 'readtype': {
+ 'usage': ['', '', ''],
+ 'func': GetType,
+ },
+ 'readpartitionnums': {
+ 'usage': ['', ''],
+ 'func': GetPartitions,
+ },
+ 'readuuid': {
+ 'usage': ['', '', ''],
+ 'func': GetUUID,
+ },
+ 'debug': {
+ 'usage': ['', ''],
+ 'func': DoDebugOutput,
+ },
+ 'validate': {
+ 'usage': ['', ''],
+ 'func': Validate,
+ },
+ }
+
+ usage = """%(prog)s [options]
+
+For information on the JSON format, see:
+ http://dev.chromium.org/chromium-os/developer-guide/disk-layout-format
+
+The --adjust_part flag takes arguments like:
+ :
+Where:
+ is a label name as found in the disk layout file
+ is one of the three: + - =
+ is a number followed by an optional size qualifier:
+ B, KiB, MiB, GiB, TiB: bytes, kibi-, mebi-, gibi-, tebi- (base 1024)
+ B, K, M, G, T: short hand for above
+ B, KB, MB, GB, TB: bytes, kilo-, mega-, giga-, tera- (base 1000)
+
+This will set the ROOT-A partition size to 1 gibibytes (1024 * 1024 * 1024 * 1):
+ --adjust_part ROOT-A:=1GiB
+This will grow the ROOT-A partition size by 500 mebibytes (1024 * 1024 * 500):
+ --adjust_part ROOT-A:+500MiB
+This will shrink the ROOT-A partition size by 10 mebibytes (1024 * 1024 * 10):
+ --adjust_part ROOT-A:-20MiB
+
+Actions:
+"""
+
+ action_docs = []
+ for action_name, action in sorted(action_map.iteritems()):
+ doc = action['func'].__doc__.split('\n', 1)[0]
+ action_docs.append(' %s %s\n %s' % (action_name,
+ ' '.join(action['usage']), doc))
+ usage += '\n\n'.join(action_docs)
+
+ parser = argparse.ArgumentParser(usage=usage)
+ parser.add_argument('--adjust_part', metavar='SPEC', default='',
+ help='adjust partition sizes')
+ parser.add_argument('command', choices=sorted(action_map.keys()))
+ parser.add_argument('args', nargs='*')
+ opts = parser.parse_args(argv)
+
+ action = action_map[opts.command]
+ if len(action['usage']) == len(opts.args):
+ ret = action['func'](opts, *opts.args)
+ if ret is not None:
+ print(ret)
+ else:
+ sys.exit('Usage: %s %s %s' % (sys.argv[0], opts.command,
+ ' '.join(action['usage'])))
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/nichrome/scripts/cgpt_shell.sh b/nichrome/scripts/cgpt_shell.sh
new file mode 100644
index 000000000..8079c0b7e
--- /dev/null
+++ b/nichrome/scripts/cgpt_shell.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script is automatically generated by @SCRIPT_GENERATOR@.
+# Do not edit!
+
+if ! type numsectors >/dev/null 2>&1; then
+ . "./chromeos-common.sh" || exit 1
+fi
+locate_gpt
+
+# Usage: create_image
+# If is a block device, wipes out the GPT
+# If it's not, it creates a new file of the requested size
+create_image() {
+ local dev="$1"
+ local min_disk_size="$2"
+ local block_size="$3"
+ if [ -b "${dev}" ]; then
+ # Zap any old partitions (otherwise gpt complains).
+ dd if=/dev/zero of="${dev}" conv=notrunc bs=512 count=32
+ dd if=/dev/zero of="${dev}" conv=notrunc bs=512 \
+ seek=$(( min_disk_size - 1 - 33 )) count=33
+ else
+ if [ ! -e "${dev}" ]; then
+ dd if=/dev/zero of="${dev}" bs="${block_size}" count=1 \
+ seek=$(( min_disk_size - 1 ))
+ fi
+ fi
+}
+
diff --git a/nichrome/scripts/chromeos-common.sh b/nichrome/scripts/chromeos-common.sh
new file mode 100644
index 000000000..b394767e9
--- /dev/null
+++ b/nichrome/scripts/chromeos-common.sh
@@ -0,0 +1,292 @@
+#!/bin/sh
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This contains common constants and functions for installer scripts. This must
+# evaluate properly for both /bin/bash and /bin/sh, since it's used both to
+# create the initial image at compile time and to install or upgrade a running
+# image.
+
+# The GPT tables describe things in terms of 512-byte sectors, but some
+# filesystems prefer 4096-byte blocks. These functions help with alignment
+# issues.
+
+# This returns the size of a file or device in 512-byte sectors, rounded up if
+# needed.
+# Invoke as: subshell
+# Args: FILENAME
+# Return: whole number of sectors needed to fully contain FILENAME
+numsectors() {
+ if [ -b "${1}" ]; then
+ dev=${1##*/}
+ if [ -e /sys/block/$dev/size ]; then
+ cat /sys/block/$dev/size
+ else
+ part=${1##*/}
+ block=$(get_block_dev_from_partition_dev "${1}")
+ block=${block##*/}
+ cat /sys/block/$block/$part/size
+ fi
+ else
+ local bytes=$(stat -c%s "$1")
+ local sectors=$(( $bytes / 512 ))
+ local rem=$(( $bytes % 512 ))
+ if [ $rem -ne 0 ]; then
+ sectors=$(( $sectors + 1 ))
+ fi
+ echo $sectors
+ fi
+}
+
+# Locate the cgpt tool. It should already be installed in the build chroot,
+# but some of these functions may be invoked outside the chroot (by
+# image_to_usb or similar), so we need to find it.
+GPT=""
+
+locate_gpt() {
+ GPT="cgpt"
+}
+
+# Read GPT table to find the starting location of a specific partition.
+# Invoke as: subshell
+# Args: DEVICE PARTNUM
+# Returns: offset (in sectors) of partition PARTNUM
+partoffset() {
+ sudo ./cgpt show -b -i $2 $1
+}
+
+# Read GPT table to find the size of a specific partition.
+# Invoke as: subshell
+# Args: DEVICE PARTNUM
+# Returns: size (in sectors) of partition PARTNUM
+partsize() {
+ sudo ./cgpt show -s -i $2 $1
+}
+
+# Extract the whole disk block device from the partition device.
+# This works for /dev/sda3 (-> /dev/sda) as well as /dev/mmcblk0p2
+# (-> /dev/mmcblk0).
+get_block_dev_from_partition_dev() {
+ local partition=$1
+ if ! (expr match "$partition" ".*[0-9]$" >/dev/null) ; then
+ echo "Invalid partition name: $partition" >&2
+ exit 1
+ fi
+ # Removes any trailing digits.
+ local block=$(echo "$partition" | sed -e 's/[0-9]*$//')
+ # If needed, strip the trailing 'p'.
+ if (expr match "$block" ".*[0-9]p$" >/dev/null); then
+ echo "${block%p}"
+ else
+ echo "$block"
+ fi
+}
+
+# Extract the partition number from the partition device.
+# This works for /dev/sda3 (-> 3) as well as /dev/mmcblk0p2 (-> 2).
+get_partition_number() {
+ local partition=$1
+ if ! (expr match "$partition" ".*[0-9]$" >/dev/null) ; then
+ echo "Invalid partition name: $partition" >&2
+ exit 1
+ fi
+ # Extract the last digit.
+ echo "$partition" | sed -e 's/^.*\([0-9]\)$/\1/'
+}
+
+# Construct a partition device name from a whole disk block device and a
+# partition number.
+# This works for [/dev/sda, 3] (-> /dev/sda3) as well as [/dev/mmcblk0, 2]
+# (-> /dev/mmcblk0p2).
+make_partition_dev() {
+ local block=$1
+ local num=$2
+ # If the disk block device ends with a number, we add a 'p' before the
+ # partition number.
+ if (expr match "$block" ".*[0-9]$" >/dev/null) ; then
+ echo "${block}p${num}"
+ else
+ echo "${block}${num}"
+ fi
+}
+
+# Return the type of device.
+#
+# The type can be:
+# MMC, SD for device managed by the MMC stack
+# ATA for ATA disk
+# NVME for NVMe device
+# OTHER for other devices.
+get_device_type() {
+ local dev="$(basename "$1")"
+ local vdr
+ local type_file
+ local vendor_file
+ # True device path of a NVMe device is just a simple PCI device.
+ # (there are no other buses),
+ # Use the device name to identify the type precisely.
+ case "${dev}" in
+ nvme*)
+ echo "NVME"
+ return
+ ;;
+ esac
+
+ type_file="/sys/block/${dev}/device/type"
+ # To detect device managed by the MMC stack
+ case $(readlink -f "${type_file}") in
+ *mmc*)
+ cat "${type_file}"
+ ;;
+ *usb*)
+ # Now if it contains 'usb', it is managed through
+ # a USB controller.
+ echo "USB"
+ ;;
+ *target*)
+ # Other SCSI devices.
+ # Check if it is an ATA device.
+ vdr="$(cat "/sys/block/${dev}/device/vendor")"
+ if [ "${vdr%% *}" = "ATA" ]; then
+ echo "ATA"
+ else
+ echo "OTHER"
+ fi
+ ;;
+ *)
+ echo "OTHER"
+ esac
+}
+
+# ATA disk have ATA as vendor.
+# They may not contain ata in their device path if behind a SAS
+# controller.
+# Exclude disks with size 0, it means they did not spin up properly.
+list_fixed_ata_disks() {
+ local sd
+ local remo
+ local vdr
+ local size
+
+ for sd in /sys/block/sd*; do
+ if [ ! -r "${sd}/size" ]; then
+ continue
+ fi
+ size=$(cat "${sd}/size")
+ remo=$(cat "${sd}/removable")
+ vdr=$(cat "${sd}/device/vendor")
+ if [ "${vdr%% *}" = "ATA" -a ${remo:-0} -eq 0 -a ${size:-0} -gt 0 ]; then
+ echo "${sd##*/}"
+ fi
+ done
+}
+
+# We assume we only have eMMC devices, not removable MMC devices.
+# also, do not consider special hardware partitions on the eMMC, like boot.
+# These devices are built on top of the eMMC sysfs path:
+# /sys/block/mmcblk0 -> .../mmc_host/.../mmc0:0001/.../mmcblk0
+# /sys/block/mmcblk0boot0 -> .../mmc_host/.../mmc0:0001/.../mmcblk0/mmcblk0boot0
+# /sys/block/mmcblk0boot1 -> .../mmc_host/.../mmc0:0001/.../mmcblk0/mmcblk0boot1
+# /sys/block/mmcblk0rpmb -> .../mmc_host/.../mmc0:0001/.../mmcblk0/mmcblk0rpmb
+#
+# Their device link points back to mmcblk0, not to the hardware
+# device (mmc0:0001). Therefore there is no type in their device link.
+# (it should be /device/device/type)
+list_fixed_mmc_disks() {
+ local mmc
+ local type_file
+ for mmc in /sys/block/mmcblk*; do
+ type_file="${mmc}/device/type"
+ if [ -r "${type_file}" ]; then
+ if [ "$(cat "${type_file}")" = "MMC" ]; then
+ echo "${mmc##*/}"
+ fi
+ fi
+ done
+}
+
+# NVMe device
+# Exclude disks with size 0, it means they did not spin up properly.
+list_fixed_nvme_disks() {
+ local nvme remo size nvme_base all_nvme
+
+ for nvme in /sys/block/nvme*; do
+ if [ ! -r "${nvme}/size" ]; then
+ continue
+ fi
+ size=$(cat "${nvme}/size")
+ remo=$(cat "${nvme}/removable")
+ if [ ${remo:-0} -eq 0 -a ${size:-0} -gt 0 ]; then
+ nvme_base="${nvme##*/}"
+ # Store in all_nvme names of nvme devices, without namespace.
+ # In case of nvme device with several namespaces, we will have
+ # redundancy.
+ all_nvme="${all_nvme} ${nvme_base%n*}"
+ fi
+ done
+ echo "${all_nvme}" | tr '[:space:]' '\n' | sort -u
+}
+
+# Find the drive to install based on the build write_cgpt.sh
+# script. If not found, return ""
+get_fixed_dst_drive() {
+ local dev rootdev
+
+ if [ -n "${DEFAULT_ROOTDEV}" ]; then
+ # No " here, the variable may contain wildcards.
+ for rootdev in ${DEFAULT_ROOTDEV}; do
+ dev="/dev/$(basename "${rootdev}")"
+ if [ -b "${dev}" ]; then
+ break
+ else
+ dev=""
+ fi
+ done
+ fi
+ echo "${dev}"
+}
+
+edit_mbr() {
+ locate_gpt
+ # TODO(icoolidge): Get this from disk_layout somehow.
+ local PARTITION_NUM_EFI_SYSTEM=12
+ local start_esp=$(partoffset "$1" ${PARTITION_NUM_EFI_SYSTEM})
+ local num_esp_sectors=$(partsize "$1" ${PARTITION_NUM_EFI_SYSTEM})
+ sfdisk -X dos "${1}" <&/dev/null; then
+ # Limit pv's output to 80 columns, for readability.
+ local term_cols=$(stty size 2>/dev/null | cut -d' ' -f2)
+ if [[ ${term_cols:-0} -gt 80 ]]; then
+ echo pv -w 80 -B 4m
+ else
+ echo pv -B 4m
+ fi
+ else
+ echo cat
+ fi
+}
+
+# Make sure we have the location and name of the calling script, using
+# the current value if it is already set.
+: ${SCRIPT_LOCATION:=$(dirname "$(readlink -f -- "$0")")}
+: ${SCRIPT_NAME:=$(basename -- "$0")}
+
+# Detect whether we're inside a chroot or not
+CHROOT_VERSION_FILE=/etc/cros_chroot_version
+if [[ -e ${CHROOT_VERSION_FILE} ]]; then
+ INSIDE_CHROOT=1
+else
+ INSIDE_CHROOT=0
+fi
+
+# Determine and set up variables needed for fancy color output (if supported).
+V_BOLD_RED=
+V_BOLD_GREEN=
+V_BOLD_YELLOW=
+V_REVERSE=
+V_VIDOFF=
+
+if [[ -t 1 ]] && tput colors >&/dev/null; then
+ # order matters: we want VIDOFF last so that when we trace with `set -x`,
+ # our terminal doesn't bleed colors as bash dumps the values of vars.
+ V_BOLD_RED=$(tput bold; tput setaf 1)
+ V_BOLD_GREEN=$(tput bold; tput setaf 2)
+ V_BOLD_YELLOW=$(tput bold; tput setaf 3)
+ V_REVERSE=$(tput rev)
+ V_VIDOFF=$(tput sgr0)
+fi
+
+# Turn on bash debug support if available for backtraces.
+shopt -s extdebug 2>/dev/null
+
+# Output a backtrace. Optional parameter allows hiding the last
+# frame(s) so functions like "die()" can hide their additional
+# frame(s) if they wish.
+dump_trace() {
+ # Default = 0 hidden frames: show everything except dump_trace
+ # frame itself.
+ local hidden_frames=${1:-0}
+ local j n p func src line args
+ p=${#BASH_ARGV[@]}
+
+ error "$(date)"
+ error "$(ps f -o pgid,ppid,pid,etime,cputime,%cpu,command)"
+
+ # Frame 0 is ourselves so it's always suppressed / does not count.
+ for (( n = ${#FUNCNAME[@]}; n > hidden_frames; --n )); do
+ func=${FUNCNAME[${n} - 1]}
+ line=${BASH_LINENO[${n} - 1]}
+ args=
+ if [[ -z ${BASH_ARGC[${n} -1]} ]]; then
+ args='(args unknown, no debug available)'
+ else
+ for (( j = 0; j < ${BASH_ARGC[${n} -1]}; ++j )); do
+ args="${args:+${args} }'${BASH_ARGV[$(( p - j - 1 ))]}'"
+ done
+ ! (( p -= ${BASH_ARGC[${n} - 1]} ))
+ fi
+ if [[ ${n} == ${#FUNCNAME[@]} ]]; then
+ error "Arguments of $$: ${0##/*} ${args}"
+ error "Backtrace: (most recent call is last)"
+ else
+ src=${BASH_SOURCE[${n}]##*/}
+ curr_func=${FUNCNAME[${n}]}
+ error "$(printf ' %s:%s:%s(), called: %s %s ' \
+ "${src}" "${line}" "${curr_func}" "${func}" "${args}")"
+ fi
+ done
+}
+
+# Declare these asap so that code below can safely assume they exist.
+_message() {
+ local prefix=$1
+ shift
+ if [[ $# -eq 0 ]]; then
+ echo -e "${prefix}${CROS_LOG_PREFIX:-""}:${V_VIDOFF}" >&2
+ return
+ fi
+ (
+ # Handle newlines in the message, prefixing each chunk correctly.
+ # Do this in a subshell to avoid having to track IFS/set -f state.
+ IFS="
+"
+ set +f
+ set -- $*
+ IFS=' '
+ if [[ $# -eq 0 ]]; then
+ # Empty line was requested.
+ set -- ''
+ fi
+ for line in "$@"; do
+ echo -e "${prefix}${CROS_LOG_PREFIX:-}: ${line}${V_VIDOFF}" >&2
+ done
+ )
+}
+
+info() {
+ _message "${V_BOLD_GREEN}INFO " "$*"
+}
+
+warn() {
+ _message "${V_BOLD_YELLOW}WARNING " "$*"
+}
+
+error() {
+ _message "${V_BOLD_RED}ERROR " "$*"
+}
+
+
+# For all die functions, they must explicitly force set +eu;
+# no reason to have them cause their own crash if we're in the middle
+# of reporting an error condition then exiting.
+die_err_trap() {
+ local result=${1:-$?}
+ local command=${2:-${BASH_COMMAND:-command unknown}}
+ set +e +u
+
+ if [[ ${result} == "0" ]]; then
+ # Let callers simplify by setting us as an EXIT trap handler.
+ return 0
+ fi
+
+ # Per the message, bash misreports 127 as 1 during err trap sometimes.
+ # Note this fact to ensure users don't place too much faith in the
+ # exit code in that case.
+ set -- "Command '${command}' exited with nonzero code: ${result}"
+ if [[ ${result} -eq 1 ]] && [[ -z $(type -t ${command}) ]]; then
+ set -- "$@" \
+ '(Note bash sometimes misreports "command not found" as exit code 1 '\
+'instead of 127)'
+ fi
+ dump_trace 1
+ error
+ error "Command failed:"
+ DIE_PREFIX=' '
+ die_notrace "$@"
+}
+
+# Exit this script due to a failure, outputting a backtrace in the process.
+die() {
+ set +e +u
+ dump_trace 1
+ error
+ error "Error was:"
+ DIE_PREFIX=' '
+ die_notrace "$@"
+}
+
+# Exit this script w/out a backtrace.
+die_notrace() {
+ set +e +u
+ if [[ $# -eq 0 ]]; then
+ set -- '(no error message given)'
+ fi
+ local line
+ for line in "$@"; do
+ error "${DIE_PREFIX}${line}"
+ done
+ exit 1
+}
+
+# Check for a single string in a list of space-separated strings.
+# e.g. has "foo" "foo bar baz" is true, but has "f" "foo bar baz" is not.
+has() { [[ " ${*:2} " == *" $1 "* ]]; }
+
+# Directory locations inside the dev chroot; try the new default,
+# falling back to user specific paths if the upgrade has yet to
+# happen.
+_user="${USER}"
+[[ ${USER} == "root" ]] && _user="${SUDO_USER}"
+_CHROOT_TRUNK_DIRS=( "/home/${_user}/trunk" /mnt/host/source )
+_DEPOT_TOOLS_DIRS=( "/home/${_user}/depot_tools" /mnt/host/depot_tools )
+_WORKSPACE_DIRS=( "/home/${_user}/workspace" /mnt/host/workspace )
+unset _user
+
+_process_mount_pt() {
+ # Given 4 arguments; the root path, the variable to set,
+ # the old location, and the new; finally, forcing the upgrade is doable
+ # via if a 5th arg is provided.
+ # This will then try to migrate the old to new if we can do so right now
+ # (else leaving symlinks in place w/in the new), and will set $1 to the
+ # new location.
+ local base=${1:-/} var=$2 old=$3 new=$4 force=${5:-false}
+ local _sudo=$([[ ${USER} != "root" ]] && echo sudo)
+ local val=${new}
+ if ${force} || [[ -L ${base}/${new} ]] || [[ ! -e ${base}/${new} ]]; then
+ # Ok, it's either a symlink or this is the first run. Upgrade if we can-
+ # specifically, if we're outside the chroot and we can rmdir the old.
+ # If we cannot rmdir the old, that's due to a mount being bound to that
+ # point (even if we can't see it, it's there)- thus fallback to adding
+ # compat links.
+ if ${force} || ( [[ ${INSIDE_CHROOT} -eq 0 ]] && \
+ ${_sudo} rmdir "${base}/${old}" 2>/dev/null ); then
+ ${_sudo} rm -f "${base}/${new}" || :
+ ${_sudo} mkdir -p "${base}/${new}" "$(dirname "${base}/${old}" )"
+ ${_sudo} ln -s "${new}" "${base}/${old}"
+ else
+ if [[ ! -L ${base}/${new} ]]; then
+ # We can't do the upgrade right now; install compatibility links.
+ ${_sudo} mkdir -p "$(dirname "${base}/${new}")" "${base}/${old}"
+ ${_sudo} ln -s "${old}" "${base}/${new}"
+ fi
+ val=${old}
+ fi
+ fi
+ eval "${var}=\"${val}\""
+}
+
+set_chroot_trunk_dir() {
+ # This takes two optional arguments; the first being the path to the chroot
+ # base; this is only used by enter_chroot. The second argument is whether
+ # or not to force the new pathways; this is only used by make_chroot. Passing
+ # a non-null value for $2 forces the new paths.
+ if [[ ${INSIDE_CHROOT} -eq 0 ]] && [[ -z ${1-} ]]; then
+ # Can't do the upgrade, thus skip trying to do so.
+ CHROOT_TRUNK_DIR="${_CHROOT_TRUNK_DIRS[1]}"
+ DEPOT_TOOLS_DIR="${_DEPOT_TOOLS_DIRS[1]}"
+ WORKSPACE_DIR="${_WORKSPACE_DIRS[1]}"
+ return
+ fi
+ _process_mount_pt "${1:-}" CHROOT_TRUNK_DIR "${_CHROOT_TRUNK_DIRS[@]}" \
+ ${2:+true}
+ _process_mount_pt "${1:-}" DEPOT_TOOLS_DIR "${_DEPOT_TOOLS_DIRS[@]}" \
+ ${2:+true}
+ _process_mount_pt "${1:-}" WORKSPACE_DIR "${_WORKSPACE_DIRS[@]}" \
+ ${2:+true}
+}
+
+set_chroot_trunk_dir
+
+# Construct a list of possible locations for the source tree. This list is
+# based on various environment variables and globals that may have been set
+# by the calling script.
+get_gclient_root_list() {
+ if [[ ${INSIDE_CHROOT} -eq 1 ]]; then
+ echo "${CHROOT_TRUNK_DIR}"
+ fi
+
+ if [[ -n ${COMMON_SH:-} ]]; then echo "$(dirname "${COMMON_SH}")/../.."; fi
+ if [[ -n ${BASH_SOURCE} ]]; then echo "$(dirname "${BASH_SOURCE}")/../.."; fi
+}
+
+# Based on the list of possible source locations we set GCLIENT_ROOT if it is
+# not already defined by looking for a src directory in each seach path
+# location. If we do not find a valid looking root we error out.
+get_gclient_root() {
+ if [[ -n ${GCLIENT_ROOT:-} ]]; then
+ return
+ fi
+
+ for path in $(get_gclient_root_list); do
+ if [[ -d ${path}/src ]]; then
+ GCLIENT_ROOT=${path}
+ break
+ fi
+ done
+
+ if [[ -z ${GCLIENT_ROOT} ]]; then
+ # Using dash or sh, we don't know where we are. $0 refers to the calling
+ # script, not ourselves, so that doesn't help us.
+ echo "Unable to determine location for common.sh. If you are sourcing"
+ echo "common.sh from a script run via dash or sh, you must do it in the"
+ echo "following way:"
+ echo ' COMMON_SH="$(dirname "$0")/../../scripts/common.sh"'
+ echo ' . "${COMMON_SH}"'
+ echo "where the first line is the relative path from your script to"
+ echo "common.sh."
+ exit 1
+ fi
+}
+
+# Populate the ENVIRONMENT_WHITELIST array.
+load_environment_whitelist() {
+ set -f
+ ENVIRONMENT_WHITELIST=(
+ $("${GCLIENT_ROOT}/chromite/scripts/cros_env_whitelist")
+ )
+ set +f
+}
+
+# Find root of source tree
+# get_gclient_root
+
+# Canonicalize the directories for the root dir and the calling script.
+# readlink is part of coreutils and should be present even in a bare chroot.
+# This is better than just using
+# FOO="$(cd ${FOO} ; pwd)"
+# since that leaves symbolic links intact.
+# Note that 'realpath' is equivalent to 'readlink -f'.
+SCRIPT_LOCATION=$(readlink -f "${SCRIPT_LOCATION}")
+GCLIENT_ROOT=$(readlink -f "${GCLIENT_ROOT}")
+
+# Other directories should always be pathed down from GCLIENT_ROOT.
+SRC_ROOT="${GCLIENT_ROOT}/src"
+SRC_INTERNAL="${GCLIENT_ROOT}/src-internal"
+SCRIPTS_DIR="${SRC_ROOT}/scripts"
+BUILD_LIBRARY_DIR="${SCRIPTS_DIR}/build"
+
+# Load developer's custom settings. Default location is in scripts dir,
+# since that's available both inside and outside the chroot. By convention,
+# settings from this file are variables starting with 'CHROMEOS_'
+: ${CHROMEOS_DEV_SETTINGS:=${SCRIPTS_DIR}/.chromeos_dev}
+if [[ -f ${CHROMEOS_DEV_SETTINGS} ]]; then
+ # Turn on exit-on-error during custom settings processing
+ SAVE_OPTS=$(set +o)
+ switch_to_strict_mode
+
+ # Read settings
+ . "${CHROMEOS_DEV_SETTINGS}"
+
+ # Restore previous state of exit-on-error
+ eval "${SAVE_OPTS}"
+fi
+
+# Load shflags
+# NOTE: This code snippet is in particular used by the au-generator (which
+# stores shflags in ./lib/shflags/) and should not be touched.
+if [[ -f lib/shflags/shflags ]]; then
+ . "lib/shflags/shflags" || die "Couldn't find shflags"
+else
+ . ./lib/shflags/shflags || die "Couldn't find shflags"
+fi
+
+
+# Our local mirror
+DEFAULT_CHROMEOS_SERVER=${CHROMEOS_SERVER:-"http://build.chromium.org/mirror"}
+
+# Upstream mirrors and build suites come in 2 flavors
+# DEV - development chroot, used to build the chromeos image
+# IMG - bootable image, to run on actual hardware
+
+DEFAULT_DEV_MIRROR=${CHROMEOS_DEV_MIRROR:-"${DEFAULT_CHROMEOS_SERVER}/ubuntu"}
+DEFAULT_DEV_SUITE=${CHROMEOS_DEV_SUITE:-"karmic"}
+
+DEFAULT_IMG_MIRROR=${CHROMEOS_IMG_MIRROR:-"${DEFAULT_CHROMEOS_SERVER}/ubuntu"}
+DEFAULT_IMG_SUITE=${CHROMEOS_IMG_SUITE:-"karmic"}
+
+# Default location for chroot
+DEFAULT_CHROOT_DIR=${CHROMEOS_CHROOT_DIR:-"${GCLIENT_ROOT}/chroot"}
+
+# All output files from build should go under ${DEFAULT_BUILD_ROOT}, so that
+# they don't pollute the source directory.
+DEFAULT_BUILD_ROOT=${CHROMEOS_BUILD_ROOT:-"${SRC_ROOT}/build"}
+
+# Default location for event files
+DEFAULT_EVENT_DIR=${DEFAULT_EVENT_DIR:-"${DEFAULT_BUILD_ROOT}/events"}
+
+# Default event file. Format is YYYYDD.HHMM.json
+DEFAULT_EVENT_FILE=${DEFAULT_EVENT_FILE:-"${DEFAULT_EVENT_DIR}/$(date +%Y%m%d.%H%M.).json"}
+
+# Set up a global ALL_BOARDS value
+if [[ -d ${SRC_ROOT}/overlays ]]; then
+ ALL_BOARDS=$(cd "${SRC_ROOT}/overlays"; \
+ ls -1d overlay-* 2>&- | sed 's,overlay-,,g')
+fi
+# Normalize whitespace.
+ALL_BOARDS=$(echo ${ALL_BOARDS})
+
+# Sets the default board variable for calling script.
+if [[ -f ${GCLIENT_ROOT}/src/scripts/.default_board ]]; then
+ DEFAULT_BOARD=$(<"${GCLIENT_ROOT}/src/scripts/.default_board")
+ # Check for user typos like whitespace.
+ if [[ -n ${DEFAULT_BOARD//[a-zA-Z0-9-_]} ]]; then
+ die ".default_board: invalid name detected; please fix:" \
+ "'${DEFAULT_BOARD}'"
+ fi
+fi
+# Stub to get people to upgrade.
+get_default_board() {
+ warn "please upgrade your script, and make sure to run build_packages"
+}
+
+# Enable --fast by default.
+DEFAULT_FAST=${FLAGS_TRUE}
+
+# Directory to store built images. Should be set by sourcing script when used.
+BUILD_DIR=
+
+# Path to the verified boot directory where we get signing related keys/scripts.
+VBOOT_DIR="${CHROOT_TRUNK_DIR}/src/platform/vboot_reference"
+VBOOT_TESTKEYS_DIR="${VBOOT_DIR}/tests/testkeys"
+# We load these from the chroot rather than directly from the vboot source repo
+# so we work correctly even in a minilayout.
+VBOOT_DEVKEYS_DIR="vboot/devkeys"
+VBOOT_SIGNING_DIR="vboot/bin"
+
+# Standard filenames
+CHROMEOS_BASE_IMAGE_NAME="chromiumos_base_image.bin"
+CHROMEOS_IMAGE_NAME="chromiumos_image.bin"
+CHROMEOS_DEVELOPER_IMAGE_NAME="chromiumos_image.bin"
+CHROMEOS_RECOVERY_IMAGE_NAME="recovery_image.bin"
+CHROMEOS_TEST_IMAGE_NAME="chromiumos_test_image.bin"
+CHROMEOS_FACTORY_INSTALL_SHIM_NAME="factory_install_shim.bin"
+SYSROOT_SETTINGS_FILE="var/cache/edb/chromeos"
+
+# Install mask for portage ebuilds. Used by build_image and gmergefs.
+# TODO: Is /usr/local/autotest-chrome still used by anyone?
+COMMON_INSTALL_MASK="
+ *.a
+ *.c
+ *.cc
+ *.go
+ *.la
+ *.h
+ *.hh
+ *.hpp
+ *.h++
+ *.hxx
+ */.keep*
+ /etc/init.d
+ /etc/runlevels
+ /firmware
+ /lib/modules/*/vdso
+ /lib/rc
+ /opt/google/containers/android/vendor/lib*/pkgconfig
+ /usr/bin/*-config
+ /usr/bin/Xnest
+ /usr/bin/Xvfb
+ /usr/include/nspr/*
+ /usr/include/X11/*
+ /usr/lib/debug
+ /usr/lib/gopath
+ /usr/lib*/pkgconfig
+ /usr/local/autotest-chrome
+ /usr/man
+ /usr/share/aclocal
+ /usr/share/cups/drv
+ /usr/share/doc
+ /usr/share/gettext
+ /usr/share/gtk-2.0
+ /usr/share/gtk-doc
+ /usr/share/info
+ /usr/share/man
+ /usr/share/ppd
+ /usr/share/openrc
+ /usr/share/pkgconfig
+ /usr/share/profiling
+ /usr/share/readline
+ /usr/src
+ "
+
+# Mask for base, dev, and test images (build_image, build_image --test)
+DEFAULT_INSTALL_MASK="
+ ${COMMON_INSTALL_MASK}
+ /boot/config-*
+ /boot/System.map-*
+ /usr/local/build/autotest
+ /lib/modules/*/build
+ /lib/modules/*/source
+ test_*.ko
+ "
+
+# Mask for factory test image (make_factory_toolkit.sh)
+FACTORY_TEST_INSTALL_MASK="
+ ${COMMON_INSTALL_MASK}
+ */.svn
+ */CVS
+ /usr/local/autotest/conmux
+ /usr/local/build/autotest
+ /usr/local/factory/bundle
+ "
+
+# Mask for factory install shim (build_image factory_install)
+FACTORY_SHIM_INSTALL_MASK="
+ ${DEFAULT_INSTALL_MASK}
+ /opt/[^g]*
+ /opt/google/chrome
+ /opt/google/containers
+ /opt/google/o3d
+ /opt/google/talkplugin
+ /usr/lib/dri
+ /usr/lib/python2.6/test
+ /usr/lib64/dri
+ /usr/local/autotest-pkgs
+ /usr/share/X11
+ /usr/share/chewing
+ /usr/share/chromeos-assets
+ /usr/share/fonts
+ /usr/share/ibus-pinyin
+ /usr/share/libhangul
+ /usr/share/locale
+ /usr/share/m17n
+ /usr/share/mime
+ /usr/share/oem
+ /usr/share/pyzy
+ /usr/share/sounds
+ /usr/share/tts
+ /usr/share/zoneinfo
+ "
+
+# Mask for images without systemd.
+SYSTEMD_INSTALL_MASK="
+ /lib/systemd
+ /usr/lib/systemd
+"
+
+# -----------------------------------------------------------------------------
+# Functions
+
+setup_board_warning() {
+ echo
+ echo "${V_REVERSE}================ WARNING =====================${V_VIDOFF}"
+ echo
+ echo "*** No default board detected in " \
+ "${GCLIENT_ROOT}/src/scripts/.default_board"
+ echo "*** Either run setup_board with default flag set"
+ echo "*** or echo |board_name| > ${GCLIENT_ROOT}/src/scripts/.default_board"
+ echo
+}
+
+is_nfs() {
+ [[ $(stat -f -L -c %T "$1") == "nfs" ]]
+}
+
+warn_if_nfs() {
+ if is_nfs "$1"; then
+ warn "$1 is on NFS. This is untested. You can send patches if it's broken."
+ fi
+}
+
+# Enter a chroot and restart the current script if needed
+restart_in_chroot_if_needed() {
+ # NB: Pass in ARGV: restart_in_chroot_if_needed "$@"
+ if [[ ${INSIDE_CHROOT} -ne 1 ]]; then
+ # Get inside_chroot path for script.
+ local chroot_path="$(reinterpret_path_for_chroot "$0")"
+ exec ${GCLIENT_ROOT}/chromite/bin/cros_sdk -- "${chroot_path}" "$@"
+ fi
+}
+
+# Fail unless we're inside the chroot. This guards against messing up your
+# workstation.
+assert_inside_chroot() {
+ echo "BRO"
+}
+
+# Fail if we're inside the chroot. This guards against creating or entering
+# nested chroots, among other potential problems.
+assert_outside_chroot() {
+ echo "BRO"
+}
+
+assert_not_root_user() {
+ echo "BRO"
+}
+
+assert_root_user() {
+ echo "BRO"
+}
+
+# Check that all arguments are flags; that is, there are no remaining arguments
+# after parsing from shflags. Allow (with a warning) a single empty-string
+# argument.
+#
+# TODO: fix buildbot so that it doesn't pass the empty-string parameter,
+# then change this function.
+#
+# Usage: check_flags_only_and_allow_null_arg "$@" && set --
+check_flags_only_and_allow_null_arg() {
+ local do_shift=1
+ if [[ $# -eq 1 ]] && [[ -z $1 ]]; then
+ echo "$0: warning: ignoring null argument" >&2
+ shift
+ do_shift=0
+ fi
+ if [[ $# -gt 0 ]]; then
+ echo "error: invalid arguments: \"$*\"" >&2
+ flags_help
+ exit 1
+ fi
+ return ${do_shift}
+}
+
+# Removes single quotes around parameter
+# Arguments:
+# $1 - string which optionally has surrounding quotes
+# Returns:
+# None, but prints the string without quotes.
+remove_quotes() {
+ echo "$1" | sed -e "s/^'//; s/'$//"
+}
+
+# Writes stdin to the given file name as root using sudo in overwrite mode.
+#
+# $1 - The output file name.
+sudo_clobber() {
+ sudo tee "$1" >/dev/null
+}
+
+# Writes stdin to the given file name as root using sudo in append mode.
+#
+# $1 - The output file name.
+sudo_append() {
+ sudo tee -a "$1" >/dev/null
+}
+
+# Execute multiple commands in a single sudo. Generally will speed things
+# up by avoiding multiple calls to `sudo`. If any commands fail, we will
+# call die with the failing command. We can handle a max of ~100 commands,
+# but hopefully no one will ever try that many at once.
+#
+# $@ - The commands to execute, one per arg.
+sudo_multi() {
+ local i cmds
+
+ # Construct the shell code to execute. It'll be of the form:
+ # ... && ( ( command ) || exit ) && ...
+ # This way we know which command exited. The exit status of
+ # the underlying command is lost, but we never cared about it
+ # in the first place (other than it is non zero), so oh well.
+ for (( i = 1; i <= $#; ++i )); do
+ cmds+=" && ( ( ${!i} ) || exit $(( i + 10 )) )"
+ done
+
+ # Execute our constructed shell code.
+ sudo -- sh -c ":${cmds[*]}" && i=0 || i=$?
+
+ # See if this failed, and if so, print out the failing command.
+ if [[ $i -gt 10 ]]; then
+ : $(( i -= 10 ))
+ die "sudo_multi failed: ${!i}"
+ elif [[ $i -ne 0 ]]; then
+ die "sudo_multi failed for unknown reason $i"
+ fi
+}
+
+# Clears out stale shadow-utils locks in the given target root.
+sudo_clear_shadow_locks() {
+ info "Clearing shadow utils lockfiles under $1"
+ sudo rm -f "$1/etc/"{passwd,group,shadow,gshadow}.lock*
+}
+
+# Writes stdin to the given file name as the sudo user in overwrite mode.
+#
+# $@ - The output file names.
+user_clobber() {
+ install -m644 -o ${SUDO_UID} -g ${SUDO_GID} /dev/stdin "$@"
+}
+
+# Copies the specified file owned by the user to the specified location.
+# If the copy fails as root (e.g. due to root_squash and NFS), retry the copy
+# with the user's account before failing.
+user_cp() {
+ cp -p "$@" 2>/dev/null || sudo -u ${SUDO_USER} -- cp -p "$@"
+}
+
+# Appends stdin to the given file name as the sudo user.
+#
+# $1 - The output file name.
+user_append() {
+ cat >> "$1"
+ chown ${SUDO_UID}:${SUDO_GID} "$1"
+}
+
+# Create the specified directory, along with parents, as the sudo user.
+#
+# $@ - The directories to create.
+user_mkdir() {
+ install -o ${SUDO_UID} -g ${SUDO_GID} -d "$@"
+}
+
+# Create the specified symlink as the sudo user.
+#
+# $1 - Link target
+# $2 - Link name
+user_symlink() {
+ ln -sfT "$1" "$2"
+ chown -h ${SUDO_UID}:${SUDO_GID} "$2"
+}
+
+# Locate all mounts below a specified directory.
+#
+# $1 - The root tree.
+sub_mounts() {
+ # Assume that `mount` outputs a list of mount points in the order
+ # that things were mounted (since it always has and hopefully always
+ # will). As such, we have to unmount in reverse order to cleanly
+ # unmount submounts (think /dev/pts and /dev).
+ awk -v path="$1" -v len="${#1}" \
+ '(substr($2, 1, len) == path) { print $2 }' /proc/mounts | \
+ tac | \
+ sed -e 's/\\040(deleted)$//'
+ # Hack(zbehan): If a bind mount's source is mysteriously removed,
+ # we'd end up with an orphaned mount with the above string in its name.
+ # It can only be seen through /proc/mounts and will stick around even
+ # when it should be gone already. crosbug.com/31250
+}
+
+# Unmounts a directory, if the unmount fails, warn, and then lazily unmount.
+#
+# $1 - The path to unmount.
+safe_umount_tree() {
+ local mount_point="$1"
+
+ local mounts=( $(sub_mounts "${mount_point}") )
+
+ # Silently return if the mount_point was already unmounted.
+ if [[ ${#mounts[@]} -eq 0 ]]; then
+ return 0
+ fi
+
+ # First try to unmount in one shot to speed things up.
+ if LC_ALL=C safe_umount -d "${mounts[@]}"; then
+ return 0
+ fi
+
+ # Well that didn't work, so lazy unmount remaining ones.
+ warn "Failed to unmount ${mounts[@]}, these are the processes using the" \
+ "mount points."
+ sudo fuser -vm "${mount_point}" || true
+
+ warn "Doing a lazy unmount"
+ if ! safe_umount -d -l "${mounts[@]}"; then
+ mounts=( $(sub_mounts "${mount_point}") )
+ die "Failed to lazily unmount ${mounts[@]}"
+ fi
+}
+
+
+# Run umount as root.
+safe_umount() {
+ $([[ ${UID:-$(id -u)} != 0 ]] && echo sudo) umount "$@"
+}
+
+# Run a command with sudo in a way that still preferentially uses files
+# from au-generator.zip, but still finds things in /sbin and /usr/sbin when
+# not using au-generator.zip.
+au_generator_sudo() {
+ # When searching for env, the unmodified path is used and env is potentially
+ # found somewhere out in the system. env itself sees the modified PATH
+ # and will find the command where we're telling it to. Running the command
+ # directly without env will escape our constructed PATH.
+ sudo -E PATH="${PATH}:/sbin:/usr/sbin" env "$@"
+}
+
+# Setup a loopback device for a file and scan for partitions, with retries.
+#
+# $1 - The file to back the new loopback device.
+# $2-$N - Additional arguments to pass to losetup.
+loopback_partscan() {
+ local lb_dev image="$1"
+ shift
+ lb_dev=$(au_generator_sudo losetup --show -f "$@" "${image}")
+ # Ignore problems deleting existing partitions. There shouldn't be any
+ # which will upset partx, but that's actually ok.
+ au_generator_sudo partx -d "${lb_dev}" 2>/dev/null || true
+ au_generator_sudo partx -a "${lb_dev}"
+
+ echo "${lb_dev}"
+}
+
+# Detach a loopback device set up earlier.
+#
+# $1 - The loop device to detach.
+# $2-$N - Additional arguments to pass to losetup.
+loopback_detach() {
+ # Retry the deletes before we detach. crbug.com/469259
+ local i
+ for (( i = 0; i < 10; i++ )); do
+ if au_generator_sudo partx -d "$1"; then
+ break
+ fi
+ warn "Sleeping & retrying ..."
+ sync
+ sleep 1
+ done
+ au_generator_sudo losetup --detach "$@"
+}
+
+# Get the size of a regular file or a block device.
+#
+# $1 - The regular file or block device to get the size of.
+bd_safe_size() {
+ local file="$1"
+ if [[ -b "${file}" ]]; then
+ sudo blockdev --getsize64 "${file}"
+ else
+ stat -c%s "${file}"
+ fi
+}
+
+get_git_id() {
+ git var GIT_COMMITTER_IDENT | sed -e 's/^.*<\(\S\+\)>.*$/\1/'
+}
+
+# Fixes symlinks that are incorrectly prefixed with the build root $1
+# rather than the real running root '/'.
+# TODO(sosa) - Merge setup - cleanup below with this method.
+fix_broken_symlinks() {
+ local build_root=$1
+ local symlinks=$(find "${build_root}/usr/local" -lname "${build_root}/*")
+ local symlink
+ for symlink in ${symlinks}; do
+ echo "Fixing ${symlink}"
+ local target=$(ls -l "${symlink}" | cut -f 2 -d '>')
+ # Trim spaces from target (bashism).
+ target=${target/ /}
+ # Make new target (removes rootfs prefix).
+ new_target=$(echo ${target} | sed "s#${build_root}##")
+
+ echo "Fixing symlink ${symlink}"
+ sudo unlink "${symlink}"
+ sudo ln -sf "${new_target}" "${symlink}"
+ done
+}
+
+# Sets up symlinks for the developer root. It is necessary to symlink
+# usr and local since the developer root is mounted at /usr/local and
+# applications expect to be installed under /usr/local/bin, etc.
+# This avoids packages installing into /usr/local/usr/local/bin.
+# $1 specifies the symlink target for the developer root.
+# $2 specifies the symlink target for the var directory.
+# $3 specifies the location of the stateful partition.
+setup_symlinks_on_root() {
+ # Give args better names.
+ local dev_image_target=$1
+ local var_target=$2
+ local dev_image_root="$3/dev_image"
+
+ # If our var target is actually the standard var, we are cleaning up the
+ # symlinks (could also check for /usr/local for the dev_image_target).
+ if [[ ${var_target} == "/var" ]]; then
+ echo "Cleaning up /usr/local symlinks for ${dev_image_root}"
+ else
+ echo "Setting up symlinks for /usr/local for ${dev_image_root}"
+ fi
+
+ # Set up symlinks that should point to ${dev_image_target}.
+ local path
+ for path in usr local; do
+ if [[ -h ${dev_image_root}/${path} ]]; then
+ sudo unlink "${dev_image_root}/${path}"
+ elif [[ -e ${dev_image_root}/${path} ]]; then
+ die "${dev_image_root}/${path} should be a symlink if exists"
+ fi
+ sudo ln -s "${dev_image_target}" "${dev_image_root}/${path}"
+ done
+
+ # Setup var symlink.
+ if [[ -h ${dev_image_root}/var ]]; then
+ sudo unlink "${dev_image_root}/var"
+ elif [[ -e ${dev_image_root}/var ]]; then
+ die "${dev_image_root}/var should be a symlink if it exists"
+ fi
+
+ sudo ln -s "${var_target}" "${dev_image_root}/var"
+}
+
+# These two helpers clobber the ro compat value in our root filesystem.
+#
+# When the system is built with --enable_rootfs_verification, bit-precise
+# integrity checking is performed. That precision poses a usability issue on
+# systems that automount partitions with recognizable filesystems, such as
+# ext2/3/4. When the filesystem is mounted 'rw', ext2 metadata will be
+# automatically updated even if no other writes are performed to the
+# filesystem. In addition, ext2+ does not support a "read-only" flag for a
+# given filesystem. That said, forward and backward compatibility of
+# filesystem features are supported by tracking if a new feature breaks r/w or
+# just write compatibility. We abuse the read-only compatibility flag[1] in
+# the filesystem header by setting the high order byte (le) to FF. This tells
+# the kernel that features R24-R31 are all enabled. Since those features are
+# undefined on all ext-based filesystem, all standard kernels will refuse to
+# mount the filesystem as read-write -- only read-only[2].
+#
+# [1] 32-bit flag we are modifying:
+# https://chromium.googlesource.com/chromiumos/third_party/kernel.git/+/master/include/linux/ext2_fs.h#l417
+# [2] Mount behavior is enforced here:
+# https://chromium.googlesource.com/chromiumos/third_party/kernel.git/+/master/ext2/super.c#l857
+#
+# N.B., if the high order feature bits are used in the future, we will need to
+# revisit this technique.
+disable_rw_mount() {
+ local rootfs=$1
+ local offset="${2-0}" # in bytes
+ local ro_compat_offset=$((0x464 + 3)) # Set 'highest' byte
+ is_ext_filesystem "${rootfs}" "${offset}" || return 0
+ is_ext2_rw_mount_enabled "${rootfs}" "${offset}" || return 0
+
+ make_block_device_rw "${rootfs}"
+ printf '\377' |
+ sudo dd of="${rootfs}" seek=$((offset + ro_compat_offset)) \
+ conv=notrunc count=1 bs=1 status=none
+}
+
+enable_rw_mount() {
+ local rootfs=$1
+ local offset="${2-0}"
+ local ro_compat_offset=$((0x464 + 3)) # Set 'highest' byte
+ is_ext_filesystem "${rootfs}" "${offset}" || return 0
+ is_ext2_rw_mount_enabled "${rootfs}" "${offset}" && return 0
+
+ make_block_device_rw "${rootfs}"
+ printf '\000' |
+ sudo dd of="${rootfs}" seek=$((offset + ro_compat_offset)) \
+ conv=notrunc count=1 bs=1 status=none
+}
+
+is_ext2_rw_mount_enabled() {
+ local rootfs=$1
+ local offset="${2-0}"
+ local ro_compat_offset=$((0x464 + 3)) # Get 'highest' byte
+ local ro_compat_flag=$(sudo dd if="${rootfs}" \
+ skip=$((offset + ro_compat_offset)) bs=1 count=1 status=none \
+ 2>/dev/null | hexdump -e '1 "%.2x"')
+ test "${ro_compat_flag}" = "00"
+}
+
+# Returns whether the passed rootfs is an extended filesystem by checking the
+# ext2 s_magic field in the superblock.
+is_ext_filesystem() {
+ local rootfs=$1
+ local offset="${2-0}"
+ local ext_magic_offset=$((0x400 + 56))
+ local ext_magic=$(sudo dd if="${rootfs}" \
+ skip=$((offset + ext_magic_offset)) bs=1 count=2 2>/dev/null |
+ hexdump -e '1/2 "%.4x"')
+ test "${ext_magic}" = "ef53"
+}
+
+# If the passed argument is a block device, ensure it is writtable and make it
+# writtable if not.
+make_block_device_rw() {
+ local block_dev="$1"
+ [[ -b "${block_dev}" ]] || return 0
+ if [[ $(sudo blockdev --getro "${block_dev}") == "1" ]]; then
+ sudo blockdev --setrw "${block_dev}"
+ fi
+}
+
+# Get current timestamp. Assumes common.sh runs at startup.
+start_time=$(date +%s)
+
+# Get time elapsed since start_time in seconds.
+get_elapsed_seconds() {
+ local end_time=$(date +%s)
+ local elapsed_seconds=$(( end_time - start_time ))
+ echo ${elapsed_seconds}
+}
+
+# Print time elapsed since start_time.
+print_time_elapsed() {
+ # Optional first arg to specify elapsed_seconds. If not given, will
+ # recalculate elapsed time to now. Optional second arg to specify
+ # command name associated with elapsed time.
+ local elapsed_seconds=${1:-$(get_elapsed_seconds)}
+ local cmd_base=${2:-}
+
+ local minutes=$(( elapsed_seconds / 60 ))
+ local seconds=$(( elapsed_seconds % 60 ))
+
+ if [[ -n ${cmd_base} ]]; then
+ info "Elapsed time (${cmd_base}): ${minutes}m${seconds}s"
+ else
+ info "Elapsed time: ${minutes}m${seconds}s"
+ fi
+}
+
+# Associative array for filling in extra command-specific stats before
+# calling command_completed.
+declare -A EXTRA_COMMAND_STATS
+
+# Save original command line.
+command_line_arr=( "$0" "$@" )
+
+command_completed() {
+ # Call print_elapsed_time regardless.
+ local run_time=$(get_elapsed_seconds)
+ local cmd_base=$(basename "${command_line_arr[0]}")
+ print_time_elapsed ${run_time} ${cmd_base}
+
+ # Prepare command stats in an associative array. Additional command-specific
+ # stats can be added through EXTRA_COMMAND_STATS associative array.
+ declare -A stats
+ stats=(
+ [cmd_line]=${command_line_arr[*]}
+ [cmd_base]=${cmd_base}
+ [cmd_args]=${command_line_arr[*]:1}
+ [run_time]=${run_time}
+ [username]=$(get_git_id)
+ [board]=${FLAGS_board}
+ [host]=$(hostname -f)
+ [cpu_count]=$(grep -c processor /proc/cpuinfo)
+ [cpu_type]=$(uname -p)
+ )
+
+ local attr
+ for attr in "${!EXTRA_COMMAND_STATS[@]}"; do
+ stats[${attr}]=${EXTRA_COMMAND_STATS[${attr}]}
+ done
+
+ # Prepare temporary file for stats.
+ local tmpfile=$(mktemp -t tmp.stats.XXXXXX)
+ trap "rm -f '${tmpfile}'" EXIT
+
+ # Write stats out to temporary file.
+ echo "Chromium OS Build Command Stats - Version 1" > "${tmpfile}"
+ for attr in "${!stats[@]}"; do
+ echo "${attr} ${stats[${attr}]}"
+ done >> "${tmpfile}"
+
+ rm "${tmpfile}"
+ trap - EXIT
+}
+
+# The board and variant command line options can be used in a number of ways
+# to specify the board and variant. The board can encode both pieces of
+# information separated by underscores. Or the variant can be passed using
+# the separate variant option. This function extracts the canonical board and
+# variant information and provides it in the BOARD, VARIANT and BOARD_VARIANT
+# variables.
+get_board_and_variant() {
+ local flags_board=$1
+ local flags_variant=$2
+ local flags_brick=$3
+
+ if [[ -n "${flags_brick}" ]]; then
+ BOARD="$(cros_brick_utils --friendly-name ${flags_brick})"
+ BOARD_VARIANT="${BOARD}"
+ VARIANT=""
+ return
+ fi
+
+ BOARD=$(echo "${flags_board}" | cut -d '_' -f 1)
+ VARIANT=${flags_variant:-$(echo "${flags_board}" | cut -s -d '_' -f 2)}
+
+ BOARD_VARIANT=${BOARD}
+ if [[ -n ${VARIANT} ]]; then
+ BOARD_VARIANT+="_${VARIANT}"
+ fi
+}
+
+# Load a setting from the sysroot's standard configuration file,
+# etc/make.conf.board_setup.
+# $1 - Path to the sysroot.
+# $2 - Variable to get.
+get_sysroot_config() {
+ local sysroot=$1
+ local variable=$2
+ local config_file="${sysroot%/}/etc/make.conf.board_setup"
+
+ get_variable "${config_file}" "${variable}"
+}
+
+# Load a single variable from a bash file.
+# $1 - Path to the file.
+# $2 - Variable to get.
+get_variable() {
+ local filepath=$1
+ local variable=$2
+ local lockfile="${filepath}.lock"
+
+ if [[ -e "${filepath}" ]]; then
+ userowned_file "${lockfile}"
+ (
+ flock 201
+ . "${filepath}"
+ if [[ "${!variable+set}" == "set" ]]; then
+ echo "${!variable}"
+ fi
+ ) 201>"${lockfile}"
+ fi
+}
+
+# Set a single variable in a KEY=VALUE file.
+# Note: the file is assumed to be owned by root.
+# $1 - Path to the file.
+# $2 - Variable to set.
+# $3 - Value to set.
+set_variable() {
+ local filepath=$1
+ local variable=$2
+ local value=$3
+ local lockfile="${filepath}.lock"
+
+ userowned_file "${lockfile}"
+ (
+ flock 201
+ sudo touch "${filepath}"
+ sudo sed -i -e "/^${variable}=/d" "${filepath}"
+ printf '\n%s="%s"\n' "${variable}" "${value}" | sudo_append "${filepath}"
+ ) 201>"${lockfile}"
+}
+
+# Creates a user owned file.
+# $1 - Path to the file.
+userowned_file() {
+ local filepath=$1
+
+ if [[ ! -w "${filepath}" ]]; then
+ cmds=(
+ "mkdir -p '$(dirname "${filepath}")'"
+ "touch '${filepath}'"
+ "chown ${USER} '${filepath}'"
+ )
+ sudo_multi "${cmds[@]}"
+ fi
+}
+
+# Load configuration files that allow board-specific overrides of default
+# functionality to be specified in overlays.
+# $1 - File to load.
+load_board_specific_script() {
+ local file=$1 overlay
+ [[ $# -ne 1 ]] && die "load_board_specific_script requires exactly 1 param"
+ for overlay in ${BOARD_OVERLAY}; do
+ local setup_sh="${overlay}/scripts/${file}"
+ if [[ -e ${setup_sh} ]]; then
+ source "${setup_sh}"
+ fi
+ done
+}
+
+# Check that the specified file exists. If the file path is empty or the file
+# doesn't exist on the filesystem generate useful error messages. Otherwise
+# show the user the name and path of the file that will be used. The padding
+# parameter can be used to tabulate multiple name:path pairs. For example:
+#
+# check_for_file "really long name" "...:" "file.foo"
+# check_for_file "short name" ".........:" "another.bar"
+#
+# Results in the following output:
+#
+# Using really long name...: file.foo
+# Using short name.........: another.bar
+#
+# If tabulation is not required then passing "" for padding generates the
+# output "Using "
+check_for_file() {
+ local name=$1
+ local padding=$2
+ local path=$3
+
+ if [[ -z ${path} ]]; then
+ die "No ${name} file specified."
+ fi
+
+ if [[ ! -e ${path} ]]; then
+ die "No ${name} file found at: ${path}"
+ else
+ info "Using ${name}${padding} ${path}"
+ fi
+}
+
+# Check that the specified tool exists. If it does not exist in the PATH
+# generate a useful error message indicating how to install the ebuild
+# that contains the required tool.
+check_for_tool() {
+ local tool=$1
+ local ebuild=$2
+
+ if ! which "${tool}" >/dev/null; then
+ error "The ${tool} utility was not found in your path. Run the following"
+ error "command in your chroot to install it: sudo -E emerge ${ebuild}"
+ exit 1
+ fi
+}
+
+# Reinterprets path from outside the chroot for use inside.
+# Returns "" if "" given.
+# $1 - The path to reinterpret.
+reinterpret_path_for_chroot() {
+ if [[ ${INSIDE_CHROOT} -ne 1 ]]; then
+ if [[ -z $1 ]]; then
+ echo ""
+ else
+ local path_abs_path=$(readlink -f "$1")
+ local gclient_root_abs_path=$(readlink -f "${GCLIENT_ROOT}")
+
+ # Strip the repository root from the path.
+ local relative_path=$(echo ${path_abs_path} \
+ | sed "s:${gclient_root_abs_path}/::")
+
+ if [[ ${relative_path} == "${path_abs_path}" ]]; then
+ die "Error reinterpreting path. Path $1 is not within source tree."
+ fi
+
+ # Prepend the chroot repository path.
+ echo "/mnt/host/source/${relative_path}"
+ fi
+ else
+ # Path is already inside the chroot :).
+ echo "$1"
+ fi
+}
+
+emerge_custom_kernel() {
+ local install_root=$1
+ local root=/build/${FLAGS_board}
+ local tmp_pkgdir=${root}/custom-packages
+
+ # Clean up any leftover state in custom directories.
+ sudo rm -rf "${tmp_pkgdir}"
+
+ # Update chromeos-initramfs to contain the latest binaries from the build
+ # tree. This is basically just packaging up already-built binaries from
+ # ${root}. We are careful not to muck with the existing prebuilts so that
+ # prebuilts can be uploaded in parallel.
+ # TODO(davidjames): Implement ABI deps so that chromeos-initramfs will be
+ # rebuilt automatically when its dependencies change.
+ sudo -E PKGDIR="${tmp_pkgdir}" ${EMERGE_BOARD_CMD} -1 \
+ chromeos-base/chromeos-initramfs || die "Cannot emerge chromeos-initramfs"
+
+ # Verify all dependencies of the kernel are installed. This should be a
+ # no-op, but it's good to check in case a developer didn't run
+ # build_packages. We need the expand_virtual call to workaround a bug
+ # in portage where it only installs the virtual pkg.
+ local kernel=$(portageq-${FLAGS_board} expand_virtual ${root} \
+ virtual/linux-sources)
+ sudo -E PKGDIR="${tmp_pkgdir}" ${EMERGE_BOARD_CMD} --onlydeps \
+ ${kernel} || die "Cannot emerge kernel dependencies"
+
+ # Build the kernel. This uses the standard root so that we can pick up the
+ # initramfs from there. But we don't actually install the kernel to the
+ # standard root, because that'll muck up the kernel debug symbols there,
+ # which we want to upload in parallel.
+ sudo -E PKGDIR="${tmp_pkgdir}" ${EMERGE_BOARD_CMD} --buildpkgonly \
+ ${kernel} || die "Cannot emerge kernel"
+
+ # Install the custom kernel to the provided install root.
+ sudo -E PKGDIR="${tmp_pkgdir}" ${EMERGE_BOARD_CMD} --usepkgonly \
+ --root=${install_root} ${kernel} || die "Cannot emerge kernel to root"
+}
+
+enable_strict_sudo() {
+ if [[ -z ${CROS_SUDO_KEEP_ALIVE} ]]; then
+ echo "$0 was somehow invoked in a way that the sudo keep alive could"
+ echo "not be found. Failing due to this. See crosbug.com/18393."
+ exit 126
+ fi
+ sudo() {
+ $(type -P sudo) -n "$@"
+ }
+}
+
+# Checks that stdin and stderr are both terminals.
+# If so, we assume that there is a live user we can interact with.
+# This check can be overridden by setting the CROS_NO_PROMPT environment
+# variable to a non-empty value.
+is_interactive() {
+ [[ -z ${CROS_NO_PROMPT} && -t 0 && -t 2 ]]
+}
+
+assert_interactive() {
+ if ! is_interactive; then
+ die "Script ${0##*/} tried to get user input on a non-interactive terminal."
+ fi
+}
+
+# Selection menu with a default option: this is similar to bash's select
+# built-in, only that in case of an empty selection it'll return the default
+# choice. Like select, it uses PS3 as the prompt.
+#
+# $1: name of variable to be assigned the selected value; it better not be of
+# the form choose_foo to avoid conflict with local variables.
+# $2: default value to return in case of an empty user entry.
+# $3: value to return in case of an invalid choice.
+# $...: options for selection.
+#
+# Usage example:
+#
+# PS3="Select one [1]: "
+# choose reply "foo" "ERROR" "foo" "bar" "foobar"
+#
+# This will present the following menu and prompt:
+#
+# 1) foo
+# 2) bar
+# 3) foobar
+# Select one [1]:
+#
+# The return value will be stored in a variable named 'reply'. If the input is
+# 1, 2 or 3, the return value will be "foo", "bar" or "foobar", respectively.
+# If it is empty (i.e. the user clicked Enter) it will be "foo". Anything else
+# will return "ERROR".
+choose() {
+ typeset -i choose_i=1
+
+ # Retrieve output variable name and default return value.
+ local choose_reply=$1
+ local choose_default=$2
+ local choose_invalid=$3
+ shift 3
+
+ # Select a return value
+ unset REPLY
+ if [[ $# -gt 0 ]]; then
+ assert_interactive
+
+ # Actual options provided, present a menu and prompt for a choice.
+ local choose_opt
+ for choose_opt in "$@"; do
+ echo "${choose_i}) ${choose_opt}" >&2
+ : $(( ++choose_i ))
+ done
+ read -p "$PS3"
+ fi
+ # Filter out strings containing non-digits.
+ if [[ ${REPLY} != "${REPLY%%[!0-9]*}" ]]; then
+ REPLY=0
+ fi
+ choose_i="${REPLY}"
+
+ if [[ ${choose_i} -ge 1 && ${choose_i} -le $# ]]; then
+ # Valid choice, return the corresponding value.
+ eval ${choose_reply}=\""${!choose_i}"\"
+ elif [[ -z ${REPLY} ]]; then
+ # Empty choice, return default value.
+ eval ${choose_reply}=\""${choose_default}"\"
+ else
+ # Invalid choice, return corresponding value.
+ eval ${choose_reply}=\""${choose_invalid}\""
+ fi
+}
+
+# Display --help if requested. This is used to hide options from help
+# that are not intended for developer use.
+#
+# How to use:
+# 1) Declare the options that you want to appear in help.
+# 2) Call this function.
+# 3) Declare the options that you don't want to appear in help.
+#
+# See build_packages for example usage.
+show_help_if_requested() {
+ local opt
+ for opt in "$@"; do
+ if [[ ${opt} == "-h" || ${opt} == "--help" ]]; then
+ flags_help
+ exit 0
+ fi
+ done
+}
+
+switch_to_strict_mode() {
+ # Set up strict execution mode; note that the trap
+ # must follow switch_to_strict_mode, else it will have no effect.
+ set -e
+ trap 'die_err_trap' ERR
+ if [[ $# -ne 0 ]]; then
+ set "$@"
+ fi
+}
+
+# TODO: Re-enable this once shflags is set -e safe.
+#switch_to_strict_mode
+
+okboat() {
+ # http://www.chris.com/ascii/index.php?art=transportation/nautical
+ echo -e "${V_BOLD_GREEN}"
+ cat </dev/null) ]]; then
+ local pyver=$(ROOT="${root_fs_dir}/usr/local" eselect python show --ABI)
+ if [[ -z ${pyver} ]]; then
+ # TODO(build): Should be able to make this fatal once python-2.7 lands.
+ pyver=$(readlink "${root_fs_dir}"/usr/local/bin/python2 | sed s:python::)
+ fi
+ local python_path="/usr/local/bin/python${pyver}"
+
+ info "Fixing python symlinks for developer and test images."
+ local cmds=() path python_paths=(
+ /usr/{local/,}bin/python
+ /usr/{local/,}bin/python${pyver:0:1}
+ /usr/bin/python${pyver}
+ )
+ for path in "${python_paths[@]}"; do
+ cmds+=(
+ "ln -sfT '${python_path}' '${root_fs_dir}${path}'"
+ )
+ done
+ sudo_multi "${cmds[@]}"
+ fi
+
+ # If bash is not installed on rootfs, we'll need a bash symlink.
+ # Otherwise, emerge won't work.
+ if [[ ! -e "${root_fs_dir}"/bin/bash ]]; then
+ info "Fixing bash path for developer and test images."
+ sudo ln -sf /usr/local/bin/bash "${root_fs_dir}"/bin/bash
+ fi
+
+ setup_etc_shadow "${root_fs_dir}"
+
+ info "Developer image built and stored at ${image_name}"
+
+ unmount_image
+ trap - EXIT
+
+ if [[ ${skip_kernelblock_install} -ne 1 ]]; then
+ if should_build_image ${image_name}; then
+ ${SCRIPTS_DIR}/bin/cros_make_image_bootable "${BUILD_DIR}" \
+ ${image_name} --force_developer_mode
+ fi
+ fi
+}
diff --git a/nichrome/scripts/disk_layout_util.sh b/nichrome/scripts/disk_layout_util.sh
new file mode 100755
index 000000000..4d5b5f4b2
--- /dev/null
+++ b/nichrome/scripts/disk_layout_util.sh
@@ -0,0 +1,600 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# BUILD_LIBRARY_DIR must be set prior to sourcing this file, since this file
+# is sourced as ${BUILD_LIBRARY_DIR}/disk_layout_util.sh
+. "filesystem_util.sh" || exit 1
+
+CGPT_PY="./cgpt.py"
+PARTITION_SCRIPT_PATH="usr/sbin/write_gpt.sh"
+DISK_LAYOUT_PATH=
+
+cgpt_py() {
+ if [[ -n "${FLAGS_adjust_part-}" ]]; then
+ set -- --adjust_part "${FLAGS_adjust_part}" "$@"
+ if [[ ! -t 0 ]]; then
+ warn "The --adjust_part flag was passed." \
+ "This option must ONLY be used interactively. If" \
+ "you need to pass a size from another script, you're" \
+ "doing it wrong and should be using a disk layout type."
+ fi
+ fi
+ "${CGPT_PY}" "$@"
+}
+
+get_disk_layout_path() {
+ DISK_LAYOUT_PATH="./legacy_disk_layout.json"
+}
+
+write_partition_script() {
+ local image_type=$1
+ local partition_script_path=$2
+ echo "get disk layout"
+ get_disk_layout_path
+
+ local temp_script_file=$(mktemp)
+
+ sudo mkdir -p "$(dirname "${partition_script_path}")"
+
+ echo "cgpty command"
+
+ cgpt_py write "${image_type}" "${DISK_LAYOUT_PATH}" \
+ "${temp_script_file}"
+ sudo mv "${temp_script_file}" "${partition_script_path}"
+ sudo chmod a+r "${partition_script_path}"
+}
+
+run_partition_script() {
+ local outdev=$1
+ local partition_script=$2
+
+ local pmbr_img
+ case ${ARCH} in
+ amd64|x86)
+ pmbr_img=$(readlink -f /usr/share/syslinux/gptmbr.bin)
+ ;;
+ *)
+ pmbr_img=/dev/zero
+ ;;
+ esac
+
+ . "${partition_script}"
+ write_partition_table "${outdev}" "${pmbr_img}"
+}
+
+get_fs_block_size() {
+ get_disk_layout_path
+
+ cgpt_py readfsblocksize "${DISK_LAYOUT_PATH}"
+}
+
+get_block_size() {
+ get_disk_layout_path
+
+ cgpt_py readblocksize "${DISK_LAYOUT_PATH}"
+}
+
+get_image_types() {
+ get_disk_layout_path
+
+ cgpt_py readimagetypes "${DISK_LAYOUT_PATH}"
+}
+
+get_partition_size() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readpartsize "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_filesystem_format() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readfsformat "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_filesystem_options() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readfsoptions "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_format() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readformat "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_partitions() {
+ local image_type=$1
+ get_disk_layout_path
+
+ cgpt_py readpartitionnums "${image_type}" "${DISK_LAYOUT_PATH}"
+}
+
+get_uuid() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readuuid "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_type() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readtype "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_filesystem_size() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readfssize "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_label() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readlabel "${image_type}" "${DISK_LAYOUT_PATH}" "${part_id}"
+}
+
+get_image_partition_number() {
+ local image="$1"
+ local label="$2"
+ local part=$(./cgpt find -n -l "${label}" "${image}")
+ echo "${part}"
+}
+
+get_layout_partition_number() {
+ local image_type=$1
+ local part_label=$2
+ get_disk_layout_path
+
+ cgpt_py readnumber "${image_type}" "${DISK_LAYOUT_PATH}" "${part_label}"
+}
+
+get_reserved_erase_blocks() {
+ local image_type=$1
+ local part_id=$2
+ get_disk_layout_path
+
+ cgpt_py readreservederaseblocks "${image_type}" "${DISK_LAYOUT_PATH}" \
+ ${part_id}
+}
+
+check_valid_layout() {
+ local image_type=$1
+ get_disk_layout_path
+
+ cgpt_py validate "${image_type}" "${DISK_LAYOUT_PATH}" > /dev/null
+}
+
+get_disk_layout_type() {
+ DISK_LAYOUT_TYPE="base"
+ if should_build_image ${CHROMEOS_FACTORY_INSTALL_SHIM_NAME}; then
+ DISK_LAYOUT_TYPE="factory_install"
+ fi
+}
+
+emit_gpt_scripts() {
+ local image="$1"
+ local dir="$2"
+
+ local pack="pack_partitions.sh"
+ local unpack="unpack_partitions.sh"
+ local mount="mount_image.sh"
+ local umount="umount_image.sh"
+
+ local start size part x
+
+ local default
+ # Write out the header for the script.
+ local cgpt_output=$(./cgpt show "${image}")
+ local gpt_layout=$(echo "${cgpt_output}" | sed -e 's/^/# /')
+ for x in "${unpack}" "${pack}" "${mount}" "${umount}"; do
+ cat >"${x}" <<\EOF
+#!/bin/bash -eu
+# File automatically generated. Do not edit.
+
+usage() {
+ local ret=0
+ if [[ $# -gt 0 ]]; then
+ # Write to stderr on errors.
+ exec 1>&2
+ echo "ERROR: $*"
+ echo
+ ret=1
+ fi
+ echo "Usage: $0 [image] [part]"
+ echo "Example: $0 chromiumos_image.bin"
+ exit ${ret}
+}
+
+TARGET=${1:-}
+PART=${2:-}
+case ${TARGET} in
+-h|--help)
+ usage
+ ;;
+"")
+ for TARGET in chromiumos_{,base_}image.bin ""; do
+ if [[ -e ${TARGET} ]]; then
+ echo "autodetected image: ${TARGET}"
+ break
+ fi
+ done
+ if [[ -z ${TARGET} ]]; then
+ usage "could not autodetect an image"
+ fi
+ ;;
+*)
+ if [[ ! -e ${TARGET} ]]; then
+ usage "image does not exist: ${TARGET}"
+ fi
+esac
+
+EOF
+ echo "${gpt_layout}" >> "${x}"
+ done
+
+ # Read each partition and generate code for it.
+ while read start size part x; do
+ local file="part_${part}"
+ local dir="dir_${part}"
+ local target='"${TARGET}"'
+ local dd_args="bs=512 count=${size}"
+ local start_b=$(( start * 512 ))
+ local size_b=$(( size * 512 ))
+ local label=$(./cgpt show "${image}" -i ${part} -l)
+
+ for x in "${unpack}" "${pack}" "${mount}" "${umount}"; do
+ cat <> "${x}"
+case \${PART:-${part}} in
+${part}|"${label}")
+EOF
+ done
+
+ cat <> "${unpack}"
+dd if=${target} of=${file} ${dd_args} skip=${start}
+ln -sfT ${file} "${file}_${label}"
+EOF
+ cat <> "${pack}"
+dd if=${file} of=${target} ${dd_args} seek=${start} conv=notrunc
+EOF
+
+ if [[ ${size} -gt 1 ]]; then
+ cat <<-EOF >>"${mount}"
+(
+mkdir -p ${dir}
+m=( sudo mount -o loop,offset=${start_b},sizelimit=${size_b} ${target} ${dir} )
+if ! "\${m[@]}"; then
+ if ! "\${m[@]}" -o ro; then
+ rmdir ${dir}
+ exit 0
+ fi
+fi
+ln -sfT ${dir} "${dir}_${label}"
+) &
+EOF
+ cat <<-EOF >>"${umount}"
+if [[ -d ${dir} ]]; then
+ (
+ sudo umount ${dir} || :
+ rmdir ${dir}
+ rm -f "${dir}_${label}"
+ ) &
+fi
+EOF
+ fi
+
+ for x in "${unpack}" "${pack}" "${mount}" "${umount}"; do
+ echo "esac" >> "${x}"
+ done
+ done < <(./cgpt show -q "${image}")
+
+ echo "wait" >> "${mount}"
+ echo "wait" >> "${umount}"
+
+ chmod +x "${unpack}" "${pack}" "${mount}" "${umount}"
+}
+
+# Usage: mk_fs
+# Args:
+# image_file: The image file.
+# image_type: The layout name used to look up partition info in disk layout.
+# partition_num: The partition number to look up in the disk layout.
+#
+# Note: After we mount the fs, we will attempt to reset the root dir ownership
+# to 0:0 to workaround a bug in mke2fs (fixed in upstream git now).
+mk_fs() {
+ local image_file=$1
+ local image_type=$2
+ local part_num=$3
+
+ echo "CALLED WITH"
+ echo $1 $2 $3
+
+ # These are often not in non-root $PATH, but they contain tools that
+ # we can run just fine w/non-root users when we work on plain files.
+ local p
+ for p in /sbin /usr/sbin; do
+ if [[ ":${PATH}:" != *:${p}:* ]]; then
+ PATH+=":${p}"
+ fi
+ done
+
+ # Keep `local` decl split from assignment so return code is checked.
+ local fs_bytes fs_label fs_format fs_options fs_block_size offset fs_type
+ fs_format=$(get_filesystem_format ${image_type} ${part_num})
+ echo ${fs_format}
+ fs_options="$(get_filesystem_options ${image_type} ${part_num})"
+ # Split the fs_options into an array.
+ local fs_options_arr=(${fs_options})
+ if [ -z "${fs_format}" ]; then
+ echo "HERE"
+ # We only make fs for partitions that specify a format.
+ return 0
+ fi
+
+ fs_bytes=$(get_filesystem_size ${image_type} ${part_num})
+ fs_block_size=$(get_fs_block_size)
+ echo "HERE"
+ if [ "${fs_bytes}" -le ${fs_block_size} ]; then
+ # Skip partitions that are too small.
+ echo "Skipping partition ${part_num} as the blocksize is too small."
+ return 0
+ fi
+
+ echo "Creating FS for partition ${part_num} with format ${fs_format}."
+
+ fs_label=$(get_label ${image_type} ${part_num})
+ fs_uuid=$(get_uuid ${image_type} ${part_num})
+ fs_type=$(get_type ${image_type} ${part_num})
+ echo "MADE ABBUNCH OF VARIABLES"
+ # Mount at the correct place in the file.
+ offset=$(( $(partoffset "${image_file}" "${part_num}") * 512 ))
+ echo "HERE"
+ # Root is needed to mount on loopback device.
+ # sizelimit is used to denote the FS size for mkfs if not specified.
+ local part_dev=$(sudo losetup -f --show --offset=${offset} \
+ --sizelimit=${fs_bytes} "${image_file}")
+ echo "HERE"
+ if [ ! -e "${part_dev}" ]; then
+ die "No free loopback device to create partition."
+ fi
+
+ echo "HERE"
+ case ${fs_format} in
+ ext[234])
+ # When mke2fs supports the same values for -U as tune2fs does, the
+ # following conditionals can be removed and ${fs_uuid} can be used
+ # as the value of the -U option as-is.
+ echo "HERE"
+ local uuid_option=()
+ if [[ "${fs_uuid}" == "clear" ]]; then
+ fs_uuid="00000000-0000-0000-0000-000000000000"
+ fi
+ echo "HERE"
+ if [[ "${fs_uuid}" != "random" ]]; then
+ uuid_option=( -U "${fs_uuid}" )
+ fi
+ echo "HERE"
+ sudo mkfs.${fs_format} -F -q -O ext_attr \
+ "${uuid_option[@]}" \
+ -E lazy_itable_init=0 \
+ -b ${fs_block_size} "${part_dev}" "$((fs_bytes / fs_block_size))"
+ echo "HERE"
+ # We need to redirect from stdin and clear the prompt variable to make
+ # sure tune2fs doesn't throw up random prompts on us. We know that the
+ # command below is what we want and is safe (it's a new FS).
+ unset TUNE2FS_FORCE_PROMPT
+ echo "HERE"
+ sudo tune2fs -L "${fs_label}" \
+ -c 0 \
+ -i 0 \
+ -T 20091119110000 \
+ -m 0 \
+ -r 0 \
+ -e remount-ro \
+ "${part_dev}" \
+ "${fs_options_arr[@]}" /dev/null
+ rmdir "${squash_dir}"
+ sudo dd if="${squash_file}" of="${part_dev}" bs=4096 status=none
+ rm "${squash_file}"
+ ;;
+ btrfs)
+ sudo mkfs.${fs_format} -b "$((fs_bytes))" -d single -m single -M \
+ -L "${fs_label}" -O "${fs_options_arr[@]}" "${part_dev}"
+ ;;
+ *)
+ die "Unknown fs format '${fs_format}' for part ${part_num}";;
+ esac
+
+ local mount_dir="$(mktemp -d)"
+ local cmds=(
+ # mke2fs is funky and sets the root dir owner to current uid:gid.
+ "chown 0:0 '${mount_dir}' 2>/dev/null || :"
+ )
+
+ # Prepare partitions with well-known mount points.
+ if [ "${fs_label}" = "STATE" ]; then
+ # These directories are used to mount data from stateful onto the rootfs.
+ cmds+=("sudo mkdir '${mount_dir}/dev_image'"
+ "sudo mkdir '${mount_dir}/var_overlay'"
+ )
+ elif [ "${fs_type}" = "rootfs" ]; then
+ # These rootfs mount points are necessary to mount data from other
+ # partitions onto the rootfs. These are used by both build and run times.
+ cmds+=("sudo mkdir -p '${mount_dir}/mnt/stateful_partition'"
+ "sudo mkdir -p '${mount_dir}/usr/local'"
+ "sudo mkdir -p '${mount_dir}/usr/share/oem'"
+ "sudo mkdir '${mount_dir}/var'"
+ )
+ fi
+ fs_mount "${part_dev}" "${mount_dir}" "${fs_format}" "rw"
+ sudo_multi "${cmds[@]}"
+ fs_umount "${part_dev}" "${mount_dir}" "${fs_format}" "${fs_options}"
+ fs_remove_mountpoint "${mount_dir}"
+}
+
+# Creates the gpt image for the given disk layout. In addition to creating
+# the partition layout it creates all the initial filesystems. After this file
+# is created, mount_gpt_image.sh can be used to mount all the filesystems onto
+# directories.
+build_gpt_image() {
+ local outdev="$1"
+ local disk_layout="$2"
+
+ # Build the partition table and partition script.
+ local partition_script_path="$(dirname "${outdev}")/partition_script.sh"
+ echo "writing partition"
+ write_partition_script "${disk_layout}" "${partition_script_path}"
+ run_partition_script "${outdev}" "${partition_script_path}"
+
+ # Emit the gpt scripts so we can use them from here on out.
+ emit_gpt_scripts "${outdev}" "$(dirname "${outdev}")"
+
+ echo "MADE IT HERE"
+ # Create the filesystem on each partition defined in the layout file.
+ local p
+ for p in $(get_partitions "${disk_layout}"); do
+ mk_fs "${outdev}" "${disk_layout}" "${p}"
+ done
+
+ echo "MADE IT RIGHT HERE"
+ # Pre-set "sucessful" bit in gpt, so we will never mark-for-death
+ # a partition on an SDCard/USB stick.
+ ./cgpt add -i $(get_layout_partition_number "${disk_layout}" KERN-A) -S 1 \
+ "${outdev}"
+}
+
+round_up_4096() {
+ local blocks=$1
+ local round_up=$(( blocks % 4096 ))
+ if [ $round_up -ne 0 ]; then
+ blocks=$(( blocks + 4096 - round_up ))
+ fi
+ echo $blocks
+}
+
+# Rebuild an image's partition table with new stateful size.
+# $1: source image filename
+# $2: source stateful partition image filename
+# $3: number of sectors to allocate to the new stateful partition
+# $4: destination image filename
+# Used by dev/host/tests/mod_recovery_for_decryption.sh and
+# mod_image_for_recovery.sh.
+update_partition_table() {
+ local src_img=$1 # source image
+ local src_state=$2 # stateful partition image
+ local dst_stateful_blocks=$3 # number of blocks in resized stateful partition
+ local dst_img=$4
+
+ rm -f "${dst_img}"
+
+ # Find partition number of STATE.
+ local part=0
+ local label=""
+ while [ "${label}" != "STATE" ]; do
+ part=$(( part + 1 ))
+ local label=$(./cgpt show -i ${part} -l ${src_img})
+ local src_start=$(./cgpt show -i ${part} -b ${src_img})
+ if [ ${src_start} -eq 0 ]; then
+ echo "Could not find 'STATE' partition" >&2
+ return 1
+ fi
+ done
+
+ # Make sure new stateful's size is a multiple of 4096 blocks so that
+ # relocated partitions following it are not misaligned.
+ dst_stateful_blocks=$(round_up_4096 $dst_stateful_blocks)
+ # Calculate change in image size.
+ local src_stateful_blocks=$(./cgpt show -i ${part} -s ${src_img})
+ local delta_blocks=$(( dst_stateful_blocks - src_stateful_blocks ))
+ local dst_stateful_bytes=$(( dst_stateful_blocks * 512 ))
+ local src_stateful_bytes=$(( src_stateful_blocks * 512 ))
+ local src_size=$(stat -c %s ${src_img})
+ local dst_size=$(( src_size - src_stateful_bytes + dst_stateful_bytes ))
+ truncate -s ${dst_size} ${dst_img}
+
+ # Copy MBR, initialize GPT.
+ dd if="${src_img}" of="${dst_img}" conv=notrunc bs=512 count=1 status=none
+ ./cgpt create ${dst_img}
+
+ local src_state_start=$(./cgpt show -i ${part} -b ${src_img})
+
+ # Duplicate each partition entry.
+ part=0
+ while :; do
+ part=$(( part + 1 ))
+ local src_start=$(./cgpt show -i ${part} -b ${src_img})
+ if [ ${src_start} -eq 0 ]; then
+ # No more partitions to copy.
+ break
+ fi
+ local dst_start=${src_start}
+ # Load source partition details.
+ local size=$(./cgpt show -i ${part} -s ${src_img})
+ local label=$(./cgpt show -i ${part} -l ${src_img})
+ local attr=$(./cgpt show -i ${part} -A ${src_img})
+ local tguid=$(./cgpt show -i ${part} -t ${src_img})
+ local uguid=$(./cgpt show -i ${part} -u ${src_img})
+ if [[ ${size} -eq 0 ]]; then
+ continue
+ fi
+ # Change size of stateful.
+ if [ "${label}" = "STATE" ]; then
+ size=${dst_stateful_blocks}
+ fi
+ # Partitions located after STATE need to have their start moved.
+ if [ ${src_start} -gt ${src_state_start} ]; then
+ dst_start=$(( dst_start + delta_blocks ))
+ fi
+ # Add this partition to the destination.
+ ./cgpt add -i ${part} -b ${dst_start} -s ${size} -l "${label}" -A ${attr} \
+ -t ${tguid} -u ${uguid} ${dst_img}
+ if [ "${label}" != "STATE" ]; then
+ # Copy source partition as-is.
+ dd if="${src_img}" of="${dst_img}" conv=notrunc bs=512 \
+ skip=${src_start} seek=${dst_start} count=${size} status=none
+ else
+ # Copy new stateful partition into place.
+ dd if="${src_state}" of="${dst_img}" conv=notrunc bs=512 \
+ seek=${dst_start} status=none
+ fi
+ done
+ return 0
+}
diff --git a/nichrome/scripts/filesystem_util.sh b/nichrome/scripts/filesystem_util.sh
new file mode 100644
index 000000000..ec22ca798
--- /dev/null
+++ b/nichrome/scripts/filesystem_util.sh
@@ -0,0 +1,184 @@
+# Copyright 2015 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# . "${BUILD_LIBRARY_DIR}/common.sh" || exit 1
+
+# Usage: fs_parse_option [default_value]
+#
+# Print the value associated with the option_key in the passed mount_options,
+# or the optional default_value if it wasn't specified.
+#
+# Args:
+# mount_options: Options that could be passed to the "mount" command, for
+# example "loop,ro,offset=1234".
+# option_key: The key you are looking for.
+# default_value: An optional default value used if the option key is not
+# found.
+fs_parse_option() {
+ # If we are mounting a partition inside a device by passing an offset
+ # in the mount options, we need to tell unsquashfs to read from there.
+ local mount_options="$1"
+ local option_key="$2"
+ local default_value="${3:-}"
+
+ local option_value
+ if option_value=$(echo "${mount_options}" | tr , '\n' | \
+ grep -E "^${option_key}"'(=|$)'); then
+ echo "${option_value}" | cut --fields=2 --delimiter== --only-delimited
+ else
+ echo "${default_value}"
+ fi
+}
+
+# Usage: fs_mount [ro_rw] [mount_options]
+#
+# Mount the passed partition device in the mount point. The partition is mounted
+# as the fs_format filesystem (if fs_format is not empty). If the filesystem
+# doesn't support to be mounted as read-write, like for example squashfs or
+# ubifs, and "rw" mount is requested the contents are copied instead. When
+# unmounted, the contents will be copied back to the partition, but you need to
+# unmount the filesystem calling fs_umount.
+#
+# Args:
+# part_dev: A block device with the partition to mount.
+# mount_point: A directory where to mount the filesystem.
+# fs_format: The filesystem format, such as for example "ext2" or "squashfs".
+# ro_rw: The ro_rw parameter should be "ro" or "rw" (the default if empty).
+# mount_options: Extra mount options passed to the command "mount" when used.
+fs_mount() {
+ local part_dev="$1"
+ local mount_point="$2"
+ local fs_format="$3"
+ local ro_rw="${4:-rw}"
+ local mount_options="${5:-}"
+
+ if [[ "${ro_rw}" != "ro" && "${ro_rw}" != "rw" ]]; then
+ die "ro_rw must be \"ro\" or \"rw\", not \"${ro_rw}\"."
+ fi
+
+ local all_options="${ro_rw}"
+ [[ -n "${mount_options}" ]] && all_options="${ro_rw},${mount_options}"
+
+ # TODO: move this to layout file.(crbug.com/710929)
+ case ${fs_format} in
+ btrfs) all_options+=",compress=zlib";;
+ esac
+
+ case ${fs_format} in
+ ext[234]|fat12|fat16|fat32|fat|vfat|btrfs|"")
+ local extra_flags=()
+ [[ -n "${fs_format}" ]] && extra_flags=( -t "${fs_format}" )
+ sudo mount "${part_dev}" "${mount_point}" -o "${all_options}" \
+ "${extra_flags[@]}"
+ ;;
+ squashfs)
+ if [[ "${ro_rw}" == "ro" ]]; then
+ sudo mount "${part_dev}" "${mount_point}" -o "${all_options}" \
+ -t "${fs_format}"
+ else
+ local offset=$(fs_parse_option "${mount_options}" offset 0)
+ local sizelimit=$(fs_parse_option "${mount_options}" sizelimit)
+ local sizelimit_arg=""
+ if [[ "${offset}" != "0" || -n "${sizelimit}" ]]; then
+ local losetup_opts=( --show --read-only --offset "${offset}" )
+ if [[ -n "${sizelimit}" ]]; then
+ losetup_opts+=( --sizelimit "${sizelimit}" )
+ fi
+ part_dev=$(sudo losetup "${losetup_opts[@]}" -f "${part_dev}")
+ fi
+
+ sudo unsquashfs -dest "${mount_point}" -no-progress -force "${part_dev}"
+
+ if [[ "${offset}" != "0" ]]; then
+ # Cleanup the loop device used to unsquash the filesystem.
+ sudo losetup -d "${part_dev}"
+ fi
+ fi
+ ;;
+ *)
+ die "Unknown fs format '${fs_format}'";;
+ esac
+}
+
+# Usage: fs_umount \
+# [mount_options]
+#
+# Unmount the partition mounted with fs_mount.
+#
+# Args:
+# part_dev: The block device with the partition that was mounted.
+# mount_point: The directory where the partition was mounted.
+# fs_format: The filesystem format, such as for example "ext2" or "squashfs".
+# fs_options: The options used when creating the filesystem. These options are
+# used when we need to recreate the fs.
+# mount_options: Extra mount options passed to the command "mount" when used.
+# Only the "offset=" options is considering while unmounting.
+fs_umount() {
+ local part_dev="$1"
+ local mount_point="$2"
+ local fs_format="$3"
+ local fs_options="$4"
+ local mount_options="${5:-}"
+
+ if mountpoint -q "${mount_point}"; then
+ # First use safe_umount_tree for the general case. This also unmounts
+ # mount points created with "mount --bind" in the filesystem.
+ safe_umount_tree "${mount_point}"
+ return
+ fi
+
+ case ${fs_format} in
+ ext[234]|fat12|fat16|fat32|fat|vfat|"")
+ # Nothing else to do for these filesystems.
+ ;;
+ squashfs)
+ # Unmount anything else that could be mounted in the filesystem before
+ # re-squashing.
+ safe_umount_tree "${mount_point}"
+
+ # Re-squash the filesystem to a temporary file.
+ local squash_file="$(mktemp --suffix=.squashfs)"
+ local fs_options_arr=(${fs_options})
+ # If there are errors in mkquashfs they are sent to stderr, but in the
+ # normal case a lot of useless information is sent to stdout.
+ sudo mksquashfs "${mount_point}" "${squash_file}" -noappend \
+ -no-progress -no-recovery "${fs_options_arr[@]}" >/dev/null
+
+ local sizelimit=$(fs_parse_option "${mount_options}" sizelimit)
+ local squashed_size=$(stat -c%s "${squash_file}")
+
+ if [[ -n "${sizelimit}" && "${sizelimit}" -lt "${squashed_size}" ]]; then
+ sudo rm -f "${squash_file}"
+ die "The squashfs filesystem mounted at ${mount_point} is "\
+"${squashed_size} bytes but the sizelimit is ${sizelimit} bytes, about "\
+"$(( (squashed_size - sizelimit) / 1024 )) KiB smaller. Please increase the "\
+"size of your filesystem or remove some files from it."
+ fi
+
+ local offset=$(fs_parse_option "${mount_options}" offset 0)
+ # mksquashfs pads the filesystem up to 4kB, but we can use a bigger block
+ # size to improve speed.
+ sudo dd if="${squash_file}" of="${part_dev}" bs=8M seek="${offset}" \
+ oflag=seek_bytes conv=notrunc status=none
+ sudo rm -f "${squash_file}"
+ ;;
+ *)
+ die "Unknown fs format '${fs_format}'";;
+ esac
+}
+
+# Usage: fs_remove_mountpoint
+#
+# fs_umount will unmount the filesystem but will keep the mount point
+# directory. When using squashfs in rw mode, the contents of the filesystem
+# will remain in the mount point directory.
+# This function removes the mountpoint directory as long as it is not mounted.
+# Returns whether it was successfully removed.
+fs_remove_mountpoint() {
+ local mount_point="$1"
+ safe_umount_tree "${mount_point}" || return
+ if ! mountpoint -q "${mount_point}"; then
+ sudo rm -rf "${mount_point}"
+ fi
+}
diff --git a/nichrome/scripts/kernels/linux.bin b/nichrome/scripts/kernels/linux.bin
new file mode 100644
index 000000000..607b794ad
Binary files /dev/null and b/nichrome/scripts/kernels/linux.bin differ
diff --git a/nichrome/scripts/legacy_disk_layout.json b/nichrome/scripts/legacy_disk_layout.json
new file mode 100755
index 000000000..0e7c253b7
--- /dev/null
+++ b/nichrome/scripts/legacy_disk_layout.json
@@ -0,0 +1,246 @@
+{
+ # See README_disk_layout
+ "parent": "common_disk_layout.json",
+
+ "metadata": {
+ "block_size": 512,
+ "fs_block_size": 4096
+ },
+ "layouts": {
+ # common is the standard layout template.
+ "common": [
+ {
+ # Reserve space for RW firmware. Only used on some boards.
+ "num": 11,
+ "label": "RWFW",
+ "type": "firmware",
+ "size": "8 MiB"
+ },
+ {
+ # Unused partition, reserved for software slot C.
+ "num": 6,
+ "label": "KERN-C",
+ "type": "kernel",
+ "blocks": "1"
+ },
+ {
+ # Unused partition, reserved for software slot C.
+ "num": 7,
+ "label": "ROOT-C",
+ "type": "rootfs",
+ "blocks": "1"
+ },
+ {
+ # Unused partition, reserved for future changes.
+ "num": 9,
+ "type": "reserved",
+ "label": "reserved",
+ "blocks": "1"
+ },
+ {
+ # Unused partition, reserved for future changes.
+ "num": 10,
+ "type": "reserved",
+ "label": "reserved",
+ "blocks": "1"
+ },
+ {
+ # Pad out so Kernel A starts on a 4096 block boundry for
+ # performance. This is especially important on Daisy.
+ "type": "blank",
+ "size": "2014 KiB"
+ },
+ {
+ # Kernel for Slot A, no file system.
+ "num": 2,
+ "label": "KERN-A",
+ "type": "kernel",
+ "size": "16 MiB"
+ },
+ {
+ # Kernel for Slot B, no file system.
+ "num": 4,
+ "label": "KERN-B",
+ "type": "kernel",
+ "size": "16 MiB"
+ },
+ {
+ # Board specific files, mostly unused.
+ "num": 8,
+ "label": "OEM",
+ "type": "data",
+ "fs_format": "ext4",
+ "size": "16 MiB",
+ "uuid": "random"
+ },
+ {
+ # Pad out, but not sure why.
+ "type": "blank",
+ "size": "64 MiB"
+ },
+ {
+ # Used for Legacy Bios, and EFI Bios, not ChromeOS hardware
+ "num": 12,
+ "label": "EFI-SYSTEM",
+ "type": "efi",
+ "fs_format": "vfat",
+ "size": "32 MiB",
+ "uuid": "clear"
+ },
+ {
+ # Slot B rootfs. Must match Root A in side for normal
+ # updates. Will contain copy of Root A after install, and
+ # contain new rootfs's after runtime updates.
+ "num": 5,
+ "label": "ROOT-B",
+ "type": "rootfs",
+ "size": "2048 MiB"
+ },
+ {
+ # Slot A rootfs. Rootfs + extras must fit.
+ # FS size + Verity (64 * FS blocks) + Boot Cache (200M).
+ # Make sure that other layouts still has room for the
+ # extras, should you increase FS size
+ #
+ # Note that updates will fail if the rootfs size
+ # shrinks. (crbug.com/192136)
+ #
+ # Changes to the offset of this partition may require
+ # changes in cros-signing/security_test_baselines/
+ # ensure_secure_kernelparams.config to allow secure boot.
+ "num": 3,
+ "label": "ROOT-A",
+ "type": "rootfs",
+ "fs_format": "ext2",
+ "fs_options": {
+ "squashfs": "-noI -comp lzo -Xalgorithm lzo1x_999 -Xcompression-level 9",
+ "btrfs": "skinny-metadata"
+ },
+ "size": "2048 MiB",
+ "fs_size": "1240 MiB",
+ "uuid": "clear"
+ },
+ {
+ # User data, fills all remaining space on drive.
+ "num": 1,
+ "label": "STATE",
+ "type": "data",
+ "fs_format": "ext4",
+ "size": "1216 MiB",
+ "features": ["expand"],
+ "uuid": "random"
+ }
+ ],
+ # Used for installs on main device
+ # by default, same as 'common'.
+ "base": [
+ ],
+ # Used for bootable USB installs (not recovery).
+ "usb": [
+ {
+ # Slot B rootfs, unused on USB, but pad to 2M.
+ # installation will expand this to size from base.
+ "num": 5,
+ "size": "2 MiB"
+ },
+ {
+ # Shrunken rootfs partition to support smaller USB sticks.
+ # installation will expand this to size from base.
+ "num": 3,
+ "size": "1290 MiB"
+ }
+ ],
+ # Used for factory install images.
+ "factory_install": [
+ {
+ "num": 12,
+ "size": "32 MiB"
+ },
+ {
+ "num": 5,
+ "size": "2 MiB"
+ },
+ {
+ "num": 3,
+ "size": "420 MiB",
+ "fs_size": "400 MiB"
+ },
+ {
+ "num": 1,
+ "size": "140 MiB"
+ }
+ ],
+ # Used for recovery images.
+ "recovery": [
+ {
+ # Slot B rootfs, unused on USB, but pad to 2M.
+ # installation will expand this to size from base.
+ "num": 5,
+ "size": "2 MiB"
+ },
+ {
+ # Shrunken rootfs partition to support smaller USB sticks,
+ # and smaller recovery downloads.
+ # Installation will expand this to size from base.
+ # The offset to the beginning of this partition, and the FS
+ # size must match base exactly to allow secure boot.
+ "num": 3,
+ "size": "1290 MiB"
+ },
+ {
+ # Stateful on recovery is dynamically resized larger.
+ "num": 1,
+ "size": "2 MiB"
+ }
+ ],
+ # Larger rootfs, suitable for development with symbols, etc.
+ # Cannot apply updates when running from USB (no slot B).
+ "2gb-rootfs": [
+ {
+ # Will be grown to size from base on install.
+ "num": 5,
+ "size": "2 MiB"
+ },
+ {
+ # Will be shrunk to size from base on install.
+ "num": 3,
+ "size": "2048 MiB",
+ "fs_size": "2000 MiB"
+ }
+ ],
+ # Larger rootfs, suitable for development with symbols, etc.
+ # CAN apply updates when running from USB.
+ "2gb-rootfs-updatable": [
+ {
+ # The partition size matches base, so it's installable.
+ "num": 5,
+ "size": "2048 MiB"
+ },
+ {
+ # The partition size matches base, so it's installable.
+ "num": 3,
+ "size": "2048 MiB",
+ "fs_size": "2000 MiB"
+ },
+ {
+ "num": 1,
+ "size": "4 GiB"
+ }
+ ],
+ # Very large rootfs, suitable for development with symbols,
+ # etc. Cannot apply updates when running from USB (no slot B)
+ "4gb-rootfs": [
+ {
+ "num": 5,
+ "size": "2 MiB"
+ },
+ {
+ # This partition is larger than the base partition, so the
+ # installer will corrupt the disk during installation.
+ "num": 3,
+ "size": "4096 MiB",
+ "fs_size": "4000 MiB"
+ }
+ ]
+ }
+}
diff --git a/nichrome/scripts/lib/shflags/README.chromium b/nichrome/scripts/lib/shflags/README.chromium
new file mode 100644
index 000000000..388689236
--- /dev/null
+++ b/nichrome/scripts/lib/shflags/README.chromium
@@ -0,0 +1 @@
+This is r137 of shflags
diff --git a/nichrome/scripts/lib/shflags/shflags b/nichrome/scripts/lib/shflags/shflags
new file mode 100644
index 000000000..773e0f3d8
--- /dev/null
+++ b/nichrome/scripts/lib/shflags/shflags
@@ -0,0 +1,1009 @@
+# $Id: shflags 133 2009-05-10 18:04:51Z kate.ward@forestent.com $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# shFlags -- Advanced command-line flag library for Unix shell scripts.
+# http://code.google.com/p/shflags/
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# This module implements something like the google-gflags library available
+# from http://code.google.com/p/google-gflags/.
+#
+# FLAG TYPES: This is a list of the DEFINE_*'s that you can do. All flags take
+# a name, default value, help-string, and optional 'short' name (one-letter
+# name). Some flags have other arguments, which are described with the flag.
+#
+# DEFINE_string: takes any input, and intreprets it as a string.
+#
+# DEFINE_boolean: typically does not take any argument: say --myflag to set
+# FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
+# Alternately, you can say
+# --myflag=true or --myflag=t or --myflag=0 or
+# --myflag=false or --myflag=f or --myflag=1
+# Passing an option has the same affect as passing the option once.
+#
+# DEFINE_float: takes an input and intreprets it as a floating point number. As
+# shell does not support floats per-se, the input is merely validated as
+# being a valid floating point value.
+#
+# DEFINE_integer: takes an input and intreprets it as an integer.
+#
+# SPECIAL FLAGS: There are a few flags that have special meaning:
+# --help (or -?) prints a list of all the flags in a human-readable fashion
+# --flagfile=foo read flags from foo. (not implemented yet)
+# -- as in getopt(), terminates flag-processing
+#
+# EXAMPLE USAGE:
+#
+# -- begin hello.sh --
+# #! /bin/sh
+# . ./shflags
+# DEFINE_string name 'world' "somebody's name" n
+# FLAGS "$@" || exit $?
+# eval set -- "${FLAGS_ARGV}"
+# echo "Hello, ${FLAGS_name}."
+# -- end hello.sh --
+#
+# $ ./hello.sh -n Kate
+# Hello, Kate.
+#
+# NOTE: Not all systems include a getopt version that supports long flags. On
+# these systems, only short flags are recognized.
+
+#==============================================================================
+# shFlags
+#
+# Shared attributes:
+# flags_error: last error message
+# flags_return: last return value
+#
+# __flags_longNames: list of long names for all flags
+# __flags_shortNames: list of short names for all flags
+# __flags_boolNames: list of boolean flag names
+#
+# __flags_opts: options parsed by getopt
+#
+# Per-flag attributes:
+# FLAGS_: contains value of flag named 'flag_name'
+# __flags__default: the default flag value
+# __flags__help: the flag help string
+# __flags__short: the flag short name
+# __flags__type: the flag type
+#
+# Notes:
+# - lists of strings are space separated, and a null value is the '~' char.
+
+# return if FLAGS already loaded
+[ -n "${FLAGS_VERSION:-}" ] && return 0
+FLAGS_VERSION='1.0.3'
+
+# return values
+FLAGS_TRUE=0
+FLAGS_FALSE=1
+FLAGS_ERROR=2
+
+# reserved flag names
+FLAGS_RESERVED='ARGC ARGV ERROR FALSE HELP PARENT RESERVED TRUE VERSION'
+
+_flags_debug() { echo "flags:DEBUG $@" >&2; }
+_flags_warn() { echo "flags:WARN $@" >&2; }
+_flags_error() { echo "flags:ERROR $@" >&2; }
+_flags_fatal() { echo "flags:FATAL $@" >&2; }
+
+# specific shell checks
+if [ -n "${ZSH_VERSION:-}" ]; then
+ setopt |grep "^shwordsplit$" >/dev/null
+ if [ $? -ne ${FLAGS_TRUE} ]; then
+ _flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
+ exit ${FLAGS_ERROR}
+ fi
+ if [ -z "${FLAGS_PARENT:-}" ]; then
+ _flags_fatal "zsh does not pass \$0 through properly. please declare' \
+\"FLAGS_PARENT=\$0\" before calling shFlags"
+ exit ${FLAGS_ERROR}
+ fi
+fi
+
+#
+# constants
+#
+
+# getopt version
+__FLAGS_GETOPT_VERS_STD=0
+__FLAGS_GETOPT_VERS_ENH=1
+__FLAGS_GETOPT_VERS_BSD=2
+
+getopt >/dev/null 2>&1
+case $? in
+ 0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;; # bsd getopt
+ 2)
+ # TODO(kward): look into '-T' option to test the internal getopt() version
+ if [ "`getopt --version`" = '-- ' ]; then
+ __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
+ else
+ __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
+ fi
+ ;;
+ *)
+ _flags_fatal 'unable to determine getopt version'
+ exit ${FLAGS_ERROR}
+ ;;
+esac
+
+# getopt optstring lengths
+__FLAGS_OPTSTR_SHORT=0
+__FLAGS_OPTSTR_LONG=1
+
+__FLAGS_NULL='~'
+
+# flag info strings
+__FLAGS_INFO_DEFAULT='default'
+__FLAGS_INFO_HELP='help'
+__FLAGS_INFO_SHORT='short'
+__FLAGS_INFO_TYPE='type'
+
+# flag lengths
+__FLAGS_LEN_SHORT=0
+__FLAGS_LEN_LONG=1
+
+# flag types
+__FLAGS_TYPE_NONE=0
+__FLAGS_TYPE_BOOLEAN=1
+__FLAGS_TYPE_FLOAT=2
+__FLAGS_TYPE_INTEGER=3
+__FLAGS_TYPE_STRING=4
+
+# set the constants readonly
+__flags_constants=`set |awk -F= '/^FLAGS_/ || /^__FLAGS_/ {print $1}'`
+for __flags_const in ${__flags_constants}; do
+ # skip certain flags
+ case ${__flags_const} in
+ FLAGS_HELP) continue ;;
+ FLAGS_PARENT) continue ;;
+ esac
+ # set flag readonly
+ if [ -z "${ZSH_VERSION:-}" ]; then
+ readonly ${__flags_const}
+ else # handle zsh
+ case ${ZSH_VERSION} in
+ [123].*) readonly ${__flags_const} ;;
+ *) readonly -g ${__flags_const} ;; # declare readonly constants globally
+ esac
+ fi
+done
+unset __flags_const __flags_constants
+
+#
+# internal variables
+#
+
+__flags_boolNames=' ' # space separated list of boolean flag names
+__flags_longNames=' ' # space separated list of long flag names
+__flags_shortNames=' ' # space separated list of short flag names
+
+__flags_columns='' # screen width in columns
+__flags_opts='' # temporary storage for parsed getopt flags
+
+#------------------------------------------------------------------------------
+# private functions
+#
+
+# Define a flag.
+#
+# Calling this function will define the following info variables for the
+# specified flag:
+# FLAGS_flagname - the name for this flag (based upon the long flag name)
+# __flags__default - the default value
+# __flags_flagname_help - the help string
+# __flags_flagname_short - the single letter alias
+# __flags_flagname_type - the type of flag (one of __FLAGS_TYPE_*)
+#
+# Args:
+# _flags__type: integer: internal type of flag (__FLAGS_TYPE_*)
+# _flags__name: string: long flag name
+# _flags__default: default flag value
+# _flags__help: string: help string
+# _flags__short: string: (optional) short flag name
+# Returns:
+# integer: success of operation, or error
+_flags_define()
+{
+ if [ $# -lt 4 ]; then
+ flags_error='DEFINE error: too few arguments'
+ flags_return=${FLAGS_ERROR}
+ _flags_error "${flags_error}"
+ return ${flags_return}
+ fi
+
+ _flags_type_=$1
+ _flags_name_=$2
+ _flags_default_=$3
+ _flags_help_=$4
+ _flags_short_=${5:-${__FLAGS_NULL}}
+
+ _flags_return_=${FLAGS_TRUE}
+
+ # TODO(kward): check for validity of the flag name (e.g. dashes)
+
+ # check whether the flag name is reserved
+ echo " ${FLAGS_RESERVED} " |grep " ${_flags_name_} " >/dev/null
+ if [ $? -eq 0 ]; then
+ flags_error="flag name (${_flags_name_}) is reserved"
+ _flags_return_=${FLAGS_ERROR}
+ fi
+
+ # require short option for getopt that don't support long options
+ if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
+ -a ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} \
+ -a "${_flags_short_}" = "${__FLAGS_NULL}" ]
+ then
+ flags_error="short flag required for (${_flags_name_}) on this platform"
+ _flags_return_=${FLAGS_ERROR}
+ fi
+
+ # check for existing long name definition
+ if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+ if _flags_itemInList "${_flags_name_}" \
+ ${__flags_longNames} ${__flags_boolNames}
+ then
+ flags_error="flag name ([no]${_flags_name_}) already defined"
+ _flags_warn "${flags_error}"
+ _flags_return_=${FLAGS_FALSE}
+ fi
+ fi
+
+ # check for existing short name definition
+ if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
+ -a "${_flags_short_}" != "${__FLAGS_NULL}" ]
+ then
+ if _flags_itemInList "${_flags_short_}" ${__flags_shortNames}; then
+ flags_error="flag short name (${_flags_short_}) already defined"
+ _flags_warn "${flags_error}"
+ _flags_return_=${FLAGS_FALSE}
+ fi
+ fi
+
+ # handle default value. note, on several occasions the 'if' portion of an
+ # if/then/else contains just a ':' which does nothing. a binary reversal via
+ # '!' is not done because it does not work on all shells.
+ if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+ case ${_flags_type_} in
+ ${__FLAGS_TYPE_BOOLEAN})
+ if _flags_validateBoolean "${_flags_default_}"; then
+ case ${_flags_default_} in
+ true|t|0) _flags_default_=${FLAGS_TRUE} ;;
+ false|f|1) _flags_default_=${FLAGS_FALSE} ;;
+ esac
+ else
+ flags_error="invalid default flag value '${_flags_default_}'"
+ _flags_return_=${FLAGS_ERROR}
+ fi
+ ;;
+
+ ${__FLAGS_TYPE_FLOAT})
+ if _flags_validateFloat "${_flags_default_}"; then
+ :
+ else
+ flags_error="invalid default flag value '${_flags_default_}'"
+ _flags_return_=${FLAGS_ERROR}
+ fi
+ ;;
+
+ ${__FLAGS_TYPE_INTEGER})
+ if _flags_validateInteger "${_flags_default_}"; then
+ :
+ else
+ flags_error="invalid default flag value '${_flags_default_}'"
+ _flags_return_=${FLAGS_ERROR}
+ fi
+ ;;
+
+ ${__FLAGS_TYPE_STRING}) ;; # everything in shell is a valid string
+
+ *)
+ flags_error="unrecognized flag type '${_flags_type_}'"
+ _flags_return_=${FLAGS_ERROR}
+ ;;
+ esac
+ fi
+
+ if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+ # store flag information
+ eval "FLAGS_${_flags_name_}='${_flags_default_}'"
+ eval "__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
+ eval "__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}=\
+\"${_flags_default_}\""
+ eval "__flags_${_flags_name_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
+ eval "__flags_${_flags_name_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
+
+ # append flag name(s) to list of names
+ __flags_longNames="${__flags_longNames}${_flags_name_} "
+ __flags_shortNames="${__flags_shortNames}${_flags_short_} "
+ [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
+ __flags_boolNames="${__flags_boolNames}no${_flags_name_} "
+ fi
+
+ flags_return=${_flags_return_}
+ unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ _flags_short_ \
+ _flags_type_
+ [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
+ return ${flags_return}
+}
+
+# Return valid getopt options using currently defined list of long options.
+#
+# This function builds a proper getopt option string for short (and long)
+# options, using the current list of long options for reference.
+#
+# Args:
+# _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
+# Output:
+# string: generated option string for getopt
+# Returns:
+# boolean: success of operation (always returns True)
+_flags_genOptStr()
+{
+ _flags_optStrType_=$1
+
+ _flags_opts_=''
+
+ for _flags_flag_ in ${__flags_longNames}; do
+ _flags_type_=`_flags_getFlagInfo ${_flags_flag_} ${__FLAGS_INFO_TYPE}`
+ case ${_flags_optStrType_} in
+ ${__FLAGS_OPTSTR_SHORT})
+ _flags_shortName_=`_flags_getFlagInfo \
+ ${_flags_flag_} ${__FLAGS_INFO_SHORT}`
+ if [ "${_flags_shortName_}" != "${__FLAGS_NULL}" ]; then
+ _flags_opts_="${_flags_opts_}${_flags_shortName_}"
+ # getopt needs a trailing ':' to indicate a required argument
+ [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
+ _flags_opts_="${_flags_opts_}:"
+ fi
+ ;;
+
+ ${__FLAGS_OPTSTR_LONG})
+ _flags_opts_="${_flags_opts_:+${_flags_opts_},}${_flags_flag_}"
+ # getopt needs a trailing ':' to indicate a required argument
+ [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
+ _flags_opts_="${_flags_opts_}:"
+ ;;
+ esac
+ done
+
+ echo "${_flags_opts_}"
+ unset _flags_flag_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
+ _flags_type_
+ return ${FLAGS_TRUE}
+}
+
+# Returns flag details based on a flag name and flag info.
+#
+# Args:
+# string: long flag name
+# string: flag info (see the _flags_define function for valid info types)
+# Output:
+# string: value of dereferenced flag variable
+# Returns:
+# integer: one of FLAGS_{TRUE|FALSE|ERROR}
+_flags_getFlagInfo()
+{
+ _flags_name_=$1
+ _flags_info_=$2
+
+ _flags_nameVar_="__flags_${_flags_name_}_${_flags_info_}"
+ _flags_strToEval_="_flags_value_=\"\${${_flags_nameVar_}:-}\""
+ eval "${_flags_strToEval_}"
+ if [ -n "${_flags_value_}" ]; then
+ flags_return=${FLAGS_TRUE}
+ else
+ # see if the _flags_name_ variable is a string as strings can be empty...
+ # note: the DRY principle would say to have this function call itself for
+ # the next three lines, but doing so results in an infinite loop as an
+ # invalid _flags_name_ will also not have the associated _type variable.
+ # Because it doesn't (it will evaluate to an empty string) the logic will
+ # try to find the _type variable of the _type variable, and so on. Not so
+ # good ;-)
+ _flags_typeVar_="__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}"
+ _flags_strToEval_="_flags_type_=\"\${${_flags_typeVar_}:-}\""
+ eval "${_flags_strToEval_}"
+ if [ "${_flags_type_}" = "${__FLAGS_TYPE_STRING}" ]; then
+ flags_return=${FLAGS_TRUE}
+ else
+ flags_return=${FLAGS_ERROR}
+ flags_error="invalid flag name (${_flags_nameVar_})"
+ fi
+ fi
+
+ echo "${_flags_value_}"
+ unset _flags_info_ _flags_name_ _flags_strToEval_ _flags_type_ _flags_value_ \
+ _flags_nameVar_ _flags_typeVar_
+ [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
+ return ${flags_return}
+}
+
+# check for presense of item in a list. passed a string (e.g. 'abc'), this
+# function will determine if the string is present in the list of strings (e.g.
+# ' foo bar abc ').
+#
+# Args:
+# _flags__str: string: string to search for in a list of strings
+# unnamed: list: list of strings
+# Returns:
+# boolean: true if item is in the list
+_flags_itemInList()
+{
+ _flags_str_=$1
+ shift
+
+ echo " ${*:-} " |grep " ${_flags_str_} " >/dev/null
+ if [ $? -eq 0 ]; then
+ flags_return=${FLAGS_TRUE}
+ else
+ flags_return=${FLAGS_FALSE}
+ fi
+
+ unset _flags_str_
+ return ${flags_return}
+}
+
+# Returns the width of the current screen.
+#
+# Output:
+# integer: width in columns of the current screen.
+_flags_columns()
+{
+ if [ -z "${__flags_columns}" ]; then
+ # determine the value and store it
+ if eval stty size >/dev/null 2>&1; then
+ # stty size worked :-)
+ set -- `stty size`
+ __flags_columns=$2
+ elif eval tput cols >/dev/null 2>&1; then
+ set -- `tput cols`
+ __flags_columns=$1
+ else
+ __flags_columns=80 # default terminal width
+ fi
+ fi
+ echo ${__flags_columns}
+}
+
+# Validate a boolean.
+#
+# Args:
+# _flags__bool: boolean: value to validate
+# Returns:
+# bool: true if the value is a valid boolean
+_flags_validateBoolean()
+{
+ _flags_bool_=$1
+
+ flags_return=${FLAGS_TRUE}
+ case "${_flags_bool_}" in
+ true|t|0) ;;
+ false|f|1) ;;
+ *) flags_return=${FLAGS_FALSE} ;;
+ esac
+
+ unset _flags_bool_
+ return ${flags_return}
+}
+
+# Validate a float.
+#
+# Args:
+# _flags__float: float: value to validate
+# Returns:
+# bool: true if the value is a valid float
+_flags_validateFloat()
+{
+ _flags_float_=$1
+
+ if _flags_validateInteger ${_flags_float_}; then
+ flags_return=${FLAGS_TRUE}
+ else
+ flags_return=${FLAGS_TRUE}
+ case ${_flags_float_} in
+ -*) # negative floats
+ _flags_test_=`expr "${_flags_float_}" : '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
+ ;;
+ *) # positive floats
+ _flags_test_=`expr "${_flags_float_}" : '\([0-9][0-9]*\.[0-9][0-9]*\)'`
+ ;;
+ esac
+ [ "${_flags_test_}" != "${_flags_float_}" ] && flags_return=${FLAGS_FALSE}
+ fi
+
+ unset _flags_float_ _flags_test_
+ return ${flags_return}
+}
+
+# Validate an integer.
+#
+# Args:
+# _flags__integer: interger: value to validate
+# Returns:
+# bool: true if the value is a valid integer
+_flags_validateInteger()
+{
+ _flags_int_=$1
+
+ flags_return=${FLAGS_TRUE}
+ case ${_flags_int_} in
+ -*) # negative ints
+ _flags_test_=`expr "${_flags_int_}" : '\(-[0-9][0-9]*\)'`
+ ;;
+ *) # positive ints
+ _flags_test_=`expr "${_flags_int_}" : '\([0-9][0-9]*\)'`
+ ;;
+ esac
+ [ "${_flags_test_}" != "${_flags_int_}" ] && flags_return=${FLAGS_FALSE}
+
+ unset _flags_int_ _flags_test_
+ return ${flags_return}
+}
+
+# Parse command-line options using the standard getopt.
+#
+# Note: the flag options are passed around in the global __flags_opts so that
+# the formatting is not lost due to shell parsing and such.
+#
+# Args:
+# @: varies: command-line options to parse
+# Returns:
+# integer: a FLAGS success condition
+_flags_getoptStandard()
+{
+ flags_return=${FLAGS_TRUE}
+ _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
+
+ # check for spaces in passed options
+ for _flags_opt_ in "$@"; do
+ # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
+ _flags_match_=`echo "x${_flags_opt_}x" |sed 's/ //g'`
+ if [ "${_flags_match_}" != "x${_flags_opt_}x" ]; then
+ flags_error='the available getopt does not support spaces in options'
+ flags_return=${FLAGS_ERROR}
+ break
+ fi
+ done
+
+ if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
+ __flags_opts=`getopt ${_flags_shortOpts_} $@ 2>&1`
+ _flags_rtrn_=$?
+ if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
+ _flags_warn "${__flags_opts}"
+ flags_error='unable to parse provided options with getopt.'
+ flags_return=${FLAGS_ERROR}
+ fi
+ fi
+
+ unset _flags_match_ _flags_opt_ _flags_rtrn_ _flags_shortOpts_
+ return ${flags_return}
+}
+
+# Parse command-line options using the enhanced getopt.
+#
+# Note: the flag options are passed around in the global __flags_opts so that
+# the formatting is not lost due to shell parsing and such.
+#
+# Args:
+# @: varies: command-line options to parse
+# Returns:
+# integer: a FLAGS success condition
+_flags_getoptEnhanced()
+{
+ flags_return=${FLAGS_TRUE}
+ _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
+ _flags_boolOpts_=`echo "${__flags_boolNames}" \
+ |sed 's/^ *//;s/ *$//;s/ /,/g'`
+ _flags_longOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
+
+ __flags_opts=`getopt \
+ -o ${_flags_shortOpts_} \
+ -l "${_flags_longOpts_},${_flags_boolOpts_}" \
+ -- "$@" 2>&1`
+ _flags_rtrn_=$?
+ if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
+ _flags_warn "${__flags_opts}"
+ flags_error='unable to parse provided options with getopt.'
+ flags_return=${FLAGS_ERROR}
+ fi
+
+ unset _flags_boolOpts_ _flags_longOpts_ _flags_rtrn_ _flags_shortOpts_
+ return ${flags_return}
+}
+
+# Dynamically parse a getopt result and set appropriate variables.
+#
+# This function does the actual conversion of getopt output and runs it through
+# the standard case structure for parsing. The case structure is actually quite
+# dynamic to support any number of flags.
+#
+# Args:
+# argc: int: original command-line argument count
+# @: varies: output from getopt parsing
+# Returns:
+# integer: a FLAGS success condition
+_flags_parseGetopt()
+{
+ _flags_argc_=$1
+ shift
+
+ flags_return=${FLAGS_TRUE}
+
+ if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
+ set -- $@
+ else
+ # note the quotes around the `$@' -- they are essential!
+ eval set -- "$@"
+ fi
+
+ # provide user with number of arguments to shift by later
+ # NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not
+ # properly give user access to non-flag arguments mixed in between flag
+ # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only
+ # for backwards compatibility reasons.
+ FLAGS_ARGC=`expr $# - 1 - ${_flags_argc_}`
+
+ # handle options. note options with values must do an additional shift
+ while true; do
+ _flags_opt_=$1
+ _flags_arg_=${2:-}
+ _flags_type_=${__FLAGS_TYPE_NONE}
+ _flags_name_=''
+
+ # determine long flag name
+ case "${_flags_opt_}" in
+ --) shift; break ;; # discontinue option parsing
+
+ --*) # long option
+ _flags_opt_=`expr "${_flags_opt_}" : '--\(.*\)'`
+ _flags_len_=${__FLAGS_LEN_LONG}
+ if _flags_itemInList "${_flags_opt_}" ${__flags_longNames}; then
+ _flags_name_=${_flags_opt_}
+ else
+ # check for negated long boolean version
+ if _flags_itemInList "${_flags_opt_}" ${__flags_boolNames}; then
+ _flags_name_=`expr "${_flags_opt_}" : 'no\(.*\)'`
+ _flags_type_=${__FLAGS_TYPE_BOOLEAN}
+ _flags_arg_=${__FLAGS_NULL}
+ fi
+ fi
+ ;;
+
+ -*) # short option
+ _flags_opt_=`expr "${_flags_opt_}" : '-\(.*\)'`
+ _flags_len_=${__FLAGS_LEN_SHORT}
+ if _flags_itemInList "${_flags_opt_}" ${__flags_shortNames}; then
+ # yes. match short name to long name. note purposeful off-by-one
+ # (too high) with awk calculations.
+ _flags_pos_=`echo "${__flags_shortNames}" \
+ |awk 'BEGIN{RS=" ";rn=0}$0==e{rn=NR}END{print rn}' \
+ e=${_flags_opt_}`
+ _flags_name_=`echo "${__flags_longNames}" \
+ |awk 'BEGIN{RS=" "}rn==NR{print $0}' rn="${_flags_pos_}"`
+ fi
+ ;;
+ esac
+
+ # die if the flag was unrecognized
+ if [ -z "${_flags_name_}" ]; then
+ flags_error="unrecognized option (${_flags_opt_})"
+ flags_return=${FLAGS_ERROR}
+ break
+ fi
+
+ # set new flag value
+ [ ${_flags_type_} -eq ${__FLAGS_TYPE_NONE} ] && \
+ _flags_type_=`_flags_getFlagInfo \
+ "${_flags_name_}" ${__FLAGS_INFO_TYPE}`
+ case ${_flags_type_} in
+ ${__FLAGS_TYPE_BOOLEAN})
+ if [ ${_flags_len_} -eq ${__FLAGS_LEN_LONG} ]; then
+ if [ "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
+ eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
+ else
+ eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
+ fi
+ else
+ _flags_strToEval_="_flags_val_=\
+\${__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}}"
+ eval "${_flags_strToEval_}"
+ if [ ${_flags_val_} -eq ${FLAGS_FALSE} ]; then
+ eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
+ else
+ eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
+ fi
+ fi
+ ;;
+
+ ${__FLAGS_TYPE_FLOAT})
+ if _flags_validateFloat "${_flags_arg_}"; then
+ eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+ else
+ flags_error="invalid float value (${_flags_arg_})"
+ flags_return=${FLAGS_ERROR}
+ break
+ fi
+ ;;
+
+ ${__FLAGS_TYPE_INTEGER})
+ if _flags_validateInteger "${_flags_arg_}"; then
+ eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+ else
+ flags_error="invalid integer value (${_flags_arg_})"
+ flags_return=${FLAGS_ERROR}
+ break
+ fi
+ ;;
+
+ ${__FLAGS_TYPE_STRING})
+ eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+ ;;
+ esac
+
+ # handle special case help flag
+ if [ "${_flags_name_}" = 'help' ]; then
+ if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then
+ flags_help
+ flags_error='help requested'
+ flags_return=${FLAGS_FALSE}
+ break
+ fi
+ fi
+
+ # shift the option and non-boolean arguements out.
+ shift
+ [ ${_flags_type_} != ${__FLAGS_TYPE_BOOLEAN} ] && shift
+ done
+
+ # give user back non-flag arguments
+ FLAGS_ARGV=''
+ while [ $# -gt 0 ]; do
+ FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} }'$1'"
+ shift
+ done
+
+ unset _flags_arg_ _flags_len_ _flags_name_ _flags_opt_ _flags_pos_ \
+ _flags_strToEval_ _flags_type_ _flags_val_
+ return ${flags_return}
+}
+
+#------------------------------------------------------------------------------
+# public functions
+#
+
+# A basic boolean flag. Boolean flags do not take any arguments, and their
+# value is either 1 (false) or 0 (true). For long flags, the false value is
+# specified on the command line by prepending the word 'no'. With short flags,
+# the presense of the flag toggles the current value between true and false.
+# Specifying a short boolean flag twice on the command results in returning the
+# value back to the default value.
+#
+# A default value is required for boolean flags.
+#
+# For example, lets say a Boolean flag was created whose long name was 'update'
+# and whose short name was 'x', and the default value was 'false'. This flag
+# could be explicitly set to 'true' with '--update' or by '-x', and it could be
+# explicitly set to 'false' with '--noupdate'.
+DEFINE_boolean() { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@"; }
+
+# Other basic flags.
+DEFINE_float() { _flags_define ${__FLAGS_TYPE_FLOAT} "$@"; }
+DEFINE_integer() { _flags_define ${__FLAGS_TYPE_INTEGER} "$@"; }
+DEFINE_string() { _flags_define ${__FLAGS_TYPE_STRING} "$@"; }
+
+# Parse the flags.
+#
+# Args:
+# unnamed: list: command-line flags to parse
+# Returns:
+# integer: success of operation, or error
+FLAGS()
+{
+ # define a standard 'help' flag if one isn't already defined
+ [ -z "${__flags_help_type:-}" ] && \
+ DEFINE_boolean 'help' false 'show this help' 'h'
+
+ # parse options
+ if [ $# -gt 0 ]; then
+ if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
+ _flags_getoptStandard "$@"
+ else
+ _flags_getoptEnhanced "$@"
+ fi
+ flags_return=$?
+ else
+ # nothing passed; won't bother running getopt
+ __flags_opts='--'
+ flags_return=${FLAGS_TRUE}
+ fi
+
+ if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
+ _flags_parseGetopt $# "${__flags_opts}"
+ flags_return=$?
+ fi
+
+ [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}"
+ return ${flags_return}
+}
+
+# This is a helper function for determining the `getopt` version for platforms
+# where the detection isn't working. It simply outputs debug information that
+# can be included in a bug report.
+#
+# Args:
+# none
+# Output:
+# debug info that can be included in a bug report
+# Returns:
+# nothing
+flags_getoptInfo()
+{
+ # platform info
+ _flags_debug "uname -a: `uname -a`"
+ _flags_debug "PATH: ${PATH}"
+
+ # shell info
+ if [ -n "${BASH_VERSION:-}" ]; then
+ _flags_debug 'shell: bash'
+ _flags_debug "BASH_VERSION: ${BASH_VERSION}"
+ elif [ -n "${ZSH_VERSION:-}" ]; then
+ _flags_debug 'shell: zsh'
+ _flags_debug "ZSH_VERSION: ${ZSH_VERSION}"
+ fi
+
+ # getopt info
+ getopt >/dev/null
+ _flags_getoptReturn=$?
+ _flags_debug "getopt return: ${_flags_getoptReturn}"
+ _flags_debug "getopt --version: `getopt --version 2>&1`"
+
+ unset _flags_getoptReturn
+}
+
+# Returns whether the detected getopt version is the enhanced version.
+#
+# Args:
+# none
+# Output:
+# none
+# Returns:
+# bool: true if getopt is the enhanced version
+flags_getoptIsEnh()
+{
+ test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH}
+}
+
+# Returns whether the detected getopt version is the standard version.
+#
+# Args:
+# none
+# Returns:
+# bool: true if getopt is the standard version
+flags_getoptIsStd()
+{
+ test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD}
+}
+
+# This is effectively a 'usage()' function. It prints usage information and
+# exits the program with ${FLAGS_FALSE} if it is ever found in the command line
+# arguments. Note this function can be overridden so other apps can define
+# their own --help flag, replacing this one, if they want.
+#
+# Args:
+# none
+# Returns:
+# integer: success of operation (always returns true)
+flags_help()
+{
+ if [ -n "${FLAGS_HELP:-}" ]; then
+ echo "${FLAGS_HELP}" >&2
+ else
+ echo "USAGE: ${FLAGS_PARENT:-$0} [flags] args" >&2
+ fi
+ if [ -n "${__flags_longNames}" ]; then
+ echo 'flags:' >&2
+ for flags_name_ in ${__flags_longNames}; do
+ flags_flagStr_=''
+ flags_boolStr_=''
+
+ flags_default_=`_flags_getFlagInfo \
+ "${flags_name_}" ${__FLAGS_INFO_DEFAULT}`
+ flags_help_=`_flags_getFlagInfo \
+ "${flags_name_}" ${__FLAGS_INFO_HELP}`
+ flags_short_=`_flags_getFlagInfo \
+ "${flags_name_}" ${__FLAGS_INFO_SHORT}`
+ flags_type_=`_flags_getFlagInfo \
+ "${flags_name_}" ${__FLAGS_INFO_TYPE}`
+
+ [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
+ && flags_flagStr_="-${flags_short_}"
+
+ if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
+ [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
+ && flags_flagStr_="${flags_flagStr_},"
+ [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] \
+ && flags_boolStr_='[no]'
+ flags_flagStr_="${flags_flagStr_}--${flags_boolStr_}${flags_name_}:"
+ fi
+
+ case ${flags_type_} in
+ ${__FLAGS_TYPE_BOOLEAN})
+ if [ ${flags_default_} -eq ${FLAGS_TRUE} ]; then
+ flags_defaultStr_='true'
+ else
+ flags_defaultStr_='false'
+ fi
+ ;;
+ ${__FLAGS_TYPE_FLOAT}|${__FLAGS_TYPE_INTEGER})
+ flags_defaultStr_=${flags_default_} ;;
+ ${__FLAGS_TYPE_STRING}) flags_defaultStr_="'${flags_default_}'" ;;
+ esac
+ flags_defaultStr_="(default: ${flags_defaultStr_})"
+
+ flags_helpStr_=" ${flags_flagStr_} ${flags_help_} ${flags_defaultStr_}"
+ flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
+ flags_columns_=`_flags_columns`
+ if [ ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
+ echo "${flags_helpStr_}" >&2
+ else
+ echo " ${flags_flagStr_} ${flags_help_}" >&2
+ # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
+ # because it doesn't like empty strings when used in this manner.
+ flags_emptyStr_="`echo \"x${flags_flagStr_}x\" \
+ |awk '{printf "%"length($0)-2"s", ""}'`"
+ flags_helpStr_=" ${flags_emptyStr_} ${flags_defaultStr_}"
+ flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
+ if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} \
+ -o ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
+ # indented to match help string
+ echo "${flags_helpStr_}" >&2
+ else
+ # indented four from left to allow for longer defaults as long flag
+ # names might be used too, making things too long
+ echo " ${flags_defaultStr_}" >&2
+ fi
+ fi
+ done
+ fi
+
+ unset flags_boolStr_ flags_default_ flags_defaultStr_ flags_emptyStr_ \
+ flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
+ flags_columns_ flags_short_ flags_type_
+ return ${FLAGS_TRUE}
+}
+
+# Reset shflags back to an uninitialized state.
+#
+# Args:
+# none
+# Returns:
+# nothing
+flags_reset()
+{
+ for flags_name_ in ${__flags_longNames}; do
+ flags_strToEval_="unset FLAGS_${flags_name_}"
+ for flags_type_ in \
+ ${__FLAGS_INFO_DEFAULT} \
+ ${__FLAGS_INFO_HELP} \
+ ${__FLAGS_INFO_SHORT} \
+ ${__FLAGS_INFO_TYPE}
+ do
+ flags_strToEval_=\
+"${flags_strToEval_} __flags_${flags_name_}_${flags_type_}"
+ done
+ eval ${flags_strToEval_}
+ done
+
+ # reset internal variables
+ __flags_boolNames=' '
+ __flags_longNames=' '
+ __flags_shortNames=' '
+
+ unset flags_name_ flags_type_ flags_strToEval_
+}
diff --git a/nichrome/scripts/make_bootable_usb.sh b/nichrome/scripts/make_bootable_usb.sh
new file mode 100755
index 000000000..e69de29bb
diff --git a/nichrome/scripts/mount_gpt_image.sh b/nichrome/scripts/mount_gpt_image.sh
new file mode 100755
index 000000000..ab6eadffd
--- /dev/null
+++ b/nichrome/scripts/mount_gpt_image.sh
@@ -0,0 +1,425 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Helper script that mounts chromium os image from a device or directory
+# and creates mount points for /var and /usr/local (if in dev_mode).
+
+# Helper scripts should be run from the same location as this script.
+SCRIPT_ROOT=$(dirname "$(readlink -f "$0")")
+. "common.sh" || exit 1
+. "filesystem_util.sh" || exit 1
+. "disk_layout_util.sh" || exit 1
+
+# Load functions and constants for chromeos-install
+. "chromeos-common.sh" || exit 1
+
+locate_gpt
+
+# Default value for FLAGS_image.
+DEFAULT_IMAGE="chromiumos_image.bin"
+
+# Flags.
+DEFINE_string board "$DEFAULT_BOARD" \
+ "The board for which the image was built." b
+DEFINE_boolean read_only ${FLAGS_FALSE} \
+ "Mount in read only mode -- skips stateful items."
+DEFINE_boolean safe ${FLAGS_FALSE} \
+ "Mount rootfs in read only mode."
+DEFINE_boolean unmount ${FLAGS_FALSE} \
+ "Unmount previously mounted image. Can't be used with --remount." u
+DEFINE_boolean remount ${FLAGS_FALSE} \
+ "Remount a previously mounted image. This is useful when changing the "\
+"--read_only and --safe settings. Can't be used with --unmount."
+DEFINE_string from "" \
+ "Directory, image, or device with image on it" f
+DEFINE_string image "${DEFAULT_IMAGE}" \
+ "Name of the bin file if a directory is specified in the from flag" i
+DEFINE_string partition_script "partition_script.sh" \
+ "Name of the script with the partition layout if a directory is specified"
+DEFINE_string rootfs_mountpt "/tmp/m" "Mount point for rootfs" r
+DEFINE_string stateful_mountpt "/tmp/s" \
+ "Mount point for stateful partition" s
+DEFINE_string esp_mountpt "" \
+ "Mount point for esp partition" e
+DEFINE_boolean delete_mountpts ${FLAGS_FALSE} \
+ "Delete the mountpoint directories when unmounting."
+DEFINE_boolean most_recent ${FLAGS_FALSE} "Use the most recent image dir" m
+
+# Parse flags
+FLAGS "$@" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+# Die on error
+switch_to_strict_mode
+
+# Find the last image built on the board.
+if [[ ${FLAGS_most_recent} -eq ${FLAGS_TRUE} ]] ; then
+ FLAGS_from="$(${SCRIPT_ROOT}/get_latest_image.sh --board="${FLAGS_board}")"
+fi
+
+# Check for conflicting args.
+if [[ ${FLAGS_unmount} -eq ${FLAGS_TRUE} &&
+ ${FLAGS_remount} -eq ${FLAGS_TRUE} ]]; then
+ die_notrace "Can't use --unmount with --remount."
+fi
+
+# If --from is a block device, --image can't also be specified.
+if [[ -b "${FLAGS_from}" ]]; then
+ if [[ "${FLAGS_image}" != "${DEFAULT_IMAGE}" ]]; then
+ die_notrace "-i ${FLAGS_image} can't be used with block device ${FLAGS_from}"
+ fi
+fi
+
+# Allow --from /foo/file.bin
+if [[ -f "${FLAGS_from}" ]]; then
+ # If --from is specified as a file, --image cannot be also specified.
+ if [[ "${FLAGS_image}" != "${DEFAULT_IMAGE}" ]]; then
+ die_notrace "-i ${FLAGS_image} can't be used with --from file ${FLAGS_from}"
+ fi
+ # The order is important here. We want to override FLAGS_image before
+ # destroying FLAGS_from.
+ FLAGS_image="$(basename "${FLAGS_from}")"
+ FLAGS_from="$(dirname "${FLAGS_from}")"
+fi
+
+# Usage: get_partition_size
+#
+# Print the partition size for the given partition number by looking either
+# at the partition_script values (if loaded) or the GPT in the passed image.
+#
+# This function fails (returns 1) if the partition is empty, not present in the
+# GPT image or failed to get the size for any other reason.
+get_partition_size() {
+ local filename="$1"
+ local part_num="$2"
+ if [[ -z "${part_num}" ]]; then
+ error "Skipping blank partition number."
+ return 1
+ fi
+ local part_size var_name
+
+ var_name="PARTITION_SIZE_${part_num}"
+ part_size="${!var_name}"
+ if [[ -z "${part_size}" ]]; then
+ part_size=$(partsize "${filename}" ${part_num}) || true
+ if [[ -z "${part_size}" ]]; then
+ info "Skipping unknown partition ${part_num}."
+ return 1
+ fi
+ fi
+ if [[ ${part_size} -eq 0 ]]; then
+ info "Skipping empty partition ${part_num}."
+ return 1
+ fi
+ echo "${part_size}"
+ return 0
+}
+
+load_image_partition_numbers() {
+ local partition_script="${FLAGS_from}/${FLAGS_partition_script}"
+ # Attempt to load the partition script from the rootfs when not found in the
+ # FLAGS_from directory.
+ if [[ ! -f "${partition_script}" ]]; then
+ partition_script="${FLAGS_rootfs_mountpt}/${PARTITION_SCRIPT_PATH}"
+ fi
+ if [[ -f "${partition_script}" ]]; then
+ . "${partition_script}"
+ load_partition_vars
+ return
+ fi
+
+ # Without a partition script, infer numbers from the payload image.
+ local image
+ if [[ -b "${FLAGS_from}" ]]; then
+ image="${FLAGS_from}"
+ else
+ image="${FLAGS_from}/${FLAGS_image}"
+ if [[ ! -f "${image}" ]]; then
+ die "Image ${image} does not exist."
+ fi
+ fi
+ PARTITION_NUM_STATE="$(get_image_partition_number "${image}" "STATE")"
+ PARTITION_NUM_ROOT_A="$(get_image_partition_number "${image}" "ROOT-A")"
+ PARTITION_NUM_OEM="$(get_image_partition_number "${image}" "OEM")"
+ PARTITION_NUM_EFI_SYSTEM="$(get_image_partition_number "${image}" \
+ "EFI-SYSTEM")"
+}
+
+# Common unmounts for either a device or directory
+unmount_image() {
+ info "Unmounting image from ${FLAGS_stateful_mountpt}" \
+ "and ${FLAGS_rootfs_mountpt}"
+ # Don't die on error to force cleanup
+ set +e
+ # Reset symlinks in /usr/local.
+ if mount | egrep -q ".* ${FLAGS_stateful_mountpt} .*\(rw,"; then
+ setup_symlinks_on_root "." "/var" "${FLAGS_stateful_mountpt}"
+ fix_broken_symlinks "${FLAGS_rootfs_mountpt}"
+ fi
+
+ local filename
+ if [[ -b "${FLAGS_from}" ]]; then
+ filename="${FLAGS_from}"
+ else
+ filename="${FLAGS_from}/${FLAGS_image}"
+ if [[ ! -f "${filename}" ]]; then
+ if [[ "${FLAGS_image}" == "${DEFAULT_IMAGE}" ]]; then
+ warn "Umount called without passing the image. Some filesystems can't" \
+ "be unmounted in this way."
+ filename=""
+ else
+ die "Image ${filename} does not exist."
+ fi
+ fi
+ fi
+
+ # Unmount in reverse order: EFI, OEM, stateful and rootfs.
+ local var_name mountpoint fs_format fs_options
+ local part_label part_num part_offset part_size data_size
+ for part_label in EFI_SYSTEM OEM STATE ROOT_A; do
+ var_name="${part_label}_MOUNTPOINT"
+ mountpoint="${!var_name}"
+ [[ -n "${mountpoint}" ]] || continue
+ var_name="PARTITION_NUM_${part_label}"
+ part_num="${!var_name}"
+ [[ -n "${part_num}" ]] || continue
+
+ part_size=$(get_partition_size "${filename}" "${part_num}") || continue
+
+ if [[ -z "${filename}" ]]; then
+ # TODO(deymo): Remove this legacy umount.
+ if ! mountpoint -q "${mountpoint}"; then
+ die "You must pass --image or --from when using --unmount to unmount" \
+ "this image."
+ fi
+ safe_umount_tree "${mountpoint}"
+ continue
+ fi
+
+ part_offset=$(partoffset "${filename}" ${part_num}) || \
+ die "Failed to get partition offset for partition ${part_num}"
+ # Get the variables loaded with load_partition_vars during mount_*.
+ var_name="FS_FORMAT_${part_num}"
+ fs_format="${!var_name}"
+ var_name="FS_OPTIONS_${part_num}"
+ fs_options="${!var_name}"
+ var_name="DATA_SIZE_${part_num}"
+ data_size="${!var_name}"
+
+ mount_options="offset=$(( part_offset * 512 ))"
+ if [[ -n "${data_size}" ]]; then
+ mount_options+=",sizelimit=${data_size}"
+ fi
+ fs_umount "${filename}" "${mountpoint}" "${fs_format}" "${fs_options}" \
+ "${mount_options}"
+ done
+
+ # We need to remove the mountpoints after we unmount all the partitions since
+ # there could be nested mounts.
+ if [[ ${FLAGS_delete_mountpts} -eq ${FLAGS_TRUE} ]]; then
+ for part_label in EFI_SYSTEM OEM STATE ROOT_A; do
+ var_name="${part_label}_MOUNTPOINT"
+ mountpoint="${!var_name}"
+ # Check this is a directory.
+ [[ -n "${mountpoint}" && -d "${mountpoint}" ]] || continue
+ fs_remove_mountpoint "${mountpoint}"
+ done
+ fi
+
+ switch_to_strict_mode
+}
+
+mount_usb_partitions() {
+ local ro_rw="rw"
+ local rootfs_ro_rw="rw"
+ if [[ ${FLAGS_read_only} -eq ${FLAGS_TRUE} ]]; then
+ ro_rw="ro"
+ fi
+ if [[ ${FLAGS_read_only} -eq ${FLAGS_TRUE} ||
+ ${FLAGS_safe} -eq ${FLAGS_TRUE} ]]; then
+ rootfs_ro_rw="ro"
+ fi
+
+ if [[ -f "${FLAGS_from}/${FLAGS_partition_script}" ]]; then
+ . "${FLAGS_from}/${FLAGS_partition_script}"
+ load_partition_vars
+ fi
+
+ fs_mount "${FLAGS_from}${PARTITION_NUM_ROOT_A}" "${ROOT_A_MOUNTPOINT}" \
+ "${FS_FORMAT_ROOT_A}" "${rootfs_ro_rw}"
+ fs_mount "${FLAGS_from}${PARTITION_NUM_STATE}" "${STATE_MOUNTPOINT}" \
+ "${FS_FORMAT_STATE}" "${ro_rw}"
+ fs_mount "${FLAGS_from}${PARTITION_NUM_OEM}" "${OEM_MOUNTPOINT}" \
+ "${FS_FORMAT_OEM}" "${ro_rw}"
+
+ if [[ -n "${FLAGS_esp_mountpt}" && \
+ -e ${FLAGS_from}${PARTITION_NUM_EFI_SYSTEM} ]]; then
+ fs_mount "${FLAGS_from}${PARTITION_NUM_EFI_SYSTEM}" \
+ "${EFI_SYSTEM_MOUNTPOINT}" "${FS_FORMAT_EFI_SYSTEM}" "${ro_rw}"
+ fi
+}
+
+mount_gpt_partitions() {
+ local filename="${FLAGS_from}/${FLAGS_image}"
+
+ local ro_rw="rw"
+ if [[ ${FLAGS_read_only} -eq ${FLAGS_TRUE} ]]; then
+ ro_rw="ro"
+ fi
+
+ if [[ ! -f "${filename}" ]]; then
+ die "Image ${filename} does not exist."
+ fi
+
+ if [[ -f "${FLAGS_from}/${FLAGS_partition_script}" ]]; then
+ . "${FLAGS_from}/${FLAGS_partition_script}"
+ load_partition_vars
+ fi
+
+ if [[ ${FLAGS_read_only} -eq ${FLAGS_FALSE} && \
+ ${FLAGS_safe} -eq ${FLAGS_FALSE} ]]; then
+ local rootfs_offset=$(partoffset "${filename}" ${PARTITION_NUM_ROOT_A})
+ # Make sure any callers can actually mount and modify the fs
+ # if desired.
+ # cros_make_image_bootable should restore the bit if needed.
+ enable_rw_mount "${filename}" "$(( rootfs_offset * 512 ))"
+ fi
+
+ # Mount in order: rootfs, stateful, OEM and EFI.
+ local var_name mountpoint fs_format
+ local part_label part_num part_offset part_size part_ro_rw
+ for part_label in ROOT_A STATE OEM EFI_SYSTEM; do
+ var_name="${part_label}_MOUNTPOINT"
+ mountpoint="${!var_name}"
+ [[ -n "${mountpoint}" ]] || continue
+
+ var_name="PARTITION_NUM_${part_label}"
+ part_num="${!var_name}"
+ [[ -n "${part_num}" ]] || continue
+
+ part_size=$(get_partition_size "${filename}" ${part_num}) || continue
+ part_offset=$(partoffset "${filename}" ${part_num}) ||
+ die "Failed to get partition offset for partition ${part_num}"
+ var_name="FS_FORMAT_${part_num}"
+ fs_format="${!var_name}"
+
+ # The "safe" flags tells if the rootfs should be mounted as read-only,
+ # otherwise we use ${ro_rw}.
+ part_ro_rw="${ro_rw}"
+ if [[ ${part_num} -eq ${PARTITION_NUM_ROOT_A} && \
+ ${FLAGS_safe} -eq ${FLAGS_TRUE} ]]; then
+ part_ro_rw="ro"
+ fi
+ mount_options="offset=$(( part_offset * 512 ))"
+
+ if ! fs_mount "${filename}" "${mountpoint}" "${fs_format}" \
+ "${part_ro_rw}" "${mount_options}"; then
+ error "mount failed: device=${filename}" \
+ "target=${mountpoint} format=${fs_format} ro/rw=${part_ro_rw}" \
+ "options=${mount_options}"
+ return 1
+ fi
+ done
+}
+
+# Mount a gpt based image.
+mount_image() {
+ mkdir -p "${FLAGS_rootfs_mountpt}"
+ mkdir -p "${FLAGS_stateful_mountpt}"
+ if [[ -n "${FLAGS_esp_mountpt}" ]]; then
+ mkdir -p "${FLAGS_esp_mountpt}"
+ fi
+ # Get the partitions for the image / device.
+ if [[ -b "${FLAGS_from}" ]]; then
+ mount_usb_partitions
+ elif ! mount_gpt_partitions; then
+ echo "Current loopback device status:"
+ sudo losetup --all | sed 's/^/ /'
+ die "Failed to mount all partitions in ${FLAGS_from}/${FLAGS_image}"
+ fi
+
+ # Mount directories and setup symlinks.
+ sudo mount --bind "${FLAGS_stateful_mountpt}" \
+ "${FLAGS_rootfs_mountpt}/mnt/stateful_partition"
+ sudo mount --bind "${FLAGS_stateful_mountpt}/var_overlay" \
+ "${FLAGS_rootfs_mountpt}/var"
+ sudo mount --bind "${FLAGS_stateful_mountpt}/dev_image" \
+ "${FLAGS_rootfs_mountpt}/usr/local"
+
+ # Setup symlinks in /usr/local so you can emerge packages into /usr/local.
+ if [[ ${FLAGS_read_only} -eq ${FLAGS_FALSE} ]]; then
+ setup_symlinks_on_root "." \
+ "${FLAGS_stateful_mountpt}/var_overlay" "${FLAGS_stateful_mountpt}"
+ fi
+ info "Image specified by ${FLAGS_from} mounted at"\
+ "${FLAGS_rootfs_mountpt} successfully."
+}
+
+# Remount a previously mounted gpt based image.
+remount_image() {
+ local ro_rw="rw"
+ if [[ ${FLAGS_read_only} -eq ${FLAGS_TRUE} ]]; then
+ ro_rw="ro"
+ fi
+
+ # If all the filesystems are mounted via the kernel, just issue the remount
+ # command with the proper flags.
+ local var_name mountpoint
+ local part_label part_num part_ro_rw part_size
+ for part_label in ROOT_A STATE OEM EFI_SYSTEM; do
+ var_name="${part_label}_MOUNTPOINT"
+ mountpoint="${!var_name}"
+ [[ -n "${mountpoint}" ]] || continue
+
+ var_name="PARTITION_NUM_${part_label}"
+ part_num="${!var_name}"
+
+ part_size=$(get_partition_size "${filename}" ${part_num}) || continue
+
+ if ! mountpoint -q "${mountpoint}"; then
+ # Fallback to unmount everything and re-mount everything.
+ info "Fallback --remount to --unmount and then --remount."
+ unmount_image
+ mount_image
+ return
+ fi
+
+ # The "safe" flags tells if the rootfs should be mounted as read-only,
+ # otherwise we use ${ro_rw}.
+ part_ro_rw="${ro_rw}"
+ if [[ ${part_num} -eq ${PARTITION_NUM_ROOT_A} && \
+ ${FLAGS_safe} -eq ${FLAGS_TRUE} ]]; then
+ part_ro_rw="ro"
+ fi
+
+ sudo mount "${mountpoint}" -o "remount,${part_ro_rw}"
+ done
+}
+
+# Turn paths into absolute paths.
+[[ -n "${FLAGS_from}" ]] && FLAGS_from="$(readlink -f "${FLAGS_from}")"
+FLAGS_rootfs_mountpt="$(readlink -f "${FLAGS_rootfs_mountpt}")"
+FLAGS_stateful_mountpt="$(readlink -f "${FLAGS_stateful_mountpt}")"
+
+# Partition mountpoints based on the flags.
+ROOT_A_MOUNTPOINT="${FLAGS_rootfs_mountpt}"
+STATE_MOUNTPOINT="${FLAGS_stateful_mountpt}"
+OEM_MOUNTPOINT="${FLAGS_rootfs_mountpt}/usr/share/oem"
+EFI_SYSTEM_MOUNTPOINT="${FLAGS_esp_mountpt}"
+
+whereis fs_mount
+# Read the image partition numbers from the GPT.
+load_image_partition_numbers
+
+# Perform desired operation.
+if [[ ${FLAGS_unmount} -eq ${FLAGS_TRUE} ]]; then
+ unmount_image
+elif [[ ${FLAGS_remount} -eq ${FLAGS_TRUE} ]]; then
+ remount_image
+else
+ mount_image
+
+fi
diff --git a/nichrome/scripts/mount_gpt_util.sh b/nichrome/scripts/mount_gpt_util.sh
new file mode 100755
index 000000000..4a46ca003
--- /dev/null
+++ b/nichrome/scripts/mount_gpt_util.sh
@@ -0,0 +1,103 @@
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This global array variable is used to remember options from
+# mount_image so that unmount_image can do its job.
+MOUNT_GPT_OPTIONS=( )
+
+# Usage: _check_mount_image_flags [mode_flag ...]
+#
+# Check that all the passed flags only modify the read or write access of the
+# mounted image when passed to mount_gpt_image.sh.
+# Args:
+# mode_flag ...: 0 or more flags.
+_check_mount_image_flags() {
+ local flag
+ for flag; do
+ case "${flag}" in
+ --read_only|--safe) ;;
+ *)
+ die "Invalid flag '${flag}'."
+ esac
+ done
+}
+
+# Usage: mount_image image rootfs_mountpt stateful_mountpt esp_mountpt \
+# [esp_mount] [mode_flag]
+#
+# Mount the root, stateful, and optionally ESP partitions in a Chromium OS
+# image. Create the mountpoints when needed.
+# Args:
+# image: path to image to be mounted.
+# rootfs_mountpt: path to root fs mount point.
+# stateful_mountpt: path to stateful fs mount point.
+# esp_mount: optional path to ESP fs mount point; if empty the ESP will not be
+# mounted.
+# mode_flag: Optional flag to control how the image is mounted:
+# --read-only mounts all partitions as read-only.
+# --safe, mounts only the rootfs as read-only and the rest as read/write.
+# If omitted, the image will be mounted read-write. See mount_gpt_image.sh
+# for details on these flags, and remount_image to modify this flag after it
+# is mounted.
+mount_image() {
+ MOUNT_GPT_OPTIONS=(
+ --from "$1"
+ --rootfs_mountpt "$2"
+ --stateful_mountpt "$3"
+ )
+
+ if [[ -n "${4:-}" ]]; then
+ MOUNT_GPT_OPTIONS+=( --esp_mountpt "$4" )
+ fi
+ # Bash returns an empty array for mode_flag if $@ has less than 5 elements.
+ local mode_flag=( "${@:5:1}" )
+ _check_mount_image_flags "${mode_flag[@]:+${mode_flag[@]}}"
+
+ "./mount_gpt_image.sh" "${MOUNT_GPT_OPTIONS[@]}" \
+ "${mode_flag[@]:+${mode_flag[@]}}"
+}
+
+# Usage: remount_image [mode_flag]
+#
+# Remount the file systems mounted in the previous call to mount_image with the
+# passed extra flags.
+# Args:
+# mode_flag: Optional flag to control how the image is mounted. See
+# mount_image for details.
+remount_image() {
+ _check_mount_image_flags "$@"
+ "./mount_gpt_image.sh" --remount "${MOUNT_GPT_OPTIONS[@]}" "$@"
+}
+
+# Usage: unmount_image
+# Unmount the file systems mounted in the previous call to mount_image. The
+# mountpoint directories will be removed, regardless of whether or not they
+# existed when mount_image was called.
+# No arguments.
+unmount_image() {
+ if [[ ${#MOUNT_GPT_OPTIONS[@]} -eq 0 ]]; then
+ warn "Image already unmounted."
+ return 1
+ fi
+ "./mount_gpt_image.sh" --unmount "${MOUNT_GPT_OPTIONS[@]}" \
+ --delete_mountpts
+
+ MOUNT_GPT_OPTIONS=( )
+}
+
+# Usage: get_board_from_image [image]
+#
+# Echoes the board name specified in the image.
+get_board_from_image() {
+ local image=$1
+ local dir="$(mktemp -d)"
+ local rootfs="${dir}/rootfs"
+ local stateful="${dir}/stateful"
+ (
+ trap "unmount_image > /dev/null; rm -rf ${dir}" EXIT
+ mount_image "${image}" "${rootfs}" "${stateful}" > /dev/null
+ echo "$(sed -n '/^CHROMEOS_RELEASE_BOARD=/s:^[^=]*=::p' \
+ "${rootfs}/etc/lsb-release")"
+ )
+}
diff --git a/nichrome/scripts/mount_image.sh b/nichrome/scripts/mount_image.sh
new file mode 100755
index 000000000..3373c2b83
--- /dev/null
+++ b/nichrome/scripts/mount_image.sh
@@ -0,0 +1,211 @@
+#!/bin/bash -eu
+# File automatically generated. Do not edit.
+
+usage() {
+ local ret=0
+ if [[ $# -gt 0 ]]; then
+ # Write to stderr on errors.
+ exec 1>&2
+ echo "ERROR: $*"
+ echo
+ ret=1
+ fi
+ echo "Usage: $0 [image] [part]"
+ echo "Example: $0 chromiumos_image.bin"
+ exit ${ret}
+}
+
+TARGET=${1:-}
+PART=${2:-}
+case ${TARGET} in
+-h|--help)
+ usage
+ ;;
+"")
+ for TARGET in chromiumos_{,base_}image.bin ""; do
+ if [[ -e ${TARGET} ]]; then
+ echo "autodetected image: ${TARGET}"
+ break
+ fi
+ done
+ if [[ -z ${TARGET} ]]; then
+ usage "could not autodetect an image"
+ fi
+ ;;
+*)
+ if [[ ! -e ${TARGET} ]]; then
+ usage "image does not exist: ${TARGET}"
+ fi
+esac
+
+# start size part contents
+# 0 1 PMBR (Boot GUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE)
+# 1 1 Pri GPT header
+# 2 32 Pri GPT table
+# 2961408 12132352 1 Label: "STATE"
+# Type: Linux data
+# UUID: CC1A2390-0A9D-9D48-883B-626E7DD188CB
+# 20480 32768 2 Label: "KERN-A"
+# Type: ChromeOS kernel
+# UUID: 71B947BB-2396-314B-8C78-2A62CBFC8024
+# Attr: priority=15 tries=15 successful=0
+# 319488 2641920 3 Label: "ROOT-A"
+# Type: ChromeOS rootfs
+# UUID: 5D3E9883-6405-B44A-9E79-E1125B5FDC9B
+# 53248 32768 4 Label: "KERN-B"
+# Type: ChromeOS kernel
+# UUID: CC947588-A4F8-B64A-99DE-81243D71A4BE
+# Attr: priority=0 tries=0 successful=0
+# 315392 4096 5 Label: "ROOT-B"
+# Type: ChromeOS rootfs
+# UUID: 316ADC8E-FA80-194C-9C01-F562D280239F
+# 16448 1 6 Label: "KERN-C"
+# Type: ChromeOS kernel
+# UUID: 6AD6BA67-5ED6-5C43-9DE1-238C7DA83B1A
+# Attr: priority=0 tries=0 successful=0
+# 16449 1 7 Label: "ROOT-C"
+# Type: ChromeOS rootfs
+# UUID: AA474C7E-3368-8047-9CC4-C6459C867D53
+# 86016 32768 8 Label: "OEM"
+# Type: Linux data
+# UUID: 2B5DF82C-C3D0-4443-A90A-D2A3671D5C0E
+# 16450 1 9 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 23A9BEA8-8CCA-744C-9AD4-3408624F785D
+# 16451 1 10 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 56E34019-7E1F-D244-A74F-D594B637A18F
+# 64 16384 11 Label: "RWFW"
+# Type: ChromeOS firmware
+# UUID: 529423BB-45F4-434B-846B-1A15A3ED987E
+# 249856 65536 12 Label: "EFI-SYSTEM"
+# Type: EFI System Partition
+# UUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE
+# Attr: legacy_boot=1
+# 15126495 32 Sec GPT table
+# 15126527 1 Sec GPT header
+case ${PART:-1} in
+1|"STATE")
+(
+mkdir -p dir_1
+m=( sudo mount -o loop,offset=1516240896,sizelimit=6211764224 "${TARGET}" dir_1 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_1
+ exit 0
+ fi
+fi
+ln -sfT dir_1 "dir_1_STATE"
+) &
+esac
+case ${PART:-2} in
+2|"KERN-A")
+(
+mkdir -p dir_2
+m=( sudo mount -o loop,offset=10485760,sizelimit=16777216 "${TARGET}" dir_2 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_2
+ exit 0
+ fi
+fi
+ln -sfT dir_2 "dir_2_KERN-A"
+) &
+esac
+case ${PART:-3} in
+3|"ROOT-A")
+(
+mkdir -p dir_3
+m=( sudo mount -o loop,offset=163577856,sizelimit=1352663040 "${TARGET}" dir_3 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_3
+ exit 0
+ fi
+fi
+ln -sfT dir_3 "dir_3_ROOT-A"
+) &
+esac
+case ${PART:-4} in
+4|"KERN-B")
+(
+mkdir -p dir_4
+m=( sudo mount -o loop,offset=27262976,sizelimit=16777216 "${TARGET}" dir_4 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_4
+ exit 0
+ fi
+fi
+ln -sfT dir_4 "dir_4_KERN-B"
+) &
+esac
+case ${PART:-5} in
+5|"ROOT-B")
+(
+mkdir -p dir_5
+m=( sudo mount -o loop,offset=161480704,sizelimit=2097152 "${TARGET}" dir_5 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_5
+ exit 0
+ fi
+fi
+ln -sfT dir_5 "dir_5_ROOT-B"
+) &
+esac
+case ${PART:-6} in
+6|"KERN-C")
+esac
+case ${PART:-7} in
+7|"ROOT-C")
+esac
+case ${PART:-8} in
+8|"OEM")
+(
+mkdir -p dir_8
+m=( sudo mount -o loop,offset=44040192,sizelimit=16777216 "${TARGET}" dir_8 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_8
+ exit 0
+ fi
+fi
+ln -sfT dir_8 "dir_8_OEM"
+) &
+esac
+case ${PART:-9} in
+9|"reserved")
+esac
+case ${PART:-10} in
+10|"reserved")
+esac
+case ${PART:-11} in
+11|"RWFW")
+(
+mkdir -p dir_11
+m=( sudo mount -o loop,offset=32768,sizelimit=8388608 "${TARGET}" dir_11 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_11
+ exit 0
+ fi
+fi
+ln -sfT dir_11 "dir_11_RWFW"
+) &
+esac
+case ${PART:-12} in
+12|"EFI-SYSTEM")
+(
+mkdir -p dir_12
+m=( sudo mount -o loop,offset=127926272,sizelimit=33554432 "${TARGET}" dir_12 )
+if ! "${m[@]}"; then
+ if ! "${m[@]}" -o ro; then
+ rmdir dir_12
+ exit 0
+ fi
+fi
+ln -sfT dir_12 "dir_12_EFI-SYSTEM"
+) &
+esac
+wait
diff --git a/nichrome/scripts/pack_partitions.sh b/nichrome/scripts/pack_partitions.sh
new file mode 100755
index 000000000..13341c4c3
--- /dev/null
+++ b/nichrome/scripts/pack_partitions.sh
@@ -0,0 +1,134 @@
+#!/bin/bash -eu
+# File automatically generated. Do not edit.
+
+usage() {
+ local ret=0
+ if [[ $# -gt 0 ]]; then
+ # Write to stderr on errors.
+ exec 1>&2
+ echo "ERROR: $*"
+ echo
+ ret=1
+ fi
+ echo "Usage: $0 [image] [part]"
+ echo "Example: $0 chromiumos_image.bin"
+ exit ${ret}
+}
+
+TARGET=${1:-}
+PART=${2:-}
+case ${TARGET} in
+-h|--help)
+ usage
+ ;;
+"")
+ for TARGET in chromiumos_{,base_}image.bin ""; do
+ if [[ -e ${TARGET} ]]; then
+ echo "autodetected image: ${TARGET}"
+ break
+ fi
+ done
+ if [[ -z ${TARGET} ]]; then
+ usage "could not autodetect an image"
+ fi
+ ;;
+*)
+ if [[ ! -e ${TARGET} ]]; then
+ usage "image does not exist: ${TARGET}"
+ fi
+esac
+
+# start size part contents
+# 0 1 PMBR (Boot GUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE)
+# 1 1 Pri GPT header
+# 2 32 Pri GPT table
+# 2961408 12132352 1 Label: "STATE"
+# Type: Linux data
+# UUID: CC1A2390-0A9D-9D48-883B-626E7DD188CB
+# 20480 32768 2 Label: "KERN-A"
+# Type: ChromeOS kernel
+# UUID: 71B947BB-2396-314B-8C78-2A62CBFC8024
+# Attr: priority=15 tries=15 successful=0
+# 319488 2641920 3 Label: "ROOT-A"
+# Type: ChromeOS rootfs
+# UUID: 5D3E9883-6405-B44A-9E79-E1125B5FDC9B
+# 53248 32768 4 Label: "KERN-B"
+# Type: ChromeOS kernel
+# UUID: CC947588-A4F8-B64A-99DE-81243D71A4BE
+# Attr: priority=0 tries=0 successful=0
+# 315392 4096 5 Label: "ROOT-B"
+# Type: ChromeOS rootfs
+# UUID: 316ADC8E-FA80-194C-9C01-F562D280239F
+# 16448 1 6 Label: "KERN-C"
+# Type: ChromeOS kernel
+# UUID: 6AD6BA67-5ED6-5C43-9DE1-238C7DA83B1A
+# Attr: priority=0 tries=0 successful=0
+# 16449 1 7 Label: "ROOT-C"
+# Type: ChromeOS rootfs
+# UUID: AA474C7E-3368-8047-9CC4-C6459C867D53
+# 86016 32768 8 Label: "OEM"
+# Type: Linux data
+# UUID: 2B5DF82C-C3D0-4443-A90A-D2A3671D5C0E
+# 16450 1 9 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 23A9BEA8-8CCA-744C-9AD4-3408624F785D
+# 16451 1 10 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 56E34019-7E1F-D244-A74F-D594B637A18F
+# 64 16384 11 Label: "RWFW"
+# Type: ChromeOS firmware
+# UUID: 529423BB-45F4-434B-846B-1A15A3ED987E
+# 249856 65536 12 Label: "EFI-SYSTEM"
+# Type: EFI System Partition
+# UUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE
+# Attr: legacy_boot=1
+# 15126495 32 Sec GPT table
+# 15126527 1 Sec GPT header
+case ${PART:-1} in
+1|"STATE")
+dd if=part_1 of="${TARGET}" bs=512 count=12132352 seek=2961408 conv=notrunc
+esac
+case ${PART:-2} in
+2|"KERN-A")
+dd if=part_2 of="${TARGET}" bs=512 count=32768 seek=20480 conv=notrunc
+esac
+case ${PART:-3} in
+3|"ROOT-A")
+dd if=part_3 of="${TARGET}" bs=512 count=2641920 seek=319488 conv=notrunc
+esac
+case ${PART:-4} in
+4|"KERN-B")
+dd if=part_4 of="${TARGET}" bs=512 count=32768 seek=53248 conv=notrunc
+esac
+case ${PART:-5} in
+5|"ROOT-B")
+dd if=part_5 of="${TARGET}" bs=512 count=4096 seek=315392 conv=notrunc
+esac
+case ${PART:-6} in
+6|"KERN-C")
+dd if=part_6 of="${TARGET}" bs=512 count=1 seek=16448 conv=notrunc
+esac
+case ${PART:-7} in
+7|"ROOT-C")
+dd if=part_7 of="${TARGET}" bs=512 count=1 seek=16449 conv=notrunc
+esac
+case ${PART:-8} in
+8|"OEM")
+dd if=part_8 of="${TARGET}" bs=512 count=32768 seek=86016 conv=notrunc
+esac
+case ${PART:-9} in
+9|"reserved")
+dd if=part_9 of="${TARGET}" bs=512 count=1 seek=16450 conv=notrunc
+esac
+case ${PART:-10} in
+10|"reserved")
+dd if=part_10 of="${TARGET}" bs=512 count=1 seek=16451 conv=notrunc
+esac
+case ${PART:-11} in
+11|"RWFW")
+dd if=part_11 of="${TARGET}" bs=512 count=16384 seek=64 conv=notrunc
+esac
+case ${PART:-12} in
+12|"EFI-SYSTEM")
+dd if=part_12 of="${TARGET}" bs=512 count=65536 seek=249856 conv=notrunc
+esac
diff --git a/nichrome/scripts/partition_script.sh b/nichrome/scripts/partition_script.sh
new file mode 100644
index 000000000..ddc954668
--- /dev/null
+++ b/nichrome/scripts/partition_script.sh
@@ -0,0 +1,489 @@
+#!/bin/sh
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script is automatically generated by ./cgpt_shell.sh.
+# Do not edit!
+
+if ! type numsectors >/dev/null 2>&1; then
+ . "./chromeos-common.sh" || exit 1
+fi
+locate_gpt
+
+# Usage: create_image
+# If is a block device, wipes out the GPT
+# If it's not, it creates a new file of the requested size
+create_image() {
+ local dev="$1"
+ local min_disk_size="$2"
+ local block_size="$3"
+ if [ -b "${dev}" ]; then
+ # Zap any old partitions (otherwise gpt complains).
+ dd if=/dev/zero of="${dev}" conv=notrunc bs=512 count=32
+ dd if=/dev/zero of="${dev}" conv=notrunc bs=512 \
+ seek=$(( min_disk_size - 1 - 33 )) count=33
+ else
+ if [ ! -e "${dev}" ]; then
+ dd if=/dev/zero of="${dev}" bs="${block_size}" count=1 \
+ seek=$(( min_disk_size - 1 ))
+ fi
+ fi
+}
+
+write_base_table() {
+ local target="$1"
+ create_image "${target}" 11227072 512
+ local curr=64
+ # Create the GPT headers and tables. Pad the primary ones.
+ ./cgpt create -p 0 ${target}
+ local stateful_size=2490368
+ if [ -b "${target}" ]; then
+ stateful_size=$(( $(numsectors "${target}") - 8736704))
+ fi
+ $(( stateful_size -= (stateful_size % 4096) ))
+ ./cgpt add -i 11 -b ${curr} -s 16384 -t firmware -l "RWFW" ${target}
+ $(( curr += 16384 ))
+ ./cgpt add -i 6 -b ${curr} -s 1 -t kernel -l "KERN-C" ${target}
+ $(( curr += 1 ))
+ ./cgpt add -i 7 -b ${curr} -s 1 -t rootfs -l "ROOT-C" ${target}
+ $(( curr += 1 ))
+ ./cgpt add -i 9 -b ${curr} -s 1 -t reserved -l "reserved" ${target}
+ $(( curr += 1 ))
+ ./cgpt add -i 10 -b ${curr} -s 1 -t reserved -l "reserved" ${target}
+ $(( curr += 1 ))
+ $(( curr += 4028 ))
+ ./cgpt add -i 2 -b ${curr} -s 32768 -t kernel -l "KERN-A" ${target}
+ $(( curr += 32768 ))
+ ./cgpt add -i 4 -b ${curr} -s 32768 -t kernel -l "KERN-B" ${target}
+ $(( curr += 32768 ))
+ ./cgpt add -i 8 -b ${curr} -s 32768 -t data -l "OEM" ${target}
+ : $(( curr += 32768 ))
+ : $(( curr += 131072 ))
+ ./cgpt add -i 12 -b ${curr} -s 65536 -t efi -l "EFI-SYSTEM" ${target}
+ : $(( curr += 65536 ))
+ ./cgpt add -i 5 -b ${curr} -s 4194304 -t rootfs -l "ROOT-B" ${target}
+ : $(( curr += 4194304 ))
+ ./cgpt add -i 3 -b ${curr} -s 4194304 -t rootfs -l "ROOT-A" ${target}
+ : $(( curr += 4194304 ))
+ ./cgpt add -i 1 -b ${curr} -s ${stateful_size} -t data -l "STATE" ${target}
+ : $(( curr += ${stateful_size} ))
+ ./cgpt add -i 2 -S 0 -T 15 -P 15 ${target}
+ ./cgpt add -i 4 -S 0 -T 15 -P 0 ${target}
+ ./cgpt add -i 6 -S 0 -T 15 -P 0 ${target}
+ ./cgpt boot -p -b $2 -i 12 ${target}
+ ./cgpt add -i 12 -B 1 ${target}
+ ./cgpt show ${target}
+}
+load_base_vars() {
+ DEFAULT_ROOTDEV=""
+ PARTITION_SIZE_RWFW=8388608
+ RESERVED_EBS_RWFW=0
+ DATA_SIZE_RWFW=8388608
+ FORMAT_RWFW=
+ FS_FORMAT_RWFW=
+ FS_OPTIONS_RWFW=""
+ PARTITION_NUM_RWFW="11"
+ PARTITION_SIZE_11=8388608
+ RESERVED_EBS_11=0
+ DATA_SIZE_11=8388608
+ FORMAT_11=
+ FS_FORMAT_11=
+ FS_OPTIONS_11=""
+ PARTITION_NUM_11="11"
+ PARTITION_SIZE_KERN_C=512
+ RESERVED_EBS_KERN_C=0
+ DATA_SIZE_KERN_C=512
+ FORMAT_KERN_C=
+ FS_FORMAT_KERN_C=
+ FS_OPTIONS_KERN_C=""
+ PARTITION_NUM_KERN_C="6"
+ PARTITION_SIZE_6=512
+ RESERVED_EBS_6=0
+ DATA_SIZE_6=512
+ FORMAT_6=
+ FS_FORMAT_6=
+ FS_OPTIONS_6=""
+ PARTITION_NUM_6="6"
+ PARTITION_SIZE_ROOT_C=512
+ RESERVED_EBS_ROOT_C=0
+ DATA_SIZE_ROOT_C=512
+ FORMAT_ROOT_C=
+ FS_FORMAT_ROOT_C=
+ FS_OPTIONS_ROOT_C=""
+ PARTITION_NUM_ROOT_C="7"
+ PARTITION_SIZE_7=512
+ RESERVED_EBS_7=0
+ DATA_SIZE_7=512
+ FORMAT_7=
+ FS_FORMAT_7=
+ FS_OPTIONS_7=""
+ PARTITION_NUM_7="7"
+ PARTITION_SIZE_RESERVED=512
+ RESERVED_EBS_RESERVED=0
+ DATA_SIZE_RESERVED=512
+ FORMAT_RESERVED=
+ FS_FORMAT_RESERVED=
+ FS_OPTIONS_RESERVED=""
+ PARTITION_NUM_RESERVED="9"
+ PARTITION_SIZE_9=512
+ RESERVED_EBS_9=0
+ DATA_SIZE_9=512
+ FORMAT_9=
+ FS_FORMAT_9=
+ FS_OPTIONS_9=""
+ PARTITION_NUM_9="9"
+ PARTITION_SIZE_RESERVED=512
+ RESERVED_EBS_RESERVED=0
+ DATA_SIZE_RESERVED=512
+ FORMAT_RESERVED=
+ FS_FORMAT_RESERVED=
+ FS_OPTIONS_RESERVED=""
+ PARTITION_NUM_RESERVED="10"
+ PARTITION_SIZE_10=512
+ RESERVED_EBS_10=0
+ DATA_SIZE_10=512
+ FORMAT_10=
+ FS_FORMAT_10=
+ FS_OPTIONS_10=""
+ PARTITION_NUM_10="10"
+ PARTITION_SIZE_KERN_A=16777216
+ RESERVED_EBS_KERN_A=0
+ DATA_SIZE_KERN_A=16777216
+ FORMAT_KERN_A=
+ FS_FORMAT_KERN_A=
+ FS_OPTIONS_KERN_A=""
+ PARTITION_NUM_KERN_A="2"
+ PARTITION_SIZE_2=16777216
+ RESERVED_EBS_2=0
+ DATA_SIZE_2=16777216
+ FORMAT_2=
+ FS_FORMAT_2=
+ FS_OPTIONS_2=""
+ PARTITION_NUM_2="2"
+ PARTITION_SIZE_KERN_B=16777216
+ RESERVED_EBS_KERN_B=0
+ DATA_SIZE_KERN_B=16777216
+ FORMAT_KERN_B=
+ FS_FORMAT_KERN_B=
+ FS_OPTIONS_KERN_B=""
+ PARTITION_NUM_KERN_B="4"
+ PARTITION_SIZE_4=16777216
+ RESERVED_EBS_4=0
+ DATA_SIZE_4=16777216
+ FORMAT_4=
+ FS_FORMAT_4=
+ FS_OPTIONS_4=""
+ PARTITION_NUM_4="4"
+ PARTITION_SIZE_OEM=16777216
+ RESERVED_EBS_OEM=0
+ DATA_SIZE_OEM=16777216
+ FORMAT_OEM=
+ FS_FORMAT_OEM=ext4
+ FS_OPTIONS_OEM=""
+ PARTITION_NUM_OEM="8"
+ PARTITION_SIZE_8=16777216
+ RESERVED_EBS_8=0
+ DATA_SIZE_8=16777216
+ FORMAT_8=
+ FS_FORMAT_8=ext4
+ FS_OPTIONS_8=""
+ PARTITION_NUM_8="8"
+ PARTITION_SIZE_EFI_SYSTEM=33554432
+ RESERVED_EBS_EFI_SYSTEM=0
+ DATA_SIZE_EFI_SYSTEM=33554432
+ FORMAT_EFI_SYSTEM=
+ FS_FORMAT_EFI_SYSTEM=vfat
+ FS_OPTIONS_EFI_SYSTEM=""
+ PARTITION_NUM_EFI_SYSTEM="12"
+ PARTITION_SIZE_12=33554432
+ RESERVED_EBS_12=0
+ DATA_SIZE_12=33554432
+ FORMAT_12=
+ FS_FORMAT_12=vfat
+ FS_OPTIONS_12=""
+ PARTITION_NUM_12="12"
+ PARTITION_SIZE_ROOT_B=2147483648
+ RESERVED_EBS_ROOT_B=0
+ DATA_SIZE_ROOT_B=2147483648
+ FORMAT_ROOT_B=
+ FS_FORMAT_ROOT_B=
+ FS_OPTIONS_ROOT_B=""
+ PARTITION_NUM_ROOT_B="5"
+ PARTITION_SIZE_5=2147483648
+ RESERVED_EBS_5=0
+ DATA_SIZE_5=2147483648
+ FORMAT_5=
+ FS_FORMAT_5=
+ FS_OPTIONS_5=""
+ PARTITION_NUM_5="5"
+ PARTITION_SIZE_ROOT_A=2147483648
+ RESERVED_EBS_ROOT_A=0
+ DATA_SIZE_ROOT_A=1300234240
+ FORMAT_ROOT_A=
+ FS_FORMAT_ROOT_A=ext2
+ FS_OPTIONS_ROOT_A=""
+ PARTITION_NUM_ROOT_A="3"
+ PARTITION_SIZE_3=2147483648
+ RESERVED_EBS_3=0
+ DATA_SIZE_3=1300234240
+ FORMAT_3=
+ FS_FORMAT_3=ext2
+ FS_OPTIONS_3=""
+ PARTITION_NUM_3="3"
+ PARTITION_SIZE_STATE=1275068416
+ RESERVED_EBS_STATE=0
+ DATA_SIZE_STATE=1275068416
+ FORMAT_STATE=
+ FS_FORMAT_STATE=ext4
+ FS_OPTIONS_STATE=""
+ PARTITION_NUM_STATE="1"
+ PARTITION_SIZE_1=1275068416
+ RESERVED_EBS_1=0
+ DATA_SIZE_1=1275068416
+ FORMAT_1=
+ FS_FORMAT_1=ext4
+ FS_OPTIONS_1=""
+ PARTITION_NUM_1="1"
+}
+write_partition_table() {
+ local target="$1"
+ create_image "${target}" 5484480 512
+ echo "CREATED IMAGE"
+ local curr=64
+ # Create the GPT headers and tables. Pad the primary ones.
+ ./cgpt create -p 0 ${target}
+ echo "SOME OTHER THING"
+ local stateful_size=2490368
+ if [ -b "${target}" ]; then
+ stateful_size=$(( $(numsectors "${target}") - 2994112))
+ fi
+ : $(( stateful_size -= (stateful_size % 4096) ))
+ ./cgpt add -i 11 -b ${curr} -s 16384 -t firmware -l "RWFW" ${target}
+ : $(( curr += 16384 ))
+
+ echo "HERE"
+ ./cgpt add -i 6 -b ${curr} -s 1 -t kernel -l "KERN-C" ${target}
+ : $(( curr += 1 ))
+ echo "HERE"
+ ./cgpt add -i 7 -b ${curr} -s 1 -t rootfs -l "ROOT-C" ${target}
+ : $(( curr += 1 ))
+ echo "HERE"
+ ./cgpt add -i 9 -b ${curr} -s 1 -t reserved -l "reserved" ${target}
+ : $(( curr += 1 ))
+ echo "HERE"
+ ./cgpt add -i 10 -b ${curr} -s 1 -t reserved -l "reserved" ${target}
+ : $(( curr += 1 ))
+ echo "HERE"
+ : $(( curr += 4028 ))
+ echo "HERE"
+ ./cgpt add -i 2 -b ${curr} -s 32768 -t kernel -l "KERN-A" ${target}
+ : $(( curr += 32768 ))
+ echo "HERE"
+ ./cgpt add -i 4 -b ${curr} -s 32768 -t kernel -l "KERN-B" ${target}
+ : $(( curr += 32768 ))
+ echo "HERE"
+ ./cgpt add -i 8 -b ${curr} -s 32768 -t data -l "OEM" ${target}
+ : $(( curr += 32768 ))
+ echo "HERE"
+ : $(( curr += 131072 ))
+ echo "HERE"
+ ./cgpt add -i 12 -b ${curr} -s 65536 -t efi -l "EFI-SYSTEM" ${target}
+ : $(( curr += 65536 ))
+ echo "HERE"
+ ./cgpt add -i 5 -b ${curr} -s 4096 -t rootfs -l "ROOT-B" ${target}
+ : $(( curr += 4096 ))
+ echo "HERE"
+ ./cgpt add -i 3 -b ${curr} -s 2641920 -t rootfs -l "ROOT-A" ${target}
+ : $(( curr += 2641920 ))
+ echo "HERE"
+ ./cgpt add -i 1 -b ${curr} -s ${stateful_size} -t data -l "STATE" ${target}
+ : $(( curr += ${stateful_size} ))
+ echo "HERE"
+ ./cgpt add -i 2 -S 0 -T 15 -P 15 ${target}
+ echo "HERE"
+ ./cgpt add -i 4 -S 0 -T 0 -P 0 ${target}
+ echo "HERE"
+ ./cgpt add -i 6 -S 0 -T 0 -P 0 ${target}
+ echo "HERE"
+ ./cgpt boot -p -b $2 -i 12 ${target}
+ echo "HERE"
+ ./cgpt add -i 12 -B 1 ${target}
+ echo "HERE"
+ ./cgpt show ${target}
+ echo "HERE"
+}
+load_partition_vars() {
+ DEFAULT_ROOTDEV=""
+ PARTITION_SIZE_RWFW=8388608
+ RESERVED_EBS_RWFW=0
+ DATA_SIZE_RWFW=8388608
+ FORMAT_RWFW=
+ FS_FORMAT_RWFW=
+ FS_OPTIONS_RWFW=""
+ PARTITION_NUM_RWFW="11"
+ PARTITION_SIZE_11=8388608
+ RESERVED_EBS_11=0
+ DATA_SIZE_11=8388608
+ FORMAT_11=
+ FS_FORMAT_11=
+ FS_OPTIONS_11=""
+ PARTITION_NUM_11="11"
+ PARTITION_SIZE_KERN_C=512
+ RESERVED_EBS_KERN_C=0
+ DATA_SIZE_KERN_C=512
+ FORMAT_KERN_C=
+ FS_FORMAT_KERN_C=
+ FS_OPTIONS_KERN_C=""
+ PARTITION_NUM_KERN_C="6"
+ PARTITION_SIZE_6=512
+ RESERVED_EBS_6=0
+ DATA_SIZE_6=512
+ FORMAT_6=
+ FS_FORMAT_6=
+ FS_OPTIONS_6=""
+ PARTITION_NUM_6="6"
+ PARTITION_SIZE_ROOT_C=512
+ RESERVED_EBS_ROOT_C=0
+ DATA_SIZE_ROOT_C=512
+ FORMAT_ROOT_C=
+ FS_FORMAT_ROOT_C=
+ FS_OPTIONS_ROOT_C=""
+ PARTITION_NUM_ROOT_C="7"
+ PARTITION_SIZE_7=512
+ RESERVED_EBS_7=0
+ DATA_SIZE_7=512
+ FORMAT_7=
+ FS_FORMAT_7=
+ FS_OPTIONS_7=""
+ PARTITION_NUM_7="7"
+ PARTITION_SIZE_RESERVED=512
+ RESERVED_EBS_RESERVED=0
+ DATA_SIZE_RESERVED=512
+ FORMAT_RESERVED=
+ FS_FORMAT_RESERVED=
+ FS_OPTIONS_RESERVED=""
+ PARTITION_NUM_RESERVED="9"
+ PARTITION_SIZE_9=512
+ RESERVED_EBS_9=0
+ DATA_SIZE_9=512
+ FORMAT_9=
+ FS_FORMAT_9=
+ FS_OPTIONS_9=""
+ PARTITION_NUM_9="9"
+ PARTITION_SIZE_RESERVED=512
+ RESERVED_EBS_RESERVED=0
+ DATA_SIZE_RESERVED=512
+ FORMAT_RESERVED=
+ FS_FORMAT_RESERVED=
+ FS_OPTIONS_RESERVED=""
+ PARTITION_NUM_RESERVED="10"
+ PARTITION_SIZE_10=512
+ RESERVED_EBS_10=0
+ DATA_SIZE_10=512
+ FORMAT_10=
+ FS_FORMAT_10=
+ FS_OPTIONS_10=""
+ PARTITION_NUM_10="10"
+ PARTITION_SIZE_KERN_A=16777216
+ RESERVED_EBS_KERN_A=0
+ DATA_SIZE_KERN_A=16777216
+ FORMAT_KERN_A=
+ FS_FORMAT_KERN_A=
+ FS_OPTIONS_KERN_A=""
+ PARTITION_NUM_KERN_A="2"
+ PARTITION_SIZE_2=16777216
+ RESERVED_EBS_2=0
+ DATA_SIZE_2=16777216
+ FORMAT_2=
+ FS_FORMAT_2=
+ FS_OPTIONS_2=""
+ PARTITION_NUM_2="2"
+ PARTITION_SIZE_KERN_B=16777216
+ RESERVED_EBS_KERN_B=0
+ DATA_SIZE_KERN_B=16777216
+ FORMAT_KERN_B=
+ FS_FORMAT_KERN_B=
+ FS_OPTIONS_KERN_B=""
+ PARTITION_NUM_KERN_B="4"
+ PARTITION_SIZE_4=16777216
+ RESERVED_EBS_4=0
+ DATA_SIZE_4=16777216
+ FORMAT_4=
+ FS_FORMAT_4=
+ FS_OPTIONS_4=""
+ PARTITION_NUM_4="4"
+ PARTITION_SIZE_OEM=16777216
+ RESERVED_EBS_OEM=0
+ DATA_SIZE_OEM=16777216
+ FORMAT_OEM=
+ FS_FORMAT_OEM=ext4
+ FS_OPTIONS_OEM=""
+ PARTITION_NUM_OEM="8"
+ PARTITION_SIZE_8=16777216
+ RESERVED_EBS_8=0
+ DATA_SIZE_8=16777216
+ FORMAT_8=
+ FS_FORMAT_8=ext4
+ FS_OPTIONS_8=""
+ PARTITION_NUM_8="8"
+ PARTITION_SIZE_EFI_SYSTEM=33554432
+ RESERVED_EBS_EFI_SYSTEM=0
+ DATA_SIZE_EFI_SYSTEM=33554432
+ FORMAT_EFI_SYSTEM=
+ FS_FORMAT_EFI_SYSTEM=vfat
+ FS_OPTIONS_EFI_SYSTEM=""
+ PARTITION_NUM_EFI_SYSTEM="12"
+ PARTITION_SIZE_12=33554432
+ RESERVED_EBS_12=0
+ DATA_SIZE_12=33554432
+ FORMAT_12=
+ FS_FORMAT_12=vfat
+ FS_OPTIONS_12=""
+ PARTITION_NUM_12="12"
+ PARTITION_SIZE_ROOT_B=2097152
+ RESERVED_EBS_ROOT_B=0
+ DATA_SIZE_ROOT_B=2097152
+ FORMAT_ROOT_B=
+ FS_FORMAT_ROOT_B=
+ FS_OPTIONS_ROOT_B=""
+ PARTITION_NUM_ROOT_B="5"
+ PARTITION_SIZE_5=2097152
+ RESERVED_EBS_5=0
+ DATA_SIZE_5=2097152
+ FORMAT_5=
+ FS_FORMAT_5=
+ FS_OPTIONS_5=""
+ PARTITION_NUM_5="5"
+ PARTITION_SIZE_ROOT_A=1352663040
+ RESERVED_EBS_ROOT_A=0
+ DATA_SIZE_ROOT_A=1300234240
+ FORMAT_ROOT_A=
+ FS_FORMAT_ROOT_A=ext2
+ FS_OPTIONS_ROOT_A=""
+ PARTITION_NUM_ROOT_A="3"
+ PARTITION_SIZE_3=1352663040
+ RESERVED_EBS_3=0
+ DATA_SIZE_3=1300234240
+ FORMAT_3=
+ FS_FORMAT_3=ext2
+ FS_OPTIONS_3=""
+ PARTITION_NUM_3="3"
+ PARTITION_SIZE_STATE=1275068416
+ RESERVED_EBS_STATE=0
+ DATA_SIZE_STATE=1275068416
+ FORMAT_STATE=
+ FS_FORMAT_STATE=ext4
+ FS_OPTIONS_STATE=""
+ PARTITION_NUM_STATE="1"
+ PARTITION_SIZE_1=1275068416
+ RESERVED_EBS_1=0
+ DATA_SIZE_1=1275068416
+ FORMAT_1=
+ FS_FORMAT_1=ext4
+ FS_OPTIONS_1=""
+ PARTITION_NUM_1="1"
+}
+ROOTFS_PARTITION_SIZE=2147483648
+
+write_partition_table $1 $2
diff --git a/nichrome/scripts/test_image_content.sh b/nichrome/scripts/test_image_content.sh
new file mode 100755
index 000000000..cc44bd531
--- /dev/null
+++ b/nichrome/scripts/test_image_content.sh
@@ -0,0 +1,99 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Usage: run_lddtree [args to lddtree]
+run_lddtree() {
+ # Keep `local` decl split from assignment so return code is checked.
+ local lddtree='/mnt/host/source/chromite/bin/lddtree'
+ local root="$1"
+ shift
+
+ # Since we'll feed files via xargs, we need to extract the options
+ # so we can pass it to the lddtree tool.
+ local flags=()
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+ --) break ;;
+ -*) flags+=( "$1" ) ;;
+ *) break ;;
+ esac
+ shift
+ done
+
+ # In case the file list is too big, send it through xargs.
+ # http://crbug.com/369314
+ printf '%s\0' "$@" | xargs -0 \
+ sudo "${lddtree}" -R "${root}" --skip-non-elfs "${flags[@]}"
+}
+
+# Usage: test_elf_deps
+test_elf_deps() {
+ # Keep `local` decl split from assignment so return code is checked.
+ local f deps
+ local root="$1"
+ shift
+
+ # We first check everything in one go. We assume that it'll usually be OK,
+ # so we make this the fast path. If it does fail, we'll fall back to one at
+ # a time so the error output is human readable.
+ deps=$(run_lddtree "${root}" -l "$@") || return 1
+ if echo "${deps}" | grep -q '^[^/]'; then
+ error "test_elf_deps: Failed dependency check"
+ for f in "$@"; do
+ deps=$(run_lddtree "${root}" -l "${f}")
+ if echo "${deps}" | grep -q '^[^/]'; then
+ error "Package: $(qfile --root "${root}" -qCRv "${root}${f}")"
+ error "$(run_lddtree "${root}" "${f}")"
+ fi
+ done
+ return 1
+ fi
+
+ return 0
+}
+
+test_image_content() {
+ local root="$1"
+ local returncode=0
+
+ # Keep `local` decl split from assignment so return code is checked.
+ local libs
+
+ # Check that all .so files, plus the binaries, have the appropriate
+ # dependencies. Need to use sudo as some files are set*id.
+ # Exclude Chrome components, which are the only files in the lib directory.
+ local components="${root}/opt/google/chrome/lib/*"
+ libs=( $(sudo \
+ find "${root}" -type f -name '*.so*' -not -name '*.so.debug' \
+ -not -path "${components}" -printf '/%P\n') )
+ if ! test_elf_deps "${root}" "${binaries[@]}" "${libs[@]}"; then
+ returncode=1
+ fi
+
+ local blacklist_dirs=(
+ "$root/usr/share/locale"
+ )
+ for dir in "${blacklist_dirs[@]}"; do
+ if [ -d "$dir" ]; then
+ error "test_image_content: Blacklisted directory found: $dir"
+ returncode=1
+ fi
+ done
+
+ # Check that /etc/localtime is a symbolic link pointing at
+ # /var/lib/timezone/localtime.
+ local localtime="$root/etc/localtime"
+ if [ ! -L "$localtime" ]; then
+ error "test_image_content: /etc/localtime is not a symbolic link"
+ returncode=1
+ else
+ local dest=$(readlink "$localtime")
+ if [ "$dest" != "/var/lib/timezone/localtime" ]; then
+ error "test_image_content: /etc/localtime points at $dest"
+ returncode=1
+ fi
+ fi
+
+ return $returncode
+}
diff --git a/nichrome/scripts/test_image_util.sh b/nichrome/scripts/test_image_util.sh
new file mode 100755
index 000000000..e45a115c4
--- /dev/null
+++ b/nichrome/scripts/test_image_util.sh
@@ -0,0 +1,53 @@
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Shell function library for functions specific to creating test
+# images from dev images. This file also contains additional
+# functions and initialization shared between build_image and
+# mod_image_for_test.sh.
+#
+
+# Emerges chromeos-test onto the image.
+emerge_chromeos_test() {
+ # Determine the root dir for test packages.
+ local root_dev_dir="${root_fs_dir}/usr/local"
+
+ emerge_to_image --root="${root_fs_dir}" chromeos-test-root
+ emerge_to_image --root="${root_dev_dir}" virtual/target-os-test
+}
+
+# Converts a dev image into a test or factory test image
+# Takes as an arg the name of the image to be created.
+mod_image_for_test () {
+ local image_name="$1"
+
+ trap "check_full_disk ; unmount_image ; delete_prompt" EXIT
+ mount_image "${BUILD_DIR}/${image_name}" "${root_fs_dir}" "${stateful_fs_dir}"
+
+ emerge_chromeos_test
+
+ local mod_test_script="${SCRIPTS_DIR}/mod_for_test_scripts/test_setup.sh"
+ # Run test setup script to modify the image
+ sudo -E GCLIENT_ROOT="${GCLIENT_ROOT}" ROOT_FS_DIR="${root_fs_dir}" \
+ STATEFUL_DIR="${stateful_fs_dir}" ARCH="${ARCH}" \
+ BOARD_ROOT="${BOARD_ROOT}" BUILD_DIR="${BUILD_DIR}" \
+ "${mod_test_script}"
+
+ # Run depmod to recalculate the kernel module dependencies.
+ run_depmod "${BOARD_ROOT}" "${root_fs_dir}"
+
+ # Re-run ldconfig to fix /etc/ld.so.cache.
+ run_ldconfig "${root_fs_dir}"
+
+ unmount_image
+ trap - EXIT
+
+ if [[ ${skip_kernelblock_install} -ne 1 ]]; then
+ # Now make it bootable with the flags from build_image.
+ if should_build_image ${image_name}; then
+ "${SCRIPTS_DIR}/bin/cros_make_image_bootable" "${BUILD_DIR}" \
+ ${image_name} --force_developer_mode
+ fi
+ fi
+}
diff --git a/nichrome/scripts/toolchain_utils.sh b/nichrome/scripts/toolchain_utils.sh
new file mode 100755
index 000000000..4e94ba5cf
--- /dev/null
+++ b/nichrome/scripts/toolchain_utils.sh
@@ -0,0 +1,172 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO: Convert this to python.
+
+get_all_board_toolchains()
+{
+ cros_setup_toolchains --show-board-cfg="$1" | sed 's:,: :g'
+}
+
+get_ctarget_from_board()
+{
+ local all_toolchains=( $(get_all_board_toolchains "$@") )
+ echo "${all_toolchains[0]}"
+}
+
+get_board_arch()
+{
+ local ctarget=$(get_ctarget_from_board "$@")
+
+ # Ask crossdev what the magical portage arch is!
+ local arch=$(eval $(crossdev --show-target-cfg "${ctarget}"); echo ${arch})
+ if [[ -z ${arch} ]] ; then
+ error "Unable to determine ARCH from toolchain: ${ctarget}"
+ return 1
+ fi
+
+ echo "${arch}"
+ return 0
+}
+
+is_number()
+{
+ echo "$1" | grep -q "^[0-9]\+$"
+}
+
+is_config_installed()
+{
+ gcc-config -l | cut -d" " -f3 | grep -q "$1$"
+}
+
+get_installed_atom_from_config()
+{
+ local gcc_path="$(gcc-config -B "$1")"
+ equery b "$gcc_path" | head -n1
+}
+
+get_atom_from_config()
+{
+ echo "$1" | sed -E "s|(.*)-(.*)|cross-\1/gcc-\2|g"
+}
+
+get_ctarget_from_atom()
+{
+ local atom="$1"
+ echo "$atom" | sed -E 's|cross-([^/]+)/.*|\1|g'
+}
+
+get_current_binutils_config()
+{
+ local ctarget="$1"
+ binutils-config -l | grep "$ctarget" | grep "*" | awk '{print $NF}'
+}
+
+get_bfd_config()
+{
+ local ctarget="$1"
+ binutils-config -l | grep "$ctarget" | grep -v "gold" | head -n1 | \
+ awk '{print $NF}'
+}
+
+emerge_gcc()
+{
+ local atom="$1"
+ local ctarget="$(get_ctarget_from_atom $atom)"
+ mask_file="/etc/portage/package.mask/cross-$ctarget"
+ moved_mask_file=0
+
+ # Move the package mask file elsewhere.
+ if [[ -f "$mask_file" ]]
+ then
+ temp_file="$(mktemp)"
+ sudo mv "$mask_file" "$temp_file"
+ moved_mask_file=1
+ fi
+
+ USE+=" multislot"
+ if echo "$atom" | grep -q "gcc-4.6.0$"
+ then
+ old_binutils_config="$(get_current_binutils_config $ctarget)"
+ bfd_binutils_config="$(get_bfd_config $ctarget)"
+ if [[ "$old_binutils_config" != "$bfd_binutils_config" ]]
+ then
+ sudo binutils-config "$bfd_binutils_config"
+ fi
+ fi
+ sudo ACCEPT_KEYWORDS="*" USE="$USE" emerge ="$atom"
+ emerge_retval=$?
+
+ # Move the package mask file back.
+ if [[ $moved_mask_file -eq 1 ]]
+ then
+ sudo mv "$temp_file" "$mask_file"
+ fi
+
+ if [[ ! -z "$old_binutils_config" &&
+ "$old_binutils_config" != "$(get_current_binutils_config $ctarget)" ]]
+ then
+ sudo binutils-config "$old_binutils_config"
+ fi
+
+ return $emerge_retval
+}
+
+# This function should only be called when testing experimental toolchain
+# compilers. Please don't call this from any other script.
+cros_gcc_config()
+{
+ # Return if we're not switching profiles.
+ if [[ "$1" == -* ]]
+ then
+ sudo gcc-config "$1"
+ return $?
+ fi
+
+ # cros_gcc_config can be called like:
+ # cros_gcc_config to switch config to that
+ # number. In that case we should just try to switch to
+ # that config and not try to install a missing one.
+ if ! is_number "$1" && ! is_config_installed "$1"
+ then
+ info "Configuration $1 not found."
+ info "Trying to emerge it..."
+ local atom="$(get_atom_from_config "$1")"
+ emerge_gcc "$atom" || die "Could not install $atom"
+ fi
+
+ sudo gcc-config "$1" || die "Could not switch to $1"
+
+ local boards=$(get_boards_from_config "$1")
+ local board
+ for board in $boards
+ do
+ emerge-"$board" --oneshot sys-devel/libtool
+ done
+}
+
+get_boards_from_config()
+{
+ local atom=$(get_installed_atom_from_config "$1")
+ if [[ $atom != cross* ]]
+ then
+ warn "$atom is not a cross-compiler."
+ warn "Therefore not adding its libs to the board roots."
+ return 0
+ fi
+
+ # Now copy the lib files into all possible boards.
+ local ctarget="$(get_ctarget_from_atom "$atom")"
+ for board_root in /build/*
+ do
+ local board="$(basename $board_root)"
+ local board_tc="$(get_ctarget_from_board $board)"
+ if [[ "${board_tc}" == "${ctarget}" ]]
+ then
+ echo "$board"
+ fi
+ done
+}
diff --git a/nichrome/scripts/umount_image.sh b/nichrome/scripts/umount_image.sh
new file mode 100755
index 000000000..35f520c6d
--- /dev/null
+++ b/nichrome/scripts/umount_image.sh
@@ -0,0 +1,179 @@
+#!/bin/bash -eu
+# File automatically generated. Do not edit.
+
+usage() {
+ local ret=0
+ if [[ $# -gt 0 ]]; then
+ # Write to stderr on errors.
+ exec 1>&2
+ echo "ERROR: $*"
+ echo
+ ret=1
+ fi
+ echo "Usage: $0 [image] [part]"
+ echo "Example: $0 chromiumos_image.bin"
+ exit ${ret}
+}
+
+TARGET=${1:-}
+PART=${2:-}
+case ${TARGET} in
+-h|--help)
+ usage
+ ;;
+"")
+ for TARGET in chromiumos_{,base_}image.bin ""; do
+ if [[ -e ${TARGET} ]]; then
+ echo "autodetected image: ${TARGET}"
+ break
+ fi
+ done
+ if [[ -z ${TARGET} ]]; then
+ usage "could not autodetect an image"
+ fi
+ ;;
+*)
+ if [[ ! -e ${TARGET} ]]; then
+ usage "image does not exist: ${TARGET}"
+ fi
+esac
+
+# start size part contents
+# 0 1 PMBR (Boot GUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE)
+# 1 1 Pri GPT header
+# 2 32 Pri GPT table
+# 2961408 12132352 1 Label: "STATE"
+# Type: Linux data
+# UUID: CC1A2390-0A9D-9D48-883B-626E7DD188CB
+# 20480 32768 2 Label: "KERN-A"
+# Type: ChromeOS kernel
+# UUID: 71B947BB-2396-314B-8C78-2A62CBFC8024
+# Attr: priority=15 tries=15 successful=0
+# 319488 2641920 3 Label: "ROOT-A"
+# Type: ChromeOS rootfs
+# UUID: 5D3E9883-6405-B44A-9E79-E1125B5FDC9B
+# 53248 32768 4 Label: "KERN-B"
+# Type: ChromeOS kernel
+# UUID: CC947588-A4F8-B64A-99DE-81243D71A4BE
+# Attr: priority=0 tries=0 successful=0
+# 315392 4096 5 Label: "ROOT-B"
+# Type: ChromeOS rootfs
+# UUID: 316ADC8E-FA80-194C-9C01-F562D280239F
+# 16448 1 6 Label: "KERN-C"
+# Type: ChromeOS kernel
+# UUID: 6AD6BA67-5ED6-5C43-9DE1-238C7DA83B1A
+# Attr: priority=0 tries=0 successful=0
+# 16449 1 7 Label: "ROOT-C"
+# Type: ChromeOS rootfs
+# UUID: AA474C7E-3368-8047-9CC4-C6459C867D53
+# 86016 32768 8 Label: "OEM"
+# Type: Linux data
+# UUID: 2B5DF82C-C3D0-4443-A90A-D2A3671D5C0E
+# 16450 1 9 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 23A9BEA8-8CCA-744C-9AD4-3408624F785D
+# 16451 1 10 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 56E34019-7E1F-D244-A74F-D594B637A18F
+# 64 16384 11 Label: "RWFW"
+# Type: ChromeOS firmware
+# UUID: 529423BB-45F4-434B-846B-1A15A3ED987E
+# 249856 65536 12 Label: "EFI-SYSTEM"
+# Type: EFI System Partition
+# UUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE
+# Attr: legacy_boot=1
+# 15126495 32 Sec GPT table
+# 15126527 1 Sec GPT header
+case ${PART:-1} in
+1|"STATE")
+if [[ -d dir_1 ]]; then
+ (
+ sudo umount dir_1 || :
+ rmdir dir_1
+ rm -f "dir_1_STATE"
+ ) &
+fi
+esac
+case ${PART:-2} in
+2|"KERN-A")
+if [[ -d dir_2 ]]; then
+ (
+ sudo umount dir_2 || :
+ rmdir dir_2
+ rm -f "dir_2_KERN-A"
+ ) &
+fi
+esac
+case ${PART:-3} in
+3|"ROOT-A")
+if [[ -d dir_3 ]]; then
+ (
+ sudo umount dir_3 || :
+ rmdir dir_3
+ rm -f "dir_3_ROOT-A"
+ ) &
+fi
+esac
+case ${PART:-4} in
+4|"KERN-B")
+if [[ -d dir_4 ]]; then
+ (
+ sudo umount dir_4 || :
+ rmdir dir_4
+ rm -f "dir_4_KERN-B"
+ ) &
+fi
+esac
+case ${PART:-5} in
+5|"ROOT-B")
+if [[ -d dir_5 ]]; then
+ (
+ sudo umount dir_5 || :
+ rmdir dir_5
+ rm -f "dir_5_ROOT-B"
+ ) &
+fi
+esac
+case ${PART:-6} in
+6|"KERN-C")
+esac
+case ${PART:-7} in
+7|"ROOT-C")
+esac
+case ${PART:-8} in
+8|"OEM")
+if [[ -d dir_8 ]]; then
+ (
+ sudo umount dir_8 || :
+ rmdir dir_8
+ rm -f "dir_8_OEM"
+ ) &
+fi
+esac
+case ${PART:-9} in
+9|"reserved")
+esac
+case ${PART:-10} in
+10|"reserved")
+esac
+case ${PART:-11} in
+11|"RWFW")
+if [[ -d dir_11 ]]; then
+ (
+ sudo umount dir_11 || :
+ rmdir dir_11
+ rm -f "dir_11_RWFW"
+ ) &
+fi
+esac
+case ${PART:-12} in
+12|"EFI-SYSTEM")
+if [[ -d dir_12 ]]; then
+ (
+ sudo umount dir_12 || :
+ rmdir dir_12
+ rm -f "dir_12_EFI-SYSTEM"
+ ) &
+fi
+esac
+wait
diff --git a/nichrome/scripts/unpack_partitions.sh b/nichrome/scripts/unpack_partitions.sh
new file mode 100755
index 000000000..ed2668b73
--- /dev/null
+++ b/nichrome/scripts/unpack_partitions.sh
@@ -0,0 +1,146 @@
+#!/bin/bash -eu
+# File automatically generated. Do not edit.
+
+usage() {
+ local ret=0
+ if [[ $# -gt 0 ]]; then
+ # Write to stderr on errors.
+ exec 1>&2
+ echo "ERROR: $*"
+ echo
+ ret=1
+ fi
+ echo "Usage: $0 [image] [part]"
+ echo "Example: $0 chromiumos_image.bin"
+ exit ${ret}
+}
+
+TARGET=${1:-}
+PART=${2:-}
+case ${TARGET} in
+-h|--help)
+ usage
+ ;;
+"")
+ for TARGET in chromiumos_{,base_}image.bin ""; do
+ if [[ -e ${TARGET} ]]; then
+ echo "autodetected image: ${TARGET}"
+ break
+ fi
+ done
+ if [[ -z ${TARGET} ]]; then
+ usage "could not autodetect an image"
+ fi
+ ;;
+*)
+ if [[ ! -e ${TARGET} ]]; then
+ usage "image does not exist: ${TARGET}"
+ fi
+esac
+
+# start size part contents
+# 0 1 PMBR (Boot GUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE)
+# 1 1 Pri GPT header
+# 2 32 Pri GPT table
+# 2961408 12132352 1 Label: "STATE"
+# Type: Linux data
+# UUID: CC1A2390-0A9D-9D48-883B-626E7DD188CB
+# 20480 32768 2 Label: "KERN-A"
+# Type: ChromeOS kernel
+# UUID: 71B947BB-2396-314B-8C78-2A62CBFC8024
+# Attr: priority=15 tries=15 successful=0
+# 319488 2641920 3 Label: "ROOT-A"
+# Type: ChromeOS rootfs
+# UUID: 5D3E9883-6405-B44A-9E79-E1125B5FDC9B
+# 53248 32768 4 Label: "KERN-B"
+# Type: ChromeOS kernel
+# UUID: CC947588-A4F8-B64A-99DE-81243D71A4BE
+# Attr: priority=0 tries=0 successful=0
+# 315392 4096 5 Label: "ROOT-B"
+# Type: ChromeOS rootfs
+# UUID: 316ADC8E-FA80-194C-9C01-F562D280239F
+# 16448 1 6 Label: "KERN-C"
+# Type: ChromeOS kernel
+# UUID: 6AD6BA67-5ED6-5C43-9DE1-238C7DA83B1A
+# Attr: priority=0 tries=0 successful=0
+# 16449 1 7 Label: "ROOT-C"
+# Type: ChromeOS rootfs
+# UUID: AA474C7E-3368-8047-9CC4-C6459C867D53
+# 86016 32768 8 Label: "OEM"
+# Type: Linux data
+# UUID: 2B5DF82C-C3D0-4443-A90A-D2A3671D5C0E
+# 16450 1 9 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 23A9BEA8-8CCA-744C-9AD4-3408624F785D
+# 16451 1 10 Label: "reserved"
+# Type: ChromeOS reserved
+# UUID: 56E34019-7E1F-D244-A74F-D594B637A18F
+# 64 16384 11 Label: "RWFW"
+# Type: ChromeOS firmware
+# UUID: 529423BB-45F4-434B-846B-1A15A3ED987E
+# 249856 65536 12 Label: "EFI-SYSTEM"
+# Type: EFI System Partition
+# UUID: 09ADDEBB-0333-4B48-8E1D-CB43C88C95DE
+# Attr: legacy_boot=1
+# 15126495 32 Sec GPT table
+# 15126527 1 Sec GPT header
+case ${PART:-1} in
+1|"STATE")
+dd if="${TARGET}" of=part_1 bs=512 count=12132352 skip=2961408
+ln -sfT part_1 "part_1_STATE"
+esac
+case ${PART:-2} in
+2|"KERN-A")
+dd if="${TARGET}" of=part_2 bs=512 count=32768 skip=20480
+ln -sfT part_2 "part_2_KERN-A"
+esac
+case ${PART:-3} in
+3|"ROOT-A")
+dd if="${TARGET}" of=part_3 bs=512 count=2641920 skip=319488
+ln -sfT part_3 "part_3_ROOT-A"
+esac
+case ${PART:-4} in
+4|"KERN-B")
+dd if="${TARGET}" of=part_4 bs=512 count=32768 skip=53248
+ln -sfT part_4 "part_4_KERN-B"
+esac
+case ${PART:-5} in
+5|"ROOT-B")
+dd if="${TARGET}" of=part_5 bs=512 count=4096 skip=315392
+ln -sfT part_5 "part_5_ROOT-B"
+esac
+case ${PART:-6} in
+6|"KERN-C")
+dd if="${TARGET}" of=part_6 bs=512 count=1 skip=16448
+ln -sfT part_6 "part_6_KERN-C"
+esac
+case ${PART:-7} in
+7|"ROOT-C")
+dd if="${TARGET}" of=part_7 bs=512 count=1 skip=16449
+ln -sfT part_7 "part_7_ROOT-C"
+esac
+case ${PART:-8} in
+8|"OEM")
+dd if="${TARGET}" of=part_8 bs=512 count=32768 skip=86016
+ln -sfT part_8 "part_8_OEM"
+esac
+case ${PART:-9} in
+9|"reserved")
+dd if="${TARGET}" of=part_9 bs=512 count=1 skip=16450
+ln -sfT part_9 "part_9_reserved"
+esac
+case ${PART:-10} in
+10|"reserved")
+dd if="${TARGET}" of=part_10 bs=512 count=1 skip=16451
+ln -sfT part_10 "part_10_reserved"
+esac
+case ${PART:-11} in
+11|"RWFW")
+dd if="${TARGET}" of=part_11 bs=512 count=16384 skip=64
+ln -sfT part_11 "part_11_RWFW"
+esac
+case ${PART:-12} in
+12|"EFI-SYSTEM")
+dd if="${TARGET}" of=part_12 bs=512 count=65536 skip=249856
+ln -sfT part_12 "part_12_EFI-SYSTEM"
+esac
diff --git a/nichrome/scripts/vboot/bin/align_rootfs.sh b/nichrome/scripts/vboot/bin/align_rootfs.sh
new file mode 100755
index 000000000..e8056a33a
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/align_rootfs.sh
@@ -0,0 +1,150 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to preserve the on-disk file layout of the specified image and
+# the latest shipping image. This is accomplished by copying the new rootfs
+# over a template rootfs (aka the latest shipping image) to preserve as much
+# of the metadata from the shipping rootfs as possible. This will ensure
+# minimal disk shuffling when applying the auto-update.
+#
+# Note: This script does not recompute the rootfs hash.
+
+# Load common library. This should be the first executable line.
+# The path to common.sh should be relative to your script's location.
+. "$(dirname "$0")/common.sh"
+
+load_shflags
+
+# Flags.
+DEFINE_string image "" \
+ "The image that needs to be aligned to the latest shipping image."
+DEFINE_string src_image "" \
+ "The image to align against."
+
+# Copies the rootfs from |SRC_IMAGE| to the |DST_ROOT_FS| and preserves as
+# much of the file system metadata in |DST_ROOT_FS| as possible.
+# Args: SRC_IMAGE DST_ROOT_FS
+copy_root_fs() {
+ local src_image=$1
+ local dst_root_fs=$2
+
+ # Mount the src and dst rootfs.
+ local src_root_fs_dir=$(mktemp -d "/tmp/align_root_fs_src_mount_dir.XXXX")
+ add_cleanup_action "sudo rm -rf \"${src_root_fs_dir}\""
+ mount_image_partition_ro "${src_image}" 3 "${src_root_fs_dir}"
+ add_cleanup_action "sudo umount \"${src_root_fs_dir}\""
+
+ local dst_root_fs_dir=$(mktemp -d "/tmp/align_root_fs_dst_mount_dir.XXXX")
+ add_cleanup_action "sudo rm -rf \"${dst_root_fs_dir}\""
+ sudo mount -o loop "${dst_root_fs}" "${dst_root_fs_dir}" -o loop
+ add_cleanup_action "sudo umount \"${dst_root_fs_dir}\""
+
+ # Temporarily make immutable files on the dst rootfs mutable.
+ # We'll need to track these files in ${immutable_files} so we can make them
+ # mutable again.
+ local immutable_files=()
+ sudo find "${dst_root_fs_dir}" -xdev -type f |
+ while read -r file; do
+ immutable=$(sudo lsattr "${file}" | cut -d' ' -f1 | grep -q i ; echo $?)
+ if [ $immutable -eq 0 ]; then
+ immutable_files=("${immutable_files[@]}" "${file}")
+ sudo chattr -i "${file}"
+ fi
+ done
+
+ # Copy files from the src rootfs over top of dst rootfs.
+ # Use the --inplace flag to preserve as much of the file system metadata
+ # as possible.
+ sudo rsync -v -a -H -A -x --force --inplace --numeric-ids --delete \
+ "${src_root_fs_dir}"/ "${dst_root_fs_dir}"
+
+ # Make immutable files immutable again.
+ for file in ${immutable_files[*]} ; do
+ sudo chattr +i "${file}"
+ done
+
+ # Unmount the src and dst root fs so that we can replace the rootfs later.
+ perform_latest_cleanup_action
+ perform_latest_cleanup_action
+ perform_latest_cleanup_action
+ perform_latest_cleanup_action
+}
+
+# Zeroes the rootfs free space in the specified image.
+# Args: IMAGE
+zero_root_fs_free_space() {
+ local image=$1
+ local root_fs_dir=$(mktemp -d "/tmp/align_rootfs_zero_free_space_dir.XXXX")
+ add_cleanup_action "sudo rm -rf \"${root_fs_dir}\""
+ mount_image_partition "${image}" 3 "${root_fs_dir}"
+ add_cleanup_action "sudo umount \"${root_fs_dir}\""
+
+ info "Zeroing free space in rootfs"
+ sudo dd if=/dev/zero of="${root_fs_dir}/filler" oflag=sync bs=4096 || true
+ sudo rm -f "${root_fs_dir}/filler"
+ sudo sync
+
+ perform_latest_cleanup_action
+ perform_latest_cleanup_action
+}
+
+main() {
+ # Parse command line.
+ FLAGS "$@" || exit 1
+ eval set -- "${FLAGS_ARGV}"
+
+ # Only now can we die on error. shflags functions leak non-zero error codes,
+ # so will die prematurely if 'set -e' is specified before now.
+ set -e
+
+ # Make sure we have the required parameters.
+ if [ -z "${FLAGS_image}" ]; then
+ die "--image is required."
+ fi
+
+ if [ ! -f "${FLAGS_image}" ]; then
+ die "Cannot find the specified image."
+ fi
+
+ if [ -z "${FLAGS_src_image}" ]; then
+ die "--src_image is required."
+ fi
+
+ if [ ! -f "${FLAGS_src_image}" ]; then
+ die "Cannot find the specified source image."
+ fi
+
+ # Make sure the two rootfs are the same size.
+ # If they are not, then there is nothing for us to do.
+ # Note: Exit with a zero code so we do not break the build workflow.
+ local src_root_fs_size=$(partsize "${FLAGS_src_image}" 3)
+ local new_root_fs_size=$(partsize "${FLAGS_image}" 3)
+ if [ ${src_root_fs_size} -ne ${new_root_fs_size} ]; then
+ warn "The source rootfs and the new rootfs are not the same size."
+ exit 0
+ fi
+
+ # Extract the rootfs from the src image and use this as a template
+ # for the new image.
+ temp_root_fs=$(mktemp "/tmp/align_rootfs_temp_rootfs.XXXX")
+ add_cleanup_action "sudo rm -f \"${temp_root_fs}\""
+ info "Extracting rootfs from src image"
+ extract_image_partition "${FLAGS_src_image}" 3 "${temp_root_fs}"
+ enable_rw_mount "${temp_root_fs}"
+
+ # Perform actual copy of the two root file systems.
+ info "Copying rootfs"
+ copy_root_fs "${FLAGS_image}" "${temp_root_fs}"
+
+ # Replace the rootfs in the new image with the aligned version.
+ info "Replacing rootfs"
+ replace_image_partition "${FLAGS_image}" 3 "${temp_root_fs}"
+
+ # Zero rootfs free space.
+ zero_root_fs_free_space "${FLAGS_image}"
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/common.sh b/nichrome/scripts/vboot/bin/common.sh
new file mode 100755
index 000000000..f100be564
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/common.sh
@@ -0,0 +1,152 @@
+#!/bin/bash
+#
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+. "$(dirname "$0")/common_minimal.sh"
+CROS_LOG_PREFIX="${PROG}: "
+
+# Array of actions that are executed during the clean up process.
+declare -a cleanup_actions
+
+# Adds an action to be executed during the clean up process.
+# Actions are executed in the reverse order of when they were added.
+# ARGS: ACTION
+add_cleanup_action() {
+ cleanup_actions[${#cleanup_actions[*]}]=$1
+}
+
+# Performs the latest clean up action and removes it from the list.
+perform_latest_cleanup_action() {
+ local num_actions=${#cleanup_actions[*]}
+ if [ ${num_actions} -gt 0 ]; then
+ eval "${cleanup_actions[$num_actions-1]}" > /dev/null 2>&1
+ unset cleanup_actions[$num_actions-1]
+ fi
+}
+
+# Performs clean up by executing actions in the cleanup_actions array in
+# reversed order.
+cleanup() {
+ set +e
+
+ while [ ${#cleanup_actions[*]} -gt 0 ]; do
+ perform_latest_cleanup_action
+ done
+
+ set -e
+}
+
+# ANSI color codes used when displaying messages.
+# Taken from src/scripts/common.sh.
+V_RED="\e[31m"
+V_YELLOW="\e[33m"
+V_BOLD_GREEN="\e[1;32m"
+V_BOLD_RED="\e[1;31m"
+V_BOLD_YELLOW="\e[1;33m"
+V_VIDOFF="\e[0m"
+
+# Prints an informational message.
+# Taken from src/scripts/common.sh.
+# Arg: MESSAGE
+info() {
+ echo -e >&2 "${V_BOLD_GREEN}${CROS_LOG_PREFIX:-}INFO : $1${V_VIDOFF}"
+}
+
+# Prints a warning message.
+# Taken from src/scripts/common.sh.
+# Arg: MESSAGE
+warn() {
+ echo -e >&2 "${V_BOLD_YELLOW}${CROS_LOG_PREFIX:-}WARNING: $1${V_VIDOFF}"
+}
+
+# Prints the specified error and exit the script with an error code.
+# Taken from src/scripts/common.sh.
+# Args: MESSAGE
+error() {
+ echo -e >&2 "${V_BOLD_RED}${CROS_LOG_PREFIX:-}ERROR : $1${V_VIDOFF}"
+}
+
+TEMP_LOOP_LIST=$(mktemp)
+
+# Setup a loopback device for a file and scan for partitions, with retries.
+#
+# $1 - The file to back the new loopback device.
+# $2-$N - Additional arguments to pass to losetup.
+loopback_partscan() {
+ local lb_dev image="$1"
+ shift
+
+ # We know partition scanning & dev node creation can be racy with udev and
+ # the kernel, and the kernel does not sleep/wait for it to finish. We have
+ # to use the partx tool manually as it will sleep until things are finished.
+ lb_dev=$(sudo losetup --show -f "$@" "${image}")
+
+ # Cache the path so we can clean it up.
+ echo "${lb_dev}" >>"${TEMP_LOOP_LIST}"
+
+ # Ignore problems deleting existing partitions. There shouldn't be any
+ # which will upset partx, but that's actually ok.
+ sudo partx -d "${lb_dev}" 2>/dev/null || true
+ sudo partx -a "${lb_dev}"
+
+ echo "${lb_dev}"
+}
+
+# Detach a loopback device set up earlier.
+#
+# $1 - The loop device to detach.
+# $2-$N - Additional arguments to pass to losetup.
+loopback_detach() {
+ # Retry the deletes before we detach. crbug.com/469259
+ local i
+ for (( i = 0; i < 10; i++ )); do
+ if sudo partx -d "$1"; then
+ break
+ fi
+ warn "Sleeping & retrying ..."
+ sync
+ sleep 1
+ done
+ sudo losetup --detach "$@"
+}
+
+# Clear out all loopback devices we setup.
+cleanup_loopbacks() {
+ local line
+ while read -r line; do
+ loopback_detach "${line}" 2>/dev/null
+ done <"${TEMP_LOOP_LIST}"
+ rm -f "${TEMP_LOOP_LIST}"
+}
+
+# Usage: lsbval path-to-lsb-file key
+# Returns the value for the given lsb-release file variable.
+lsbval() {
+ local lsbfile="$1"
+ local key="$2"
+ grep "^${key}=" "${lsbfile}" | sed "s/^${key}=//"
+}
+
+# Usage: get_board_from_lsb_release rootfs
+# Returns the exact board name from /etc/lsb-release. This may contain
+# dashes or other characters not suitable for variable names. See the
+# next function for that.
+get_board_from_lsb_release() {
+ local rootfs="$1"
+ lsbval "${rootfs}/etc/lsb-release" CHROMEOS_RELEASE_BOARD
+}
+
+# Usage: get_boardvar_from_lsb_release rootfs
+# Returns the board name from /etc/lsb-release in a mangled form that can
+# be used in variable names. e.g. dashes are turned into underscores.
+get_boardvar_from_lsb_release() {
+ get_board_from_lsb_release "$@" | sed 's:[-]:_:g'
+}
+
+# This will override the trap set in common_minmal.sh
+trap "cleanup" INT TERM EXIT
+
+add_cleanup_action "cleanup_temps_and_mounts"
+add_cleanup_action "cleanup_loopbacks"
diff --git a/nichrome/scripts/vboot/bin/common_minimal.sh b/nichrome/scripts/vboot/bin/common_minimal.sh
new file mode 100755
index 000000000..c130b918f
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/common_minimal.sh
@@ -0,0 +1,388 @@
+#!/bin/sh
+#
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Note: This file must be written in dash compatible way as scripts that use
+# this may run in the Chrome OS client enviornment.
+
+# Determine script directory
+SCRIPT_DIR=$(dirname $0)
+PROG=$(basename $0)
+GPT=${GPT:-"cgpt"}
+
+# The tag when the rootfs is changed.
+TAG_NEEDS_TO_BE_SIGNED="/root/.need_to_be_signed"
+
+# List of Temporary files and mount points.
+TEMP_FILE_LIST=$(mktemp)
+TEMP_DIR_LIST=$(mktemp)
+
+# Finds and loads the 'shflags' library, or return as failed.
+load_shflags() {
+ # Load shflags
+ if [ -f /usr/share/misc/shflags ]; then
+ . /usr/share/misc/shflags
+ elif [ -f "${SCRIPT_DIR}/lib/shflags/shflags" ]; then
+ . "${SCRIPT_DIR}/lib/shflags/shflags"
+ else
+ echo "ERROR: Cannot find the required shflags library."
+ return 1
+ fi
+
+ # Add debug option for debug output below
+ DEFINE_boolean debug $FLAGS_FALSE "Provide debug messages" "d"
+}
+
+# Functions for debug output
+# ----------------------------------------------------------------------------
+
+# These helpers are for runtime systems. For scripts using common.sh,
+# they'll get better definitions that will clobber these ones.
+info() {
+ echo "${PROG}: INFO: $*" >&2
+}
+
+warn() {
+ echo "${PROG}: WARN: $*" >&2
+}
+
+error() {
+ echo "${PROG}: ERROR: $*" >&2
+}
+
+# Reports error message and exit(1)
+# Args: error message
+die() {
+ error "$@"
+ exit 1
+}
+
+# Returns true if we're running in debug mode.
+#
+# Note that if you don't set up shflags by calling load_shflags(), you
+# must set $FLAGS_debug and $FLAGS_TRUE yourself. The default
+# behavior is that debug will be off if you define neither $FLAGS_TRUE
+# nor $FLAGS_debug.
+is_debug_mode() {
+ [ "${FLAGS_debug:-not$FLAGS_TRUE}" = "$FLAGS_TRUE" ]
+}
+
+# Prints messages (in parameters) in debug mode
+# Args: debug message
+debug_msg() {
+ if is_debug_mode; then
+ echo "DEBUG: $*" 1>&2
+ fi
+}
+
+# Functions for temporary files and directories
+# ----------------------------------------------------------------------------
+
+# Create a new temporary file and return its name.
+# File is automatically cleaned when cleanup_temps_and_mounts() is called.
+make_temp_file() {
+ local tempfile=$(mktemp)
+ echo "$tempfile" >> $TEMP_FILE_LIST
+ echo $tempfile
+}
+
+# Create a new temporary directory and return its name.
+# Directory is automatically deleted and any filesystem mounted on it unmounted
+# when cleanup_temps_and_mounts() is called.
+make_temp_dir() {
+ local tempdir=$(mktemp -d)
+ echo "$tempdir" >> $TEMP_DIR_LIST
+ echo $tempdir
+}
+
+cleanup_temps_and_mounts() {
+ for i in $(cat $TEMP_FILE_LIST); do
+ rm -f $i
+ done
+ set +e # umount may fail for unmounted directories
+ for i in $(cat $TEMP_DIR_LIST); do
+ if [ -n "$i" ]; then
+ if has_needs_to_be_resigned_tag "$i"; then
+ echo "Warning: image may be modified. Please resign image."
+ fi
+ sudo umount $i 2>/dev/null
+ rm -rf $i
+ fi
+ done
+ set -e
+ rm -rf $TEMP_DIR_LIST $TEMP_FILE_LIST
+}
+
+trap "cleanup_temps_and_mounts" EXIT
+
+# Functions for partition management
+# ----------------------------------------------------------------------------
+
+# Construct a partition device name from a whole disk block device and a
+# partition number.
+# This works for [/dev/sda, 3] (-> /dev/sda3) as well as [/dev/mmcblk0, 2]
+# (-> /dev/mmcblk0p2).
+make_partition_dev() {
+ local block="$1"
+ local num="$2"
+ # If the disk block device ends with a number, we add a 'p' before the
+ # partition number.
+ if [ "${block%[0-9]}" = "${block}" ]; then
+ echo "${block}${num}"
+ else
+ echo "${block}p${num}"
+ fi
+}
+
+# Read GPT table to find the starting location of a specific partition.
+# Args: DEVICE PARTNUM
+# Returns: offset (in sectors) of partition PARTNUM
+partoffset() {
+ sudo $GPT show -b -i $2 $1
+}
+
+# Read GPT table to find the size of a specific partition.
+# Args: DEVICE PARTNUM
+# Returns: size (in sectors) of partition PARTNUM
+partsize() {
+ sudo $GPT show -s -i $2 $1
+}
+
+# Tags a file system as "needs to be resigned".
+# Args: MOUNTDIRECTORY
+tag_as_needs_to_be_resigned() {
+ local mount_dir="$1"
+ sudo touch "$mount_dir/$TAG_NEEDS_TO_BE_SIGNED"
+}
+
+# Determines if the target file system has the tag for resign
+# Args: MOUNTDIRECTORY
+# Returns: true if the tag is there otherwise false
+has_needs_to_be_resigned_tag() {
+ local mount_dir="$1"
+ [ -f "$mount_dir/$TAG_NEEDS_TO_BE_SIGNED" ]
+}
+
+# Determines if the target file system is a Chrome OS root fs
+# Args: MOUNTDIRECTORY
+# Returns: true if MOUNTDIRECTORY looks like root fs, otherwise false
+is_rootfs_partition() {
+ local mount_dir="$1"
+ [ -f "$mount_dir/$(dirname "$TAG_NEEDS_TO_BE_SIGNED")" ]
+}
+
+# If the kernel is buggy and is unable to loop+mount quickly,
+# retry the operation a few times.
+# Args: IMAGE PARTNUM MOUNTDIRECTORY [ro]
+#
+# This function does not check whether the partition is allowed to be mounted as
+# RW. Callers must ensure the partition can be mounted as RW before calling
+# this function without |ro| argument.
+_mount_image_partition_retry() {
+ local image=$1
+ local partnum=$2
+ local mount_dir=$3
+ local ro=$4
+ local offset=$(( $(partoffset "${image}" "${partnum}") * 512 ))
+ local out try
+
+ set -- sudo LC_ALL=C mount -o loop,offset=${offset},${ro} \
+ "${image}" "${mount_dir}"
+ try=1
+ while [ ${try} -le 5 ]; do
+ if ! out=$("$@" 2>&1); then
+ if [ "${out}" = "mount: you must specify the filesystem type" ]; then
+ printf 'WARNING: mounting %s at %s failed (try %i); retrying\n' \
+ "${image}" "${mount_dir}" "${try}"
+ # Try to "quiet" the disks and sleep a little to reduce contention.
+ sync
+ sleep $(( try * 5 ))
+ else
+ # Failed for a different reason; abort!
+ break
+ fi
+ else
+ # It worked!
+ return 0
+ fi
+ : $(( try += 1 ))
+ done
+ echo "ERROR: mounting ${image} at ${mount_dir} failed:"
+ echo "${out}"
+ # We don't preserve the exact exit code of `mount`, but since
+ # no one in this code base seems to check it, it's a moot point.
+ return 1
+}
+
+# If called without 'ro', make sure the partition is allowed to be mounted as
+# 'rw' before actually mounting it.
+# Args: IMAGE PARTNUM MOUNTDIRECTORY [ro]
+_mount_image_partition() {
+ local image=$1
+ local partnum=$2
+ local mount_dir=$3
+ local ro=$4
+ local offset=$(( $(partoffset "${image}" "${partnum}") * 512 ))
+
+ if [ "$ro" != "ro" ]; then
+ # Forcibly call enable_rw_mount. It should fail on unsupported
+ # filesystems and be idempotent on ext*.
+ enable_rw_mount "${image}" ${offset} 2> /dev/null
+ fi
+
+ _mount_image_partition_retry "$@"
+}
+
+# Mount a partition read-only from an image into a local directory
+# Args: IMAGE PARTNUM MOUNTDIRECTORY
+mount_image_partition_ro() {
+ _mount_image_partition "$@" "ro"
+}
+
+# Mount a partition from an image into a local directory
+# Args: IMAGE PARTNUM MOUNTDIRECTORY
+mount_image_partition() {
+ local mount_dir=$3
+ _mount_image_partition "$@"
+ if is_rootfs_partition "${mount_dir}"; then
+ tag_as_needs_to_be_resigned "${mount_dir}"
+ fi
+}
+
+# Extract a partition to a file
+# Args: IMAGE PARTNUM OUTPUTFILE
+extract_image_partition() {
+ local image=$1
+ local partnum=$2
+ local output_file=$3
+ local offset=$(partoffset "$image" "$partnum")
+ local size=$(partsize "$image" "$partnum")
+ dd if=$image of=$output_file bs=512 skip=$offset count=$size \
+ conv=notrunc 2>/dev/null
+}
+
+# Replace a partition in an image from file
+# Args: IMAGE PARTNUM INPUTFILE
+replace_image_partition() {
+ local image=$1
+ local partnum=$2
+ local input_file=$3
+ local offset=$(partoffset "$image" "$partnum")
+ local size=$(partsize "$image" "$partnum")
+ dd if=$input_file of=$image bs=512 seek=$offset count=$size \
+ conv=notrunc 2>/dev/null
+}
+
+# For details, see crosutils.git/common.sh
+enable_rw_mount() {
+ local rootfs="$1"
+ local offset="${2-0}"
+
+ # Make sure we're checking an ext2 image
+ if ! is_ext2 "$rootfs" $offset; then
+ echo "enable_rw_mount called on non-ext2 filesystem: $rootfs $offset" 1>&2
+ return 1
+ fi
+
+ local ro_compat_offset=$((0x464 + 3)) # Set 'highest' byte
+ # Dash can't do echo -ne, but it can do printf "\NNN"
+ # We could use /dev/zero here, but this matches what would be
+ # needed for disable_rw_mount (printf '\377').
+ printf '\000' |
+ sudo dd of="$rootfs" seek=$((offset + ro_compat_offset)) \
+ conv=notrunc count=1 bs=1 2>/dev/null
+}
+
+# For details, see crosutils.git/common.sh
+is_ext2() {
+ local rootfs="$1"
+ local offset="${2-0}"
+
+ # Make sure we're checking an ext2 image
+ local sb_magic_offset=$((0x438))
+ local sb_value=$(sudo dd if="$rootfs" skip=$((offset + sb_magic_offset)) \
+ count=2 bs=1 2>/dev/null)
+ local expected_sb_value=$(printf '\123\357')
+ if [ "$sb_value" = "$expected_sb_value" ]; then
+ return 0
+ fi
+ return 1
+}
+
+disable_rw_mount() {
+ local rootfs="$1"
+ local offset="${2-0}"
+
+ # Make sure we're checking an ext2 image
+ if ! is_ext2 "$rootfs" $offset; then
+ echo "disable_rw_mount called on non-ext2 filesystem: $rootfs $offset" 1>&2
+ return 1
+ fi
+
+ local ro_compat_offset=$((0x464 + 3)) # Set 'highest' byte
+ # Dash can't do echo -ne, but it can do printf "\NNN"
+ # We could use /dev/zero here, but this matches what would be
+ # needed for disable_rw_mount (printf '\377').
+ printf '\377' |
+ sudo dd of="$rootfs" seek=$((offset + ro_compat_offset)) \
+ conv=notrunc count=1 bs=1 2>/dev/null
+}
+
+rw_mount_disabled() {
+ local rootfs="$1"
+ local offset="${2-0}"
+
+ # Make sure we're checking an ext2 image
+ if ! is_ext2 "$rootfs" $offset; then
+ return 2
+ fi
+
+ local ro_compat_offset=$((0x464 + 3)) # Set 'highest' byte
+ local ro_value=$(sudo dd if="$rootfs" skip=$((offset + ro_compat_offset)) \
+ count=1 bs=1 2>/dev/null)
+ local expected_ro_value=$(printf '\377')
+ if [ "$ro_value" = "$expected_ro_value" ]; then
+ return 0
+ fi
+ return 1
+}
+
+# Misc functions
+# ----------------------------------------------------------------------------
+
+# Parses the version file containing key=value lines
+# Args: key file
+# Returns: value
+get_version() {
+ local key="$1"
+ local file="$2"
+ awk -F= -vkey="${key}" '$1 == key { print $NF }' "${file}"
+}
+
+# Returns true if all files in parameters exist.
+# Args: List of files
+ensure_files_exist() {
+ local filename return_value=0
+ for filename in "$@"; do
+ if [ ! -f "$filename" -a ! -b "$filename" ]; then
+ echo "ERROR: Cannot find required file: $filename"
+ return_value=1
+ fi
+ done
+
+ return $return_value
+}
+
+# Check if the 'chronos' user already has a password
+# Args: rootfs
+no_chronos_password() {
+ local rootfs=$1
+ # Make sure the chronos user actually exists.
+ if grep -qs '^chronos:' "${rootfs}/etc/passwd"; then
+ sudo grep -q '^chronos:\*:' "${rootfs}/etc/shadow"
+ fi
+}
+
+trap "cleanup_temps_and_mounts" EXIT
diff --git a/nichrome/scripts/vboot/bin/convert_recovery_to_full_ssd.sh b/nichrome/scripts/vboot/bin/convert_recovery_to_full_ssd.sh
new file mode 100755
index 000000000..c249a4f70
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/convert_recovery_to_full_ssd.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to convert a recovery image into an SSD image usable by factory.
+
+# TODO(gauravsh): crosbug.com/14790 (Merge this with
+# convert_recovery_to_ssd.sh)
+
+# Load common constants and variables.
+. "$(dirname "$0")/common_minimal.sh"
+
+usage() {
+ cat <
+
+Converts into a full SSD image usable by factory. Uses
+stateful partition from SSD image .
+EOF
+}
+
+if [ $# -ne 3 ]; then
+ usage
+ exit 1
+fi
+
+type -P cgpt &>/dev/null ||
+ { echo "cgpt tool must be in the path"; exit 1; }
+
+# Abort on errors.
+set -e
+
+RECOVERY_IMAGE=$1
+IMAGE_ZIP=$2
+SSD_IMAGE=$3
+
+work_dir=$(make_temp_dir)
+
+echo "Extracting original SSD image."
+unzip -o $IMAGE_ZIP chromiumos_base_image.bin -d ${work_dir}
+
+mv ${work_dir}/chromiumos_base_image.bin ${SSD_IMAGE}
+
+kerna_offset=$(partoffset ${RECOVERY_IMAGE} 2)
+kernb_offset=$(partoffset ${RECOVERY_IMAGE} 4)
+# Kernel partition sizes should be the same.
+kern_size=$(partsize ${RECOVERY_IMAGE} 2)
+
+rootfs=$(make_temp_file)
+echo "Replacing RootFS on the SSD with that of the RECOVERY image"
+extract_image_partition ${RECOVERY_IMAGE} 3 ${rootfs}
+replace_image_partition ${SSD_IMAGE} 3 ${rootfs}
+
+kerna=$(make_temp_file)
+echo "Replacing KernelA on the SSD with that of the RECOVERY image"
+extract_image_partition ${RECOVERY_IMAGE} 4 ${kerna}
+replace_image_partition ${SSD_IMAGE} 2 ${kerna}
+
+# Overwrite the kernel vblock on the created SSD image.
+stateful_dir=$(make_temp_dir)
+tmp_vblock=$(make_temp_file)
+mount_image_partition_ro ${RECOVERY_IMAGE} 1 ${stateful_dir}
+sudo cp ${stateful_dir}/vmlinuz_hd.vblock ${tmp_vblock}
+echo "Overwriting kernel vblock with SSD kernel vblock"
+sudo dd if=${tmp_vblock} of=${SSD_IMAGE} seek=${kerna_offset} bs=512 \
+ conv=notrunc
+sudo umount ${stateful_dir}
+
+# Zero out Kernel B partition.
+echo "Zeroing out Kernel partition B"
+sudo dd if=/dev/zero of=${SSD_IMAGE} seek=${kernb_offset} bs=512 \
+ count=${kern_size} conv=notrunc
+echo "${RECOVERY_IMAGE} was converted to a factory SSD image: ${SSD_IMAGE}"
diff --git a/nichrome/scripts/vboot/bin/convert_recovery_to_ssd.sh b/nichrome/scripts/vboot/bin/convert_recovery_to_ssd.sh
new file mode 100755
index 000000000..200efee0a
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/convert_recovery_to_ssd.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to convert a recovery image into an SSD image. Changes are made in-
+# place.
+
+usage() {
+ cat < [--force] [--cgpt=/path/to/cgpt]
+
+In-place converts recovery into an SSD image. With --force, does not
+ask for confirmation from the user. Use --cgpt= to specify cgpt binary location.
+
+EOF
+ exit 1
+}
+
+if [ $# -lt 1 ] || [ $# -gt 3 ]; then
+ usage
+else
+ IMAGE=$1
+ shift
+fi
+
+for arg in $*; do
+ case "$arg" in
+ --force)
+ IS_FORCE=$arg
+ ;;
+ --cgpt=*)
+ GPT=${arg#--cgpt=}
+ ;;
+ *)
+ usage
+ ;;
+ esac
+done
+
+# Load common constants (and use GPT if set above) and variables.
+. "$(dirname "$0")/common_minimal.sh"
+
+type -P $GPT &>/dev/null ||
+ { echo "cgpt tool must be in the path or specified via --cgpt"; exit 1; }
+
+# Abort on errors.
+set -e
+
+if [ "${IS_FORCE}" != "--force" ]; then
+ echo "This will modify ${IMAGE} in-place and convert it into an SSD image."
+ read -p "Are you sure you want to continue (y/N)?" SURE
+ SURE="${SURE:0:1}"
+ [ "${SURE}" != "y" ] && exit 1
+fi
+
+kerna_offset=$(partoffset ${IMAGE} 2)
+kernb_offset=$(partoffset ${IMAGE} 4)
+# Kernel partition sizes should be the same.
+kern_size=$(partsize ${IMAGE} 2)
+
+# Move Kernel B to Kernel A.
+kernb=$(make_temp_file)
+echo "Replacing Kernel partition A with Kernel partition B"
+extract_image_partition ${IMAGE} 4 ${kernb}
+replace_image_partition ${IMAGE} 2 ${kernb}
+
+# Overwrite the vblock.
+stateful_dir=$(make_temp_dir)
+tmp_vblock=$(make_temp_file)
+mount_image_partition_ro ${IMAGE} 1 ${stateful_dir}
+sudo cp ${stateful_dir}/vmlinuz_hd.vblock ${tmp_vblock}
+# Unmount before overwriting image to avoid sync issues.
+sudo umount ${stateful_dir}
+echo "Overwriting kernel partition A vblock with SSD vblock"
+sudo dd if=${tmp_vblock} of=${IMAGE} seek=${kerna_offset} bs=512 conv=notrunc
+
+# Zero out Kernel B partition.
+echo "Zeroing out Kernel partition B"
+sudo dd if=/dev/zero of=${IMAGE} seek=${kernb_offset} bs=512 count=${kern_size} conv=notrunc
+echo "${IMAGE} was converted to an SSD image."
diff --git a/nichrome/scripts/vboot/bin/ensure_no_nonrelease_files.sh b/nichrome/scripts/vboot/bin/ensure_no_nonrelease_files.sh
new file mode 100755
index 000000000..e83a2ba8e
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/ensure_no_nonrelease_files.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Abort on error.
+set -e
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+usage() {
+ echo "Usage $PROG image [config]"
+}
+
+main() {
+ # We want to catch all the discrepancies, not just the first one.
+ # So, any time we find one, we set testfail=1 and continue.
+ # When finished we will use testfail to determine our exit value.
+ local testfail=0
+
+ if [[ $# -ne 1 ]] && [[ $# -ne 2 ]]; then
+ usage
+ exit 1
+ fi
+
+ local image="$1"
+
+ # Default config location: same name/directory as this script,
+ # with a .config file extension, ie ensure_no_nonrelease_files.config.
+ local configfile="$(dirname "$0")/${0/%.sh/.config}"
+ # Or, maybe a config was provided on the command line.
+ if [[ $# -eq 2 ]]; then
+ configfile="$2"
+ fi
+ # Either way, load test-expectations data from config.
+ . "${configfile}" || return 1
+
+ local rootfs=$(make_temp_dir)
+ mount_image_partition_ro "${image}" 3 "${rootfs}"
+ # Pick the right set of test-expectation data to use.
+ local boardvar=$(get_boardvar_from_lsb_release "${rootfs}")
+ eval "release_file_blacklist=(\"\${RELEASE_FILE_BLACKLIST_${boardvar}[@]}\")"
+
+ for file in ${release_file_blacklist}; do
+ if [ -e "${rootfs}/${file}" ]; then
+ error "${file} exists in this image!"
+ ls -al "${rootfs}/${file}"
+ testfail=1
+ fi
+ done
+
+ # Verify that session_manager isn't configured to pass additional
+ # environment variables or command-line arguments to Chrome.
+ local config_path="${rootfs}/etc/chrome_dev.conf"
+ local matches=$(grep -s "^[^#]" "${config_path}")
+ if [ -n "${matches}" ]; then
+ error "Found commands in ${config_path}:"
+ error "${matches}"
+ testfail=1
+ fi
+
+ exit ${testfail}
+}
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/ensure_no_password.sh b/nichrome/scripts/vboot/bin/ensure_no_password.sh
new file mode 100755
index 000000000..10363bf34
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/ensure_no_password.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# abort on error
+set -e
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+if [ $# -ne 1 ]; then
+ echo "Usage $0 "
+ exit 1
+fi
+
+IMAGE=$1
+ROOTFS=$(make_temp_dir)
+mount_image_partition_ro "$IMAGE" 3 "$ROOTFS"
+
+if ! no_chronos_password $ROOTFS; then
+ die "chronos password is set! Shouldn't be for release builds."
+fi
diff --git a/nichrome/scripts/vboot/bin/ensure_not_ASAN.sh b/nichrome/scripts/vboot/bin/ensure_not_ASAN.sh
new file mode 100755
index 000000000..5ea51660a
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/ensure_not_ASAN.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Abort on error.
+set -e
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+usage() {
+ echo "Usage $PROG image"
+}
+
+main() {
+ if [ $# -ne 1 ]; then
+ usage
+ exit 1
+ fi
+
+ local image="$1"
+
+ local rootfs=$(make_temp_dir)
+ mount_image_partition_ro "$image" 3 "$rootfs"
+
+ # This mirrors the check performed in the platform_ToolchainOptions
+ # autotest.
+ if readelf -s "$rootfs/opt/google/chrome/chrome" | \
+ grep -q __asan_init; then
+ exit 1
+ fi
+}
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/ensure_sane_lsb-release.sh b/nichrome/scripts/vboot/bin/ensure_sane_lsb-release.sh
new file mode 100755
index 000000000..9e5a179da
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/ensure_sane_lsb-release.sh
@@ -0,0 +1,155 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Abort on error.
+set -e
+
+LSB_FILE=/etc/lsb-release
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+usage() {
+ echo "Usage $PROG image [config]"
+}
+
+# Usage: lsbequals path-to-lsb-file key expected-value
+# Returns 0 if they match, 1 otherwise.
+# Also outputs a warning message if they don't match.
+lsbequals() {
+ local lsbfile="$1"
+ local key="$2"
+ local expectval="$3"
+ local realval=$(lsbval "$lsbfile" $key)
+ if [ "$realval" != "$expectval" ]; then
+ error "${key} mismatch. Expected '${expectval}'," \
+ "image contains '${realval}'"
+ return 1
+ fi
+ return 0
+}
+
+# Usage: check_keyval_in_list lsbfile lsbkey [list of values]
+# Extracts the lsb-release value for the specified key, and confirms it
+# matches one of the whitelisted values specified in value_array.
+# Implementation note:
+# You can't really pass bash arrays to functions. Best you can do is either
+# serialize to string/pass/deserialize (e.g. using whitspace/IFS hacks), or,
+# let the array contents be received as multiple arguments to the target
+# function. We take the latter approach here, hence the shift's to get the
+# first 2 arguments out, before we process the rest of the varargs.
+check_keyval_in_list() {
+ local lsbfile="$1"
+ shift
+ local lsbkey="$1"
+ shift
+ local lsbval=$(lsbval "$lsbfile" "$lsbkey")
+ while [ $# -gt 0 ]; do
+ if [ "$lsbval" == "$1" ]; then
+ return 0
+ fi
+ shift
+ done
+ # If we get here, it wasn't found
+ error "${lsbkey}: Value '${lsbval}' was not recognized"
+ return 1
+}
+
+# Usage: lsb_syntaxcheck path-to-lsb-file
+# Enforces a number of basic sanity checks on the overall format and contents
+# of the lsb-release file:
+# - Every line is "key=value".
+# - No space after key, no space before value.
+# - key is all A-Z or _, but not starting with _.
+# - value is made up of printable characters, or is empty.
+# - Each line is a reasonable size (<255 bytes).
+# - The whole file is a reasonable size (4kb).
+lsb_syntaxcheck() {
+ local lsbfile="$1"
+ syntaxbad=0
+ # Checks for key being A-Z_, 1 or more characters, not starting with _.
+ # Also checks for = with no spaces on either side.
+ # Checks that the value contains printables (and not starting with space).
+ # Alternatively, the value is permitted to be empty (0 chars) too.
+ badlines=$(grep -Ev '^[A-Z][A-Z_]*=([[:graph:]][[:print:]]*)?$' "$lsbfile")
+ if [ -n "$badlines" ]; then
+ syntaxbad=1
+ error "${lsbfile}: Some lines seem non-well-formed:"
+ error "${badlines}"
+ fi
+
+ # Checks for a lines exceeding a reasonable overall length.
+ badlines=$(grep -E '^.{255}' "$lsbfile")
+ if [ -n "$badlines" ]; then
+ syntaxbad=1
+ error "${lsbfile}: Some lsb-release lines seem unreasonably long:"
+ error "${badlines}"
+ fi
+ # Overall file size check:
+ size=$(ls -sk "$lsbfile" | cut -d ' ' -f 1)
+ if [ $size -gt 4 ]; then
+ syntaxbad=1
+ error "${lsbfile}: This file exceeds 4kb"
+ fi
+ return $syntaxbad
+}
+
+main() {
+ # We want to catch all the discrepancies, not just the first one.
+ # So, any time we find one, we set testfail=1 and continue.
+ # When finished we will use testfail to determine our exit value.
+ local testfail=0
+
+ if [ $# -ne 1 ] && [ $# -ne 2 ]; then
+ usage
+ exit 1
+ fi
+
+ local image="$1"
+
+ # Default config location: same directory as this script.
+ local configfile="$(dirname "$0")/default_lsb_release.config"
+ # Or, maybe a config was provided on the command line.
+ if [ $# -eq 2 ]; then
+ configfile="$2"
+ fi
+ # Either way, load test-expectations data from config.
+ info "Loading config from ${configfile}"
+ . "$configfile" || return 1
+
+ local rootfs=$(make_temp_dir)
+ mount_image_partition_ro "$image" 3 "$rootfs"
+ local lsb="$rootfs/$LSB_FILE"
+
+ # Basic syntax check first.
+ lsb_syntaxcheck "$lsb" || testfail=1
+
+ lsbequals $lsb CHROMEOS_AUSERVER "$expected_auserver" || testfail=1
+ lsbequals $lsb CHROMEOS_RELEASE_NAME "$expected_release_name" || testfail=1
+ check_keyval_in_list $lsb CHROMEOS_RELEASE_TRACK \
+ "${expected_release_tracks[@]}" || testfail=1
+
+ local board=$(get_board_from_lsb_release "${rootfs}")
+ if check_keyval_in_list $lsb CHROMEOS_RELEASE_BOARD \
+ "${expected_boards[@]}"; then
+ local boardvar=$(get_boardvar_from_lsb_release "${rootfs}")
+ channel=$(lsbval $lsb CHROMEOS_RELEASE_TRACK)
+ # For a canary or dogfood channel, appid maybe a different default value.
+ if [ $channel = 'canary-channel' ] || [ $channel = 'dogfood-channel' ]; then
+ eval "expected_appid=\"\$expected_appid_${channel%\-channel}\""
+ else
+ eval "expected_appid=\"\$expected_appid_$boardvar\""
+ fi
+ lsbequals $lsb CHROMEOS_RELEASE_APPID "$expected_appid" || testfail=1
+ else # unrecognized board
+ testfail=1
+ error "Unknown board: ${board}"
+ fi
+
+ exit $testfail
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/ensure_secure_kernelparams.sh b/nichrome/scripts/vboot/bin/ensure_secure_kernelparams.sh
new file mode 100755
index 000000000..daebe451a
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/ensure_secure_kernelparams.sh
@@ -0,0 +1,218 @@
+#!/bin/bash
+
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Abort on error.
+set -e
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+# Given a kernel boot param string which includes ...dm="dmstuff"...
+# this returns the dmstuff by itself.
+get_dmparams() {
+ echo "$1" | sed 's/^.*\ dm="\([^"]*\)".*/\1/'
+}
+
+# Given a kernel boot param string which includes ...dm="stuff"...
+# this returns the param string with the dm="..." section removed.
+# Useful in conjunction with get_dmparams to divide and process
+# the two sections of parameters in seperate passes
+kparams_remove_dm() {
+ echo "$1" | sed 's/dm="[^"]*"//'
+}
+
+# Given a dm param string which includes dynamic values, return the
+# same string with these values replaced by a magic string placeholder.
+# This same magic placeholder is used in the config file, for comparison
+# purposes.
+dmparams_mangle() {
+ local dmparams=$1
+ # First handle new key-value style verity parameters.
+ dmparams=$(echo "$dmparams" |
+ sed -e 's/root_hexdigest=[0-9a-fA-F]*/root_hexdigest=MAGIC_HASH/' |
+ sed -e 's/salt=[0-9a-fA-F]*/salt=MAGIC_SALT'/)
+ # If we didn't substitute the MAGIC_HASH yet, these are the old
+ # verity parameter format.
+ if [[ $dmparams != *MAGIC_HASH* ]]; then
+ dmparams=$(echo $dmparams | sed 's/sha1 [0-9a-fA-F]*/sha1 MAGIC_HASH/')
+ fi
+ # If we have bootcache enabled, replace its copy of the root_hexdigest
+ # with MAGIC_HASH. The parameter is positional.
+ if [[ $dmparams == *bootcache* ]]; then
+ dmparams=$(echo $dmparams |
+ sed -r 's:(bootcache (PARTUUID=)?%U(/PARTNROFF=|\+)1 [0-9]+) [0-9a-fA-F]+:\1 MAGIC_HASH:')
+ fi
+ echo $dmparams
+}
+
+# This escapes any non-alphanum character, since many such characters
+# are regex metacharacters.
+escape_regexmetas() {
+ echo "$1" | sed 's/\([^a-zA-Z0-9]\)/\\\1/g'
+}
+
+usage() {
+ echo "Usage $PROG image [config]"
+}
+
+main() {
+ # We want to catch all the discrepancies, not just the first one.
+ # So, any time we find one, we set testfail=1 and continue.
+ # When finished we will use testfail to determine our exit value.
+ local testfail=0
+ # A buffer to include useful information that we dump when things fail.
+ local output
+ # Copy of a string before it has been through sed
+ local pre_sed
+ # Where the disk image is mounted.
+ local loopdev
+
+ if [[ $# -ne 1 ]] && [[ $# -ne 2 ]]; then
+ usage
+ exit 1
+ fi
+
+ local image="$1"
+
+ # A byte that should not appear in the command line to use as a sed
+ # marker when doing regular expression replacements.
+ local M=$'\001'
+
+ # Default config location: same name/directory as this script,
+ # with a .config file extension, ie ensure_secure_kernelparams.config.
+ local configfile="$(dirname "$0")/${0/%.sh/.config}"
+ # Or, maybe a config was provided on the command line.
+ if [[ $# -eq 2 ]]; then
+ configfile="$2"
+ fi
+ # Either way, load test-expectations data from config.
+ . "$configfile" || return 1
+
+ # Set up the image on a loopback device so it's faster to access.
+ local loopdev
+ loopdev=$(loopback_partscan "${image}")
+
+ # TODO(jimhebert): Perform the kernel security tests on both the kernel
+ # partitions. Here, we just run it on kernel partition 4
+ # which is the install kernel on the recovery image.
+ # crosbug.com/24274
+ local loop_kern="${loopdev}p4"
+ local loop_rootfs="${loopdev}p3"
+ local rootfs=$(make_temp_dir)
+ sudo mount -o ro "${loop_rootfs}" "${rootfs}"
+
+ # Pick the right set of test-expectation data to use.
+ local boardvar=$(get_boardvar_from_lsb_release "${rootfs}")
+ eval "required_kparams=(\"\${required_kparams_${boardvar}[@]}\")"
+ eval "required_kparams_regex=(\"\${required_kparams_regex_${boardvar}[@]}\")"
+ eval "optional_kparams=(\"\${optional_kparams_${boardvar}[@]}\")"
+ eval "optional_kparams_regex=(\"\${optional_kparams_regex_${boardvar}[@]}\")"
+ eval "required_dmparams=(\"\${required_dmparams_${boardvar}[@]}\")"
+ eval "required_dmparams_regex=(\"\${required_dmparams_regex_${boardvar}[@]}\")"
+ output+="required_kparams=(\n"
+ output+="$(printf "\t'%s'\n" "${required_kparams[@]}")\n)\n"
+ output+="required_kparams_regex=(\n"
+ output+="$(printf "\t'%s'\n" "${required_kparams_regex[@]}")\n)\n"
+ output+="optional_kparams=(\n"
+ output+="$(printf "\t'%s'\n" "${optional_kparams[@]}")\n)\n"
+ output+="optional_kparams_regex=(\n"
+ output+="$(printf "\t'%s'\n" "${optional_kparams_regex[@]}")\n)\n"
+ output+="required_dmparams=(\n"
+ output+="$(printf "\t'%s'\n" "${required_dmparams[@]}")\n)\n"
+ output+="required_dmparams_regex=(\n"
+ output+="$(printf "\t'%s'\n" "${required_dmparams_regex[@]}")\n)\n"
+
+ # Divide the dm params from the rest and process seperately.
+ local kparams=$(sudo dump_kernel_config "${loop_kern}")
+ local dmparams=$(get_dmparams "$kparams")
+ local kparams_nodm=$(kparams_remove_dm "$kparams")
+
+ output+="\nkparams='${kparams}'\n"
+ output+="\ndmparams='${dmparams}'\n"
+ output+="\nkparams_nodm='${kparams_nodm}'\n"
+
+ mangled_dmparams=$(dmparams_mangle "${dmparams}")
+ output+="\nmangled_dmparams='${mangled_dmparams}'\n"
+ # Special-case handling of the dm= param:
+ testfail=1
+ for expected_dmparams in "${required_dmparams[@]}"; do
+ # Filter out all dynamic parameters.
+ if [ "$mangled_dmparams" = "$expected_dmparams" ]; then
+ testfail=0
+ break
+ fi
+ done
+
+ for expected_dmparams in "${required_dmparams_regex[@]}"; do
+ if [[ -z $(echo "${mangled_dmparams}" | \
+ sed "s${M}^${expected_dmparams}\$${M}${M}") ]]; then
+ testfail=0
+ break
+ fi
+ done
+
+ if [ $testfail -eq 1 ]; then
+ echo "Kernel dm= parameter does not match any expected values!"
+ echo "Actual: $dmparams"
+ echo "Expected: ${required_dmparams[*]}"
+ echo "Expected (regex): ${required_dmparams_regex[*]}"
+ fi
+
+ # Ensure all other required params are present.
+ for param in "${required_kparams[@]}"; do
+ if [[ "$kparams_nodm" != *$param* ]]; then
+ echo "Kernel parameters missing required value: $param"
+ testfail=1
+ else
+ # Remove matched params as we go. If all goes well, kparams_nodm
+ # will be nothing left but whitespace by the end.
+ param=$(escape_regexmetas "$param")
+ kparams_nodm=$(echo " ${kparams_nodm} " |
+ sed "s${M} ${param} ${M} ${M}")
+ fi
+ done
+
+ # Ensure all other required regex params are present.
+ for param in "${required_kparams_regex[@]}"; do
+ pre_sed=" ${kparams_nodm} "
+ kparams_nodm=$(echo "${pre_sed}" | sed "s${M} ${param} ${M} ${M}")
+ if [[ "${pre_sed}" == "${kparams_nodm}" ]]; then
+ echo "Kernel parameters missing required value: ${param}"
+ testfail=1
+ fi
+ done
+
+ # Check-off each of the allowed-but-optional params that were present.
+ for param in "${optional_kparams[@]}"; do
+ param=$(escape_regexmetas "$param")
+ kparams_nodm=$(echo " ${kparams_nodm} " |
+ sed "s${M} ${param} ${M} ${M}")
+ done
+
+ # Check-off each of the allowed-but-optional params that were present.
+ for param in "${optional_kparams_regex[@]}"; do
+ kparams_nodm=$(echo " ${kparams_nodm} " |
+ sed "s${M} ${param} ${M} ${M}")
+ done
+
+ # This section enforces the default-deny for any unexpected params
+ # not already processed by one of the above loops.
+ if [[ ! -z ${kparams_nodm// /} ]]; then
+ echo "Unexpected kernel parameters found:"
+ echo " $(echo "${kparams_nodm}" | sed -r 's: +: :g')"
+ testfail=1
+ fi
+
+ if [[ ${testfail} -eq 1 ]]; then
+ echo "Debug output:"
+ printf '%b\n' "${output}"
+ echo "(actual error will be at the top of output)"
+ fi
+
+ exit $testfail
+}
+
+main $@
diff --git a/nichrome/scripts/vboot/bin/ensure_update_verification.sh b/nichrome/scripts/vboot/bin/ensure_update_verification.sh
new file mode 100755
index 000000000..34fb2cb3c
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/ensure_update_verification.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Verify that update payload verification is enabled.
+
+# Abort on error.
+set -e
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+usage() {
+ echo "Usage: $PROG image"
+}
+
+main() {
+ if [ $# -ne 1 ]; then
+ usage
+ exit 1
+ fi
+
+ local image=$1
+ local rootfs=$(make_temp_dir)
+ local key_location="/usr/share/update_engine/update-payload-key.pub.pem"
+ mount_image_partition_ro "$image" 3 "$rootfs"
+ if [ ! -e "$rootfs/$key_location" ]; then
+ die "Update payload verification key not found at $key_location"
+ fi
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/firmware_boot.sh b/nichrome/scripts/vboot/bin/firmware_boot.sh
new file mode 100755
index 000000000..404a7ba13
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/firmware_boot.sh
@@ -0,0 +1,101 @@
+#!/bin/bash -eux
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Refer to the Google Chrome OS Main Processor Firmware Specification for what
+# the pieces are.
+# This script generates different firmware binaries with different
+# configurations.
+
+# Syntax: ./firmware_boot.sh .
+# Usage of the script.
+usage()
+{
+ cat <
+Installs the update verification public key to .
+EOF
+ exit 1
+ fi
+ local rootfs=$(make_temp_dir)
+ local key_location="/usr/share/update_engine/"
+ mount_image_partition "$image" 3 "$rootfs"
+ sudo mkdir -p "$rootfs/$key_location"
+ sudo cp "$pub_key" "$rootfs/$key_location/update-payload-key.pub.pem"
+ sudo chown root:root "$rootfs/$key_location/update-payload-key.pub.pem"
+ sudo chmod 644 "$rootfs/$key_location/update-payload-key.pub.pem"
+ echo "AU verification key was installed. Do not forget to resign the image!"
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/insert_container_publickey.sh b/nichrome/scripts/vboot/bin/insert_container_publickey.sh
new file mode 100755
index 000000000..0b9348e80
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/insert_container_publickey.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Copyright 2017 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+load_shflags || exit 1
+
+FLAGS_HELP="Usage: ${PROG}
+
+Installs the container verification public key to
+.
+"
+
+# Parse command line.
+FLAGS "$@" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+# Abort on error.
+set -e
+
+main() {
+ if [[ $# -ne 2 ]]; then
+ flags_help
+ exit 1
+ fi
+
+ local image="$1"
+ local pub_key="$2"
+ local rootfs
+ local key_location="/usr/share/misc/"
+
+ if [[ -d "${image}" ]]; then
+ rootfs="${image}"
+ else
+ rootfs=$(make_temp_dir)
+ mount_image_partition "${image}" 3 "${rootfs}"
+ fi
+
+ # Imageloader likes DER as a runtime format as it's easier to read.
+ local tmpfile=$(make_temp_file)
+ openssl pkey -pubin -in "${pub_key}" -out "${tmpfile}" -pubout -outform DER
+
+ sudo install \
+ -D -o root -g root -m 644 \
+ "${tmpfile}" "${rootfs}/${key_location}/oci-container-key-pub.der"
+ info "Container verification key was installed." \
+ "Do not forget to resign the image!"
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/make_dev_firmware.sh b/nichrome/scripts/vboot/bin/make_dev_firmware.sh
new file mode 100755
index 000000000..cbf02112d
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/make_dev_firmware.sh
@@ -0,0 +1,358 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This script can change key (usually developer keys) in a firmware binary
+# image or system live firmware (EEPROM), and assign proper HWID, FLAGS as well.
+
+SCRIPT_BASE="$(dirname "$0")"
+. "$SCRIPT_BASE/common_minimal.sh"
+load_shflags || exit 1
+
+# Constants used by DEFINE_*
+VBOOT_BASE='/usr/share/vboot'
+DEFAULT_KEYS_FOLDER="$VBOOT_BASE/devkeys"
+DEFAULT_BACKUP_FOLDER='/mnt/stateful_partition/backups'
+
+# DEFINE_string name default_value description flag
+DEFINE_string from "" "Path of input file (empty for system live firmware)" "f"
+DEFINE_string to "" "Path of output file (empty for system live firmware)" "t"
+DEFINE_string keys "$DEFAULT_KEYS_FOLDER" "Path to folder of dev keys" "k"
+DEFINE_string preamble_flags "" "Override preamble flags value. Known values:
+ 0: None. (Using RW to boot in normal. aka, two-stop)
+ 1: VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL (one-stop)" "p"
+DEFINE_boolean mod_hwid \
+ $FLAGS_TRUE "Modify HWID to indicate this is a modified firmware" ""
+DEFINE_boolean mod_gbb_flags \
+ $FLAGS_TRUE "Modify GBB flags to enable developer friendly features" ""
+DEFINE_boolean force_backup \
+ $FLAGS_TRUE "Create backup even if source is not live" ""
+DEFINE_string backup_dir \
+ "$DEFAULT_BACKUP_FOLDER" "Path of directory to store firmware backups" ""
+
+# Parse command line
+FLAGS "$@" || exit 1
+eval set -- "$FLAGS_ARGV"
+
+# Globals
+# ----------------------------------------------------------------------------
+set -e
+
+FLASHROM="flashrom -p host"
+
+# the image we are (temporary) working with
+IMAGE="$(make_temp_file)"
+IMAGE="$(readlink -f "$IMAGE")"
+
+# a log file to keep the output results of executed command
+EXEC_LOG="$(make_temp_file)"
+
+# Functions
+# ----------------------------------------------------------------------------
+
+# Disables write protection status registers
+disable_write_protection() {
+ # No need to change WP status in file mode
+ if [ -n "$FLAGS_to" ]; then
+ return $FLAGS_TRUE
+ fi
+
+ # --wp-disable command may return success even if WP is still enabled,
+ # so we should use --wp-status to verify the results.
+ echo "Disabling system software write protection status..."
+ (${FLASHROM} --wp-disable && ${FLASHROM} --wp-status) 2>&1 |
+ tee "$EXEC_LOG" |
+ grep -q '^WP: .* is disabled\.$'
+}
+
+# Reads $IMAGE from $FLAGS_from
+read_image() {
+ if [ -z "$FLAGS_from" ]; then
+ echo "Reading system live firmware..."
+ if is_debug_mode; then
+ ${FLASHROM} -V -r "$IMAGE"
+ else
+ ${FLASHROM} -r "$IMAGE" >"$EXEC_LOG" 2>&1
+ fi
+ else
+ debug_msg "reading from file: $FLAGS_from"
+ cp -f "$FLAGS_from" "$IMAGE"
+ fi
+}
+
+# Writes $IMAGE to $FLAGS_to
+write_image() {
+ if [ -z "$FLAGS_to" ]; then
+ echo "Writing system live firmware..."
+ # TODO(hungte) we can enable partial write to make this faster
+ if is_debug_mode; then
+ ${FLASHROM} -w "$IMAGE" -V
+ else
+ ${FLASHROM} -w "$IMAGE" >"$EXEC_LOG" 2>&1
+ fi
+ else
+ debug_msg "writing to file: $FLAGS_to"
+ cp -f "$IMAGE" "$FLAGS_to"
+ chmod a+r "$FLAGS_to"
+ fi
+}
+
+# Converts HWID from $1 to proper format with "DEV" extension
+echo_dev_hwid() {
+ local hwid="$1"
+ local hwid_no_dev="${hwid% DEV}"
+
+ # NOTE: Some DEV firmware image files may put GUID in HWID.
+ # These are not officially supported and they will see "{GUID} DEV".
+
+ if [ "$hwid" != "$hwid_no_dev" ]; then
+ hwid="$hwid_no_dev"
+ fi
+ local hwid_dev="$hwid DEV"
+ debug_msg "echo_dev_hwid: [$1] -> [$hwid_dev]"
+ echo "$hwid_dev"
+}
+
+# Main
+# ----------------------------------------------------------------------------
+main() {
+ # Check parameters
+ local root_pubkey="$FLAGS_keys/root_key.vbpubk"
+ local recovery_pubkey="$FLAGS_keys/recovery_key.vbpubk"
+ local firmware_keyblock="$FLAGS_keys/firmware.keyblock"
+ local firmware_prvkey="$FLAGS_keys/firmware_data_key.vbprivk"
+ local dev_firmware_keyblock="$FLAGS_keys/dev_firmware.keyblock"
+ local dev_firmware_prvkey="$FLAGS_keys/dev_firmware_data_key.vbprivk"
+ local kernel_sub_pubkey="$FLAGS_keys/kernel_subkey.vbpubk"
+ local is_from_live=0
+ local backup_image=
+
+ debug_msg "Prerequisite check"
+ ensure_files_exist \
+ "$root_pubkey" \
+ "$recovery_pubkey" \
+ "$firmware_keyblock" \
+ "$firmware_prvkey" \
+ "$kernel_sub_pubkey" ||
+ exit 1
+
+ if [ -z "$FLAGS_from" ]; then
+ is_from_live=1
+ else
+ ensure_files_exist "$FLAGS_from" || exit 1
+ fi
+
+ debug_msg "Checking software write protection status"
+ disable_write_protection ||
+ if is_debug_mode; then
+ die "Failed to disable WP. Diagnose Message: $(cat "${EXEC_LOG}")"
+ else
+ die "Write protection is still enabled. " \
+ "Please verify that hardware write protection is disabled."
+ fi
+
+ debug_msg "Pulling image to $IMAGE"
+ (read_image && [ -s "$IMAGE" ]) ||
+ die "Failed to read image. Error message: $(cat "${EXEC_LOG}")"
+
+ debug_msg "Prepare to backup the file"
+ if [ -n "$is_from_live" -o $FLAGS_force_backup = $FLAGS_TRUE ]; then
+ backup_image="$(make_temp_file)"
+ debug_msg "Creating backup file to $backup_image..."
+ cp -f "$IMAGE" "$backup_image"
+ fi
+
+ debug_msg "Detecting developer firmware keyblock"
+ local expanded_firmware_dir="$(make_temp_dir)"
+ local use_devfw_keyblock="$FLAGS_FALSE"
+ (cd "$expanded_firmware_dir"; dump_fmap -x "$IMAGE" >/dev/null 2>&1) ||
+ die "Failed to extract firmware image."
+ if [ -f "$expanded_firmware_dir/VBLOCK_A" ]; then
+ local has_dev=$FLAGS_TRUE has_norm=$FLAGS_TRUE
+ # In output of vbutil_keyblock, "!DEV" means "bootable on normal mode" and
+ # "DEV" means "bootable on developer mode". Here we try to match the pattern
+ # in output of vbutil_block, and disable the flags (has_dev, has_norm) if
+ # the pattern was not found.
+ vbutil_keyblock --unpack "$expanded_firmware_dir/VBLOCK_A" |
+ grep -qw '!DEV' || has_norm=$FLAGS_FALSE
+ vbutil_keyblock --unpack "$expanded_firmware_dir/VBLOCK_A" |
+ grep -qw '[^!]DEV' || has_dev=$FLAGS_FALSE
+ if [ "$has_norm" = "$FLAGS_FALSE" -a "$has_dev" = "$FLAGS_TRUE" ]; then
+ use_devfw_keyblock=$FLAGS_TRUE
+ fi
+ fi
+
+ if [ "$use_devfw_keyblock" = "$FLAGS_TRUE" ]; then
+ echo "Using keyblocks (developer, normal)..."
+ else
+ echo "Using keyblocks (normal, normal)..."
+ dev_firmware_prvkey="$firmware_prvkey"
+ dev_firmware_keyblock="$firmware_keyblock"
+ fi
+
+ debug_msg "Extract firmware version and data key version"
+ futility gbb -g --rootkey="$expanded_firmware_dir/rootkey" "$IMAGE" \
+ >/dev/null 2>&1
+
+ local data_key_version firmware_version
+ # When we are going to flash directly from or to system, the versions stored
+ # in TPM can be found by crossystem; otherwise we'll need to guess from source
+ # firmware (FLAGS_from).
+ if [ -z "$FLAGS_to" -o -z "$FLAGS_from" ]; then
+ debug_msg "Reading TPM version from crossystem tpm_fwver."
+ data_key_version="$(( $(crossystem tpm_fwver) >> 16 ))"
+ firmware_version="$(( $(crossystem tpm_fwver) & 0xFFFF ))"
+ else
+ # TODO(hungte) On Vboot2, A/B slot may contain different firmware so we may
+ # need to check both and decide from largest number.
+ debug_msg "Guessing TPM version from original firmware."
+ local fw_info="$(vbutil_firmware \
+ --verify "$expanded_firmware_dir/VBLOCK_A" \
+ --signpubkey "$expanded_firmware_dir/rootkey" \
+ --fv "$expanded_firmware_dir/FW_MAIN_A")" 2>/dev/null ||
+ die "Failed to verify firmware slot A."
+ data_key_version="$(
+ echo "$fw_info" | sed -n '/^ *Data key version:/s/.*:[ \t]*//p')"
+ firmware_version="$(
+ echo "$fw_info" | sed -n '/^ *Firmware version:/s/.*:[ \t]*//p')"
+ fi
+
+ local new_data_key_version="$(
+ vbutil_keyblock --unpack "$firmware_keyblock" |
+ sed -n '/^ *Data key version:/s/.*:[ \t]*//p')"
+
+ # TODO(hungte) Change key block by data_key_version.
+ if [ "$data_key_version" -gt "$new_data_key_version" ]; then
+ echo "$(tput bold)$(tput setaf 1)
+ Warning: firmware data key version <$new_data_key_version> in your new keys
+ [$FLAGS_keys] is smaller than original firmware <$data_key_version> and
+ will boot into only recovery mode due to TPM anti-rollback detection.
+
+ After reboot with dev recovery key, you will need to reset TPM by booting a
+ test or dev image in recovery mode (NOT Ctrl-U), switch to VT2 and run
+ command ; or use a factory install shim image
+ (build_image factory_install).
+ $(tput sgr 0)" >&2
+ fi
+
+ echo "Signing with Data Key Version: $data_key_version, " \
+ "Firmware Version: $firmware_version"
+
+ echo "Preparing new firmware image..."
+
+ debug_msg "Resign the firmware code (A/B) with new keys"
+ # Note resign_firmwarefd.sh needs the original rootkey to determine firmware
+ # body size, so we must resign image before changing GBB rootkey.
+
+ local unsigned_image="$(make_temp_file)"
+ local optional_opts=""
+ if [ -n "$FLAGS_preamble_flags" ]; then
+ debug_msg "Setting FLAGS=$FLAGS_preamble_flags"
+ optional_opts="$FLAGS_preamble_flags"
+ fi
+ cp -f "$IMAGE" "$unsigned_image"
+ "$SCRIPT_BASE/resign_firmwarefd.sh" \
+ "$unsigned_image" \
+ "$IMAGE" \
+ "$firmware_prvkey" \
+ "$firmware_keyblock" \
+ "$dev_firmware_prvkey" \
+ "$dev_firmware_keyblock" \
+ "$kernel_sub_pubkey" \
+ "$firmware_version" \
+ $optional_opts >"$EXEC_LOG" 2>&1 ||
+ die "Failed to re-sign firmware. (message: $(cat "${EXEC_LOG}"))"
+ if is_debug_mode; then
+ cat "$EXEC_LOG"
+ fi
+
+ debug_msg "Extract current HWID"
+ local old_hwid
+ old_hwid="$(futility gbb --get --hwid "$IMAGE" 2>"$EXEC_LOG" |
+ sed -rne 's/^hardware_id: (.*)$/\1/p')"
+
+ debug_msg "Decide new HWID"
+ [ -z "$old_hwid" ] &&
+ die "Cannot find current HWID. (message: $(cat "${EXEC_LOG}"))"
+ local new_hwid="$old_hwid"
+ if [ "$FLAGS_mod_hwid" = "$FLAGS_TRUE" ]; then
+ new_hwid="$(echo_dev_hwid "$old_hwid")"
+ fi
+
+ local old_gbb_flags
+ old_gbb_flags="$(futility gbb --get --flags "$IMAGE" 2>"$EXEC_LOG" |
+ sed -rne 's/^flags: (.*)$/\1/p')"
+ debug_msg "Decide new GBB flags from: $old_gbb_flags"
+ [ -z "$old_gbb_flags" ] &&
+ die "Cannot find GBB flags. (message: $(cat "${EXEC_LOG}"))"
+ # 0x30: GBB_FLAG_FORCE_DEV_BOOT_USB | GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK
+ local new_gbb_flags="$((old_gbb_flags | 0x30))"
+
+ debug_msg "Replace GBB parts (futility gbb allows changing on-the-fly)"
+ futility gbb --set \
+ --hwid="$new_hwid" \
+ --rootkey="$root_pubkey" \
+ --recoverykey="$recovery_pubkey" \
+ "$IMAGE" >"$EXEC_LOG" 2>&1 ||
+ die "Failed to change GBB Data. (message: $(cat "${EXEC_LOG}"))"
+
+ # Old firmware does not support GBB flags, so let's make it an exception.
+ if [ "$FLAGS_mod_gbb_flags" = "$FLAGS_TRUE" ]; then
+ debug_msg "Changing GBB flags from $old_gbb_flags to $new_gbb_flags"
+ futility gbb --set \
+ --flags="$new_gbb_flags" \
+ "$IMAGE" >"$EXEC_LOG" 2>&1 ||
+ echo "Warning: GBB flags ($old_gbb_flags -> $new_gbb_flags) can't be set."
+ fi
+
+ # TODO(hungte) compare if the image really needs to be changed.
+
+ debug_msg "Check if we need to make backup file(s)"
+ if [ -n "$backup_image" ]; then
+ local backup_hwid_name="$(echo "$old_hwid" | sed 's/ /_/g')"
+ local backup_date_time="$(date +'%Y%m%d_%H%M%S')"
+ local backup_file_name="firmware_${backup_hwid_name}_${backup_date_time}.fd"
+ local backup_file_path="$FLAGS_backup_dir/$backup_file_name"
+ if mkdir -p "$FLAGS_backup_dir" &&
+ cp -f "$backup_image" "$backup_file_path"; then
+ true
+ elif cp -f "$backup_image" "/tmp/$backup_file_name"; then
+ backup_file_path="/tmp/$backup_file_name"
+ else
+ backup_file_path=''
+ fi
+ if [ -n "$backup_file_path" -a -s "$backup_file_path" ]; then
+ # TODO(hungte) maybe we can wrap the flashrom by 'make_dev_firmware.sh -r'
+ # so that the only command to remember would be make_dev_firmware.sh.
+ echo "
+ Backup of current firmware image is stored in:
+ $backup_file_path
+ Please copy the backup file to a safe place ASAP.
+
+ To stop using devkeys and restore original firmware, execute command:
+ ${FLASHROM} -w [PATH_TO_BACKUP_IMAGE]
+ Ex: ${FLASHROM} -w $backup_file_path
+ "
+ else
+ echo "WARNING: Cannot create file in $FLAGS_backup_dir... Ignore backups."
+ fi
+ fi
+
+ # TODO(hungte) use vbutil_firmware to check if the new firmware is valid.
+ # Or, do verification in resign_firmwarefd.sh and trust it.
+
+ debug_msg "Write the image"
+ write_image ||
+ die "Failed to write image. Error message: $(cat "${EXEC_LOG}")"
+
+ debug_msg "Complete."
+ if [ -z "$FLAGS_to" ]; then
+ echo "Successfully changed firmware to Developer Keys. New HWID: $new_hwid"
+ else
+ echo "Firmware '$FLAGS_to' now uses Developer Keys. New HWID: $new_hwid"
+ fi
+}
+
+main
diff --git a/nichrome/scripts/vboot/bin/make_dev_ssd.sh b/nichrome/scripts/vboot/bin/make_dev_ssd.sh
new file mode 100755
index 000000000..dad0e5b0d
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/make_dev_ssd.sh
@@ -0,0 +1,504 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This script can change key (usually developer keys) and kernel config
+# of kernels on an disk image (usually for SSD but also works for USB).
+
+SCRIPT_BASE="$(dirname "$0")"
+. "$SCRIPT_BASE/common_minimal.sh"
+load_shflags || exit 1
+
+# Constants used by DEFINE_*
+VBOOT_BASE='/usr/share/vboot'
+DEFAULT_KEYS_FOLDER="$VBOOT_BASE/devkeys"
+DEFAULT_BACKUP_FOLDER='/mnt/stateful_partition/backups'
+DEFAULT_PARTITIONS='2 4'
+
+# TODO(hungte) The default image selection is no longer a SSD, so the script
+# works more like "make_dev_image". We may change the file name in future.
+ROOTDEV="$(rootdev -s 2>/dev/null)"
+ROOTDEV_PARTITION="$(echo $ROOTDEV | sed -n 's/.*\([0-9][0-9]*\)$/\1/p')"
+ROOTDEV_DISK="$(rootdev -s -d 2>/dev/null)"
+ROOTDEV_KERNEL="$((ROOTDEV_PARTITION - 1))"
+
+# DEFINE_string name default_value description flag
+DEFINE_string image "$ROOTDEV_DISK" "Path to device or image file" "i"
+DEFINE_string keys "$DEFAULT_KEYS_FOLDER" "Path to folder of dev keys" "k"
+DEFINE_boolean remove_rootfs_verification \
+ $FLAGS_FALSE "Modify kernel boot config to disable rootfs verification" ""
+DEFINE_string backup_dir \
+ "$DEFAULT_BACKUP_FOLDER" "Path of directory to store kernel backups" ""
+DEFINE_string save_config "" \
+ "Base filename to store kernel configs to, instead of resigning." ""
+DEFINE_string set_config "" \
+ "Base filename to load kernel configs from" ""
+DEFINE_boolean edit_config "${FLAGS_FALSE}" \
+ "Edit kernel config in-place." ""
+DEFINE_string partitions "" \
+ "List of partitions to examine (default: $DEFAULT_PARTITIONS)" ""
+DEFINE_boolean recovery_key "$FLAGS_FALSE" \
+ "Use recovery key to sign image (to boot from USB" ""
+DEFINE_boolean force "$FLAGS_FALSE" "Skip sanity checks and make the change" "f"
+
+# Parse command line
+FLAGS "$@" || exit 1
+ORIGINAL_PARAMS="$@"
+eval set -- "$FLAGS_ARGV"
+ORIGINAL_PARTITIONS="$FLAGS_partitions"
+: ${FLAGS_partitions:=$DEFAULT_PARTITIONS}
+
+# Globals
+# ----------------------------------------------------------------------------
+set -e
+
+# a log file to keep the output results of executed command
+EXEC_LOG="$(make_temp_file)"
+
+# Functions
+# ----------------------------------------------------------------------------
+
+# Removes rootfs verification from kernel boot parameter
+# And strip out bootcache args if it exists
+remove_rootfs_verification() {
+ local new_root="PARTUUID=%U/PARTNROFF=1"
+ # the first line in sed is to strip out bootcache details
+ echo "$*" | sed '
+ s| dm=\"2 [^"]*bootcache[^"]* vroot | dm=\"1 vroot |
+ s| root=/dev/dm-[0-9] | root='"$new_root"' |
+ s| dm_verity.dev_wait=1 | dm_verity.dev_wait=0 |
+ s| payload=PARTUUID=%U/PARTNROFF=1 | payload=ROOT_DEV |
+ s| hashtree=PARTUUID=%U/PARTNROFF=1 | hashtree=HASH_DEV |
+ s| ro | rw |'
+}
+
+remove_legacy_boot_rootfs_verification() {
+ # See src/scripts/create_legacy_bootloader_templates
+ local image="$1"
+ local mount_point="$(make_temp_dir)"
+ local config_file
+ debug_msg "Removing rootfs verification for legacy boot configuration."
+ mount_image_partition "$image" 12 "$mount_point" || return $FLAGS_FALSE
+ config_file="$mount_point/efi/boot/grub.cfg"
+ [ ! -f "$config_file" ] ||
+ sudo sed -i 's/^ *set default=2 *$/set default=0/g' "$config_file"
+ config_file="$mount_point/syslinux/default.cfg"
+ [ ! -f "$config_file" ] ||
+ sudo sed -i 's/-vusb/-usb/g; s/-vhd/-hd/g' "$config_file"
+ sudo umount "$mount_point"
+}
+
+# Wrapped version of dd
+mydd() {
+ # oflag=sync is safer, but since we need bs=512, syncing every block would be
+ # very slow.
+ dd "$@" >"$EXEC_LOG" 2>&1 ||
+ die "Failed in [dd $*], Message: $(cat "${EXEC_LOG}")"
+}
+
+# Prints a more friendly name from kernel index number
+cros_kernel_name() {
+ case $1 in
+ 2)
+ echo "Kernel A"
+ ;;
+ 4)
+ echo "Kernel B"
+ ;;
+ 6)
+ echo "Kernel C"
+ ;;
+ *)
+ echo "Partition $1"
+ esac
+}
+
+find_valid_kernel_partitions() {
+ local part_id
+ local valid_partitions=""
+ for part_id in $*; do
+ local name="$(cros_kernel_name $part_id)"
+ local kernel_part="$(make_partition_dev "$FLAGS_image" "$part_id")"
+ if [ -z "$(dump_kernel_config "$kernel_part" 2>"$EXEC_LOG")" ]; then
+ info "${name}: no kernel boot information, ignored." >&2
+ else
+ [ -z "$valid_partitions" ] &&
+ valid_partitions="$part_id" ||
+ valid_partitions="$valid_partitions $part_id"
+ continue
+ fi
+ done
+ debug_msg "find_valid_kernel_partitions: [$*] -> [$valid_partitions]"
+ echo "$valid_partitions"
+}
+
+# Resigns a kernel on SSD or image.
+resign_ssd_kernel() {
+ # bs=512 is the fixed block size for dd and cgpt
+ local bs=512
+ local ssd_device="$1"
+
+ # reasonable size for current kernel partition
+ local min_kernel_size=16000
+ local max_kernel_size=65536
+ local resigned_kernels=0
+
+ for kernel_index in $FLAGS_partitions; do
+ local old_blob="$(make_temp_file)"
+ local new_blob="$(make_temp_file)"
+ local name="$(cros_kernel_name $kernel_index)"
+ local rootfs_index="$(($kernel_index + 1))"
+
+ debug_msg "Probing $name information"
+ local offset size
+ offset="$(partoffset "$ssd_device" "$kernel_index")" ||
+ die "Failed to get partition ${kernel_index} offset from ${ssd_device}"
+ size="$(partsize "$ssd_device" "$kernel_index")" ||
+ die "Failed to get partition ${kernel_index} size from ${ssd_device}"
+ if [ ! $size -gt $min_kernel_size ]; then
+ info "${name} seems too small (${size}), ignored."
+ continue
+ fi
+ if [ ! $size -le $max_kernel_size ]; then
+ info "${name} seems too large (${size}), ignored."
+ continue
+ fi
+
+ debug_msg "Reading $name from partition $kernel_index"
+ mydd if="$ssd_device" of="$old_blob" bs=$bs skip=$offset count=$size
+
+ debug_msg "Checking if $name is valid"
+ local kernel_config
+ if ! kernel_config="$(dump_kernel_config "$old_blob" 2>"$EXEC_LOG")"; then
+ debug_msg "dump_kernel_config error message: $(cat "$EXEC_LOG")"
+ info "${name}: no kernel boot information, ignored."
+ continue
+ fi
+
+ if [ -n "${FLAGS_save_config}" ]; then
+ # Save current kernel config
+ local old_config_file
+ old_config_file="${FLAGS_save_config}.$kernel_index"
+ info "Saving ${name} config to ${old_config_file}"
+ echo "$kernel_config" > "$old_config_file"
+ # Just save; don't resign
+ continue
+ fi
+
+ if [ -n "${FLAGS_set_config}" ]; then
+ # Set new kernel config from file
+ local new_config_file
+ new_config_file="${FLAGS_set_config}.$kernel_index"
+ kernel_config="$(cat "$new_config_file")" ||
+ die "Failed to read new kernel config from ${new_config_file}"
+ debug_msg "New kernel config: $kernel_config)"
+ info "${name}: Replaced config from ${new_config_file}"
+ fi
+
+ if [ "${FLAGS_edit_config}" = ${FLAGS_TRUE} ]; then
+ debug_msg "Editing kernel config file."
+ local new_config_file="$(make_temp_file)"
+ echo "${kernel_config}" >"${new_config_file}"
+ local old_md5sum="$(md5sum "${new_config_file}")"
+ local editor="${VISUAL:-${EDITOR:-vi}}"
+ info "${name}: Editing kernel config:"
+ # On ChromiumOS, some builds may come with broken EDITOR that refers to
+ # nano so we want to check again if the editor really exists.
+ if type "${editor}" >/dev/null 2>&1; then
+ "${editor}" "${new_config_file}"
+ else
+ # This script runs under dash but we want readline in bash to support
+ # editing in in console.
+ bash -c "read -e -i '${kernel_config}' &&
+ echo \"\${REPLY}\" >${new_config_file}" ||
+ die "Failed to run editor. Please specify editor name by VISUAL."
+ fi
+ kernel_config="$(cat "${new_config_file}")"
+ if [ "$(md5sum "${new_config_file}")" = "${old_md5sum}" ]; then
+ info "${name}: Config not changed."
+ else
+ debug_msg "New kernel config: ${kernel_config})"
+ info "${name}: Config updated"
+ fi
+ fi
+
+ if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_FALSE ]; then
+ debug_msg "Bypassing rootfs verification check"
+ else
+ debug_msg "Changing boot parameter to remove rootfs verification"
+ kernel_config="$(remove_rootfs_verification "$kernel_config")"
+ debug_msg "New kernel config: $kernel_config"
+ info "${name}: Disabled rootfs verification."
+ remove_legacy_boot_rootfs_verification "$ssd_device"
+ fi
+
+ local new_kernel_config_file="$(make_temp_file)"
+ echo -n "$kernel_config" >"$new_kernel_config_file"
+
+ debug_msg "Re-signing $name from $old_blob to $new_blob"
+ debug_msg "Using key: $KERNEL_DATAKEY"
+ vbutil_kernel \
+ --repack "$new_blob" \
+ --keyblock "$KERNEL_KEYBLOCK" \
+ --config "$new_kernel_config_file" \
+ --signprivate "$KERNEL_DATAKEY" \
+ --oldblob "$old_blob" >"$EXEC_LOG" 2>&1 ||
+ die "Failed to resign ${name}. Message: $(cat "${EXEC_LOG}")"
+
+ debug_msg "Creating new kernel image (vboot+code+config)"
+ local new_kern="$(make_temp_file)"
+ cp "$old_blob" "$new_kern"
+ mydd if="$new_blob" of="$new_kern" conv=notrunc
+
+ if is_debug_mode; then
+ debug_msg "for debug purposes, check *.dbgbin"
+ cp "$old_blob" old_blob.dbgbin
+ cp "$new_blob" new_blob.dbgbin
+ cp "$new_kern" new_kern.dbgbin
+ fi
+
+ debug_msg "Verifying new kernel and keys"
+ vbutil_kernel \
+ --verify "$new_kern" \
+ --signpubkey "$KERNEL_PUBKEY" --verbose >"$EXEC_LOG" 2>&1 ||
+ die "Failed to verify new ${name}. Message: $(cat "${EXEC_LOG}")"
+
+ debug_msg "Backup old kernel blob"
+ local backup_date_time="$(date +'%Y%m%d_%H%M%S')"
+ local backup_name="$(echo "$name" | sed 's/ /_/g; s/^K/k/')"
+ local backup_file_name="${backup_name}_${backup_date_time}.bin"
+ local backup_file_path="$FLAGS_backup_dir/$backup_file_name"
+ if mkdir -p "$FLAGS_backup_dir" &&
+ cp -f "$old_blob" "$backup_file_path"; then
+ info "Backup of ${name} is stored in: ${backup_file_path}"
+ else
+ warning "Cannot create file in ${FLAGS_backup_dir} ... Ignore backups."
+ fi
+
+ debug_msg "Writing $name to partition $kernel_index"
+ mydd \
+ if="$new_kern" \
+ of="$ssd_device" \
+ seek=$offset \
+ bs=$bs \
+ count=$size \
+ conv=notrunc
+ resigned_kernels=$(($resigned_kernels + 1))
+
+ debug_msg "Make the root file system writable if needed."
+ # TODO(hungte) for safety concern, a more robust way would be to:
+ # (1) change kernel config to ro
+ # (2) check if we can enable rw mount
+ # (3) change kernel config to rw
+ if [ ${FLAGS_remove_rootfs_verification} = $FLAGS_TRUE ]; then
+ local root_offset_sector=$(partoffset "$ssd_device" $rootfs_index)
+ local root_offset_bytes=$((root_offset_sector * 512))
+ if ! is_ext2 "$ssd_device" "$root_offset_bytes"; then
+ debug_msg "Non-ext2 partition: $ssd_device$rootfs_index, skip."
+ elif ! rw_mount_disabled "$ssd_device" "$root_offset_bytes"; then
+ debug_msg "Root file system is writable. No need to modify."
+ else
+ # disable the RO ext2 hack
+ debug_msg "Disabling rootfs ext2 RO bit hack"
+ enable_rw_mount "$ssd_device" "$root_offset_bytes" >"$EXEC_LOG" 2>&1 ||
+ die "Failed turning off rootfs RO bit. OS may be corrupted. " \
+ "Message: $(cat "${EXEC_LOG}")"
+ fi
+ fi
+
+ # Sometimes doing "dump_kernel_config" or other I/O now (or after return to
+ # shell) will get the data before modification. Not a problem now, but for
+ # safety, let's try to sync more.
+ sync; sync; sync
+
+ info "${name}: Re-signed with developer keys successfully."
+ done
+
+ # If we saved the kernel config, exit now so we don't print an error
+ if [ -n "${FLAGS_save_config}" ]; then
+ info "(Kernels have not been resigned.)"
+ exit 0
+ fi
+
+ return $resigned_kernels
+}
+
+sanity_check_crossystem_flags() {
+ debug_msg "crossystem sanity check"
+ if [ -n "${FLAGS_save_config}" ]; then
+ debug_msg "not resigning kernel."
+ return
+ fi
+
+ if [ "$(crossystem dev_boot_signed_only)" = "0" ]; then
+ debug_msg "dev_boot_signed_only not set - safe."
+ return
+ fi
+
+ echo "
+ ERROR: YOUR FIRMWARE WILL ONLY BOOT SIGNED IMAGES.
+
+ Modifying the kernel or root filesystem will result in an unusable system. If
+ you really want to make this change, allow the firmware to boot self-signed
+ images by running:
+
+ sudo crossystem dev_boot_signed_only=0
+
+ before re-executing this command.
+ "
+ return $FLAGS_FALSE
+}
+
+sanity_check_live_partitions() {
+ debug_msg "Partition sanity check"
+ if [ "$FLAGS_partitions" = "$ROOTDEV_KERNEL" ]; then
+ debug_msg "only for current active partition - safe."
+ return
+ fi
+ if [ "$ORIGINAL_PARTITIONS" != "" ]; then
+ debug_msg "user has assigned partitions - provide more info."
+ info "Making change to ${FLAGS_partitions} on ${FLAGS_image}."
+ return
+ fi
+ echo "
+ ERROR: YOU ARE TRYING TO MODIFY THE LIVE SYSTEM IMAGE $FLAGS_image.
+
+ The system may become unusable after that change, especially when you have
+ some auto updates in progress. To make it safer, we suggest you to only
+ change the partition you have booted with. To do that, re-execute this command
+ as:
+
+ sudo ./make_dev_ssd.sh $ORIGINAL_PARAMS --partitions $ROOTDEV_KERNEL
+
+ If you are sure to modify other partition, please invoke the command again and
+ explicitly assign only one target partition for each time (--partitions N )
+ "
+ return $FLAGS_FALSE
+}
+
+sanity_check_live_firmware() {
+ debug_msg "Firmware compatibility sanity check"
+ if [ "$(crossystem mainfw_type)" = "developer" ]; then
+ debug_msg "developer type firmware in active."
+ return
+ fi
+ debug_msg "Loading firmware to check root key..."
+ local bios_image="$(make_temp_file)"
+ local rootkey_file="$(make_temp_file)"
+ info "checking system firmware..."
+ sudo flashrom -p host -i GBB -r "$bios_image" >/dev/null 2>&1
+ futility gbb -g --rootkey="$rootkey_file" "$bios_image" >/dev/null 2>&1
+ if [ ! -s "$rootkey_file" ]; then
+ debug_msg "failed to read root key from system firmware..."
+ else
+ # The magic 130 is counted by "od dev-rootkey" for the lines until the body
+ # of key is reached. Trailing bytes (0x00 or 0xFF - both may appear, and
+ # that's why we need to skip them) are started at line 131.
+ # TODO(hungte) compare with rootkey in $VBOOT_BASE directly.
+ local rootkey_hash="$(od "$rootkey_file" |
+ head -130 | md5sum |
+ sed 's/ .*$//' )"
+ if [ "$rootkey_hash" = "a13642246ef93daaf75bd791446fec9b" ]; then
+ debug_msg "detected DEV root key in firmware."
+ return
+ else
+ debug_msg "non-devkey hash: $rootkey_hash"
+ fi
+ fi
+
+ echo "
+ ERROR: YOU ARE NOT USING DEVELOPER FIRMWARE, AND RUNNING THIS COMMAND MAY
+ THROW YOUR CHROMEOS DEVICE INTO UN-BOOTABLE STATE.
+
+ You need to either install developer firmware, or change system root key.
+
+ - To install developer firmware: type command
+ sudo chromeos-firmwareupdate --mode=todev
+
+ - To change system rootkey: disable firmware write protection (a hardware
+ switch) and then type command:
+ sudo ./make_dev_firmware.sh
+
+ If you are sure that you want to make such image without developer
+ firmware or you've already changed system root keys, please run this
+ command again with --force paramemeter:
+
+ sudo ./make_dev_ssd.sh --force $ORIGINAL_PARAMS
+ "
+ return $FLAGS_FALSE
+}
+
+# Main
+# ----------------------------------------------------------------------------
+main() {
+ local num_signed=0
+ local num_given=$(echo "$FLAGS_partitions" | wc -w)
+ # Check parameters
+ if [ "$FLAGS_recovery_key" = "$FLAGS_TRUE" ]; then
+ KERNEL_KEYBLOCK="$FLAGS_keys/recovery_kernel.keyblock"
+ KERNEL_DATAKEY="$FLAGS_keys/recovery_kernel_data_key.vbprivk"
+ KERNEL_PUBKEY="$FLAGS_keys/recovery_key.vbpubk"
+ else
+ KERNEL_KEYBLOCK="$FLAGS_keys/kernel.keyblock"
+ KERNEL_DATAKEY="$FLAGS_keys/kernel_data_key.vbprivk"
+ KERNEL_PUBKEY="$FLAGS_keys/kernel_subkey.vbpubk"
+ fi
+
+ debug_msg "Prerequisite check"
+ ensure_files_exist \
+ "$KERNEL_KEYBLOCK" \
+ "$KERNEL_DATAKEY" \
+ "$KERNEL_PUBKEY" \
+ "$FLAGS_image" ||
+ exit 1
+
+ # checks for running on a live system image.
+ if [ "$FLAGS_image" = "$ROOTDEV_DISK" ]; then
+ debug_msg "check valid kernel partitions for live system"
+ local valid_partitions="$(find_valid_kernel_partitions $FLAGS_partitions)"
+ [ -n "$valid_partitions" ] ||
+ die "No valid kernel partitions on ${FLAGS_image} (${FLAGS_partitions})."
+ FLAGS_partitions="$valid_partitions"
+
+ # Sanity checks
+ if [ "$FLAGS_force" = "$FLAGS_TRUE" ]; then
+ echo "
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ ! INFO: ALL SANITY CHECKS WERE BYPASSED. YOU ARE ON YOUR OWN. !
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ " >&2
+ local i
+ for i in $(seq 5 -1 1); do
+ echo -n "\rStart in $i second(s) (^C to abort)... " >&2
+ sleep 1
+ done
+ echo ""
+ elif ! sanity_check_live_firmware ||
+ ! sanity_check_live_partitions ||
+ ! sanity_check_crossystem_flags; then
+ die "IMAGE ${FLAGS_image} IS NOT MODIFIED."
+ fi
+ fi
+
+ resign_ssd_kernel "$FLAGS_image" || num_signed=$?
+
+ debug_msg "Complete."
+ if [ $num_signed -gt 0 -a $num_signed -le $num_given ]; then
+ # signed something at least
+ info "Successfully re-signed ${num_signed} of ${num_given} kernel(s)" \
+ " on device ${FLAGS_image}."
+ else
+ die "Failed re-signing kernels."
+ fi
+}
+
+# People using this to process images may forget to add "-i",
+# so adding parameter check is safer.
+if [ "$#" -gt 0 ]; then
+ flags_help
+ die "Unknown parameters: $*"
+fi
+
+main
diff --git a/nichrome/scripts/vboot/bin/remove_test_label.sh b/nichrome/scripts/vboot/bin/remove_test_label.sh
new file mode 100755
index 000000000..6423e3903
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/remove_test_label.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Remove the test label from lsb-release to prepare an image for
+# signing using the official keys.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+set -e
+image=$1
+
+rootfs=$(make_temp_dir)
+mount_image_partition ${image} 3 ${rootfs}
+sed -i 's/test//' "${rootfs}/etc/lsb-release"
diff --git a/nichrome/scripts/vboot/bin/resign_firmwarefd.sh b/nichrome/scripts/vboot/bin/resign_firmwarefd.sh
new file mode 100755
index 000000000..d4cb5b8c9
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/resign_firmwarefd.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Abort on error
+set -e
+
+# This script is obsolete. The required functionality is now provided by the
+# compiled futility executable, so all this does is invoke that. This wrapper
+# should go away Real Soon Now.
+
+
+# Which futility to run?
+[ -z "$FUTILITY" ] && FUTILITY=futility
+
+# required
+SRC_FD=$1
+DST_FD=$2
+FIRMWARE_DATAKEY=$3
+FIRMWARE_KEYBLOCK=$4
+DEV_FIRMWARE_DATAKEY=$5
+DEV_FIRMWARE_KEYBLOCK=$6
+KERNEL_SUBKEY=$7
+# optional
+VERSION=$8
+PREAMBLE_FLAG=$9
+LOEM_OUTPUT_DIR=${10}
+LOEMID=${11}
+
+if [ ! -e $DEV_FIRMWARE_KEYBLOCK ] || [ ! -e $DEV_FIRMWARE_DATAKEY ] ; then
+ echo "No dev firmware keyblock/datakey found. Reusing normal keys."
+ DEV_FIRMWARE_KEYBLOCK="$FIRMWARE_KEYBLOCK"
+ DEV_FIRMWARE_DATAKEY="$FIRMWARE_DATAKEY"
+fi
+
+# pass optional args
+[ -n "$VERSION" ] && VERSION="--version $VERSION"
+[ -n "$PREAMBLE_FLAG" ] && PREAMBLE_FLAG="--flags $PREAMBLE_FLAG"
+[ -n "$LOEM_OUTPUT_DIR" ] && LOEM_OUTPUT_DIR="--loemdir $LOEM_OUTPUT_DIR"
+[ -n "$LOEMID" ] && LOEMID="--loemid $LOEMID"
+
+exec ${FUTILITY} sign \
+ --signprivate $FIRMWARE_DATAKEY \
+ --keyblock $FIRMWARE_KEYBLOCK \
+ --devsign $DEV_FIRMWARE_DATAKEY \
+ --devkeyblock $DEV_FIRMWARE_KEYBLOCK \
+ --kernelkey $KERNEL_SUBKEY \
+ $VERSION \
+ $PREAMBLE_FLAG \
+ $LOEM_OUTPUT_DIR \
+ $LOEMID \
+ $SRC_FD \
+ $DST_FD
+
+echo UNABLE TO EXEC FUTILITY 1>&2
+exit 1
diff --git a/nichrome/scripts/vboot/bin/resign_kernel_partition.sh b/nichrome/scripts/vboot/bin/resign_kernel_partition.sh
new file mode 100755
index 000000000..fd7cfd398
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/resign_kernel_partition.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script that just takes in a kernel partition and outputs a new vblock
+# signed with the specific keys. For use on signing servers.
+
+# vbutil_kernel must be in the system path.
+
+SCRIPT_DIR=$(dirname $0)
+
+# Abort on error
+set -e
+
+# Check arguments
+if [ $# -lt 4 ] || [ $# -gt 5 ]; then
+ echo "usage: $0 src_kpart dst_vblock kernel_datakey kernel_keyblock [version]"
+ exit 1
+fi
+
+# Make sure the tools we need are available.
+type -P vbutil_kernel &>/dev/null || \
+ ( echo "vbutil_kernel tool not found."; exit 1; )
+
+SRC_KPART=$1
+DST_VBLOCK=$2
+KERNEL_DATAKEY=$3
+KERNEL_KEYBLOCK=$4
+VERSION=$5
+
+if [ -z $VERSION ]; then
+ VERSION=1
+fi
+echo "Using kernel version: $VERSION"
+
+vbutil_kernel --repack "${DST_VBLOCK}" \
+ --vblockonly \
+ --keyblock "${KERNEL_KEYBLOCK}" \
+ --signprivate "${KERNEL_DATAKEY}" \
+ --version "${VERSION}" \
+ --oldblob "${SRC_KPART}"
+
+echo "New kernel vblock was output to ${DST_VBLOCK}"
+
diff --git a/nichrome/scripts/vboot/bin/set_channel.sh b/nichrome/scripts/vboot/bin/set_channel.sh
new file mode 100755
index 000000000..a3bd4f977
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/set_channel.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Changes the channel on a Chrome OS image.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+set -e
+
+if [ $# -ne 2 ]; then
+ cat <
+
+: Path to image.
+: The new channel of the image.
+EOF
+ exit 1
+fi
+
+main() {
+ local image=$1
+ local to=$2
+ local rootfs lsb
+
+ rootfs=$(make_temp_dir)
+ lsb="${rootfs}/etc/lsb-release"
+ mount_image_partition "${image}" 3 "${rootfs}"
+ # Get the current channel on the image.
+ local from=$(lsbval "${lsb}" 'CHROMEOS_RELEASE_TRACK')
+ from=${from%"-channel"}
+ echo "Current channel is '${from}'. Changing to '${to}'."
+
+ local sudo
+ if [[ ! -w ${lsb} ]] ; then
+ sudo="sudo"
+ fi
+ ${sudo} sed -i "s/\b${from}\b/${to}/" "${lsb}" &&
+ echo "Channel change successful."
+ cat "${lsb}"
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/set_chronos_password.sh b/nichrome/scripts/vboot/bin/set_chronos_password.sh
new file mode 100755
index 000000000..a5742305e
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/set_chronos_password.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Customizes a Chrome OS release image by setting the chronos user password.
+
+# Usage: ./set_chronos_password.sh [--force]
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+change_chronos_password() {
+ local rootfs=$1
+ local password=$2
+ echo "Setting chronos password..."
+ local crypted_password="$(echo $password | openssl passwd -1 -stdin)"
+ local temp_shadow="$rootfs/etc/tempshadow"
+ echo "chronos:$crypted_password:14500:0:99999::::" \
+ | sudo tee "$temp_shadow" > /dev/null
+ sudo grep -Ev ^chronos: "$rootfs/etc/shadow" \
+ | sudo tee -a "$temp_shadow" > /dev/null
+ sudo mv -f "$temp_shadow" "$rootfs/etc/shadow"
+}
+
+main() {
+ set -e
+
+ local image=$1
+ local chronos_password=$2
+ if [ $# -ne 2 ] && [ $# -ne 3 ] || [ ! $3 = "--force" ] ; then
+ echo "Usage: $PROG [--force]"
+ exit 1
+ fi
+
+ local rootfs=$(make_temp_dir)
+ if [ $# -eq 2 ]; then
+ mount_image_partition_ro "$image" 3 "$rootfs"
+ if ! no_chronos_password "$rootfs"; then
+ echo "Password is already set [use --force if you'd like to update it]"
+ exit 1
+ fi
+ # Prepare for remounting read/write.
+ sudo umount $rootfs
+ fi
+ mount_image_partition "$image" 3 "$rootfs"
+ change_chronos_password "$rootfs" "$chronos_password"
+ touch "$image" # Updates the image modification time.
+ echo "Password Set."
+}
+
+main $@
diff --git a/nichrome/scripts/vboot/bin/set_gbb_flags.sh b/nichrome/scripts/vboot/bin/set_gbb_flags.sh
new file mode 100755
index 000000000..cadb39b2e
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/set_gbb_flags.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This script can change GBB flags in system live firmware or a given image
+# file.
+
+SCRIPT_BASE="$(dirname "$0")"
+. "$SCRIPT_BASE/common_minimal.sh"
+load_shflags || exit 1
+
+# DEFINE_string name default_value description flag
+DEFINE_string file "" "Path to firmware image. Default to system firmware." "f"
+DEFINE_boolean check_wp $FLAGS_TRUE "Check write protection states first." ""
+
+# Globals
+# ----------------------------------------------------------------------------
+set -e
+
+# Values from vboot_reference/firmware/include/gbb_header.h
+GBBFLAGS_DESCRIPTION="
+ Defined flags (some values may be not supported by all systems):
+
+ GBB_FLAG_DEV_SCREEN_SHORT_DELAY 0x00000001
+ GBB_FLAG_LOAD_OPTION_ROMS 0x00000002
+ GBB_FLAG_ENABLE_ALTERNATE_OS 0x00000004
+ GBB_FLAG_FORCE_DEV_SWITCH_ON 0x00000008
+ GBB_FLAG_FORCE_DEV_BOOT_USB 0x00000010
+ GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK 0x00000020
+ GBB_FLAG_ENTER_TRIGGERS_TONORM 0x00000040
+ GBB_FLAG_FORCE_DEV_BOOT_LEGACY 0x00000080
+ GBB_FLAG_FAFT_KEY_OVERIDE 0x00000100
+ GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC 0x00000200
+ GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY 0x00000400
+ GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC 0x00000800
+ GBB_FLAG_DISABLE_LID_SHUTDOWN 0x00001000
+ GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP 0x00002000
+ GBB_FLAG_ENABLE_SERIAL 0x00004000
+
+ To get a developer-friendly device, try 0x11 (short_delay + boot_usb).
+ For factory-related tests (always DEV), try 0x39.
+ For early development (disable EC/PD software sync), try 0xa39.
+"
+
+FLAGS_HELP="Changes ChromeOS Firmware GBB Flags value.
+
+ Usage: $0 [option_flags] GBB_FLAGS_VALUE
+ $GBBFLAGS_DESCRIPTION"
+
+FLASHROM_COMMON_OPT="-p host"
+FLASHROM_READ_OPT="$FLASHROM_COMMON_OPT -i GBB -r"
+FLASHROM_WRITE_OPT="$FLASHROM_COMMON_OPT -i GBB --fast-verify -w"
+
+# Check write protection
+# ----------------------------------------------------------------------------
+check_write_protection() {
+ local hw_wp="" sw_wp=""
+ if ! crossystem "wpsw_boot?0"; then
+ hw_wp="on"
+ fi
+ local wp_states="$(flashrom $FLASHROM_COMMON_OPT --wp-status 2>/dev/null \
+ | grep WP)"
+ local wp_disabled="$(echo "$wp_states" | grep "WP:.*is disabled.")"
+ local wp_zero_len="$(echo "$wp_states" | grep "WP:.*, len=0x00000000")"
+ if [ -z "$wp_disabled" -a -z "$wp_zero_len" ]; then
+ sw_wp="on"
+ fi
+ if [ -n "$hw_wp" -a -n "$sw_wp" ]; then
+ return $FLAGS_FALSE
+ fi
+ return $FLAGS_TRUE
+}
+
+# Main
+# ----------------------------------------------------------------------------
+main() {
+ if [ "$#" != "1" ]; then
+ flags_help
+ exit 1
+ fi
+
+ local value="$(($1))"
+ local image_file="$FLAGS_file"
+
+ if [ -z "$FLAGS_file" ]; then
+ image_file="$(make_temp_file)"
+ flashrom $FLASHROM_READ_OPT "$image_file"
+ fi
+
+ # Process file
+ local old_value="$(futility gbb -g --flags "$image_file")"
+ printf "Setting GBB flags from %s to 0x%x.." "$old_value" "$value" >&2
+ futility gbb -s --flags="$value" "$image_file"
+
+ if [ -z "$FLAGS_file" ]; then
+ if [ "$FLAGS_check_wp" = "$FLAGS_TRUE" ]; then
+ if ! check_write_protection; then
+ echo ""
+ echo "WARNING: System GBB Flags are NOT changed!!!"
+ echo "ERROR: You must disable write protection before setting flags."
+ exit 1
+ fi
+ fi
+ flashrom $FLASHROM_WRITE_OPT "$image_file"
+ fi
+}
+
+# Parse command line
+FLAGS "$@" || exit 1
+ORIGINAL_PARAMS="$@"
+eval set -- "$FLAGS_ARGV"
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/set_lsb_release.sh b/nichrome/scripts/vboot/bin/set_lsb_release.sh
new file mode 100755
index 000000000..9d0addd09
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/set_lsb_release.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Customizes a Chrome OS release image by setting /etc/lsb-release values.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+set_lsb_release_keyval() {
+ local rootfs=$1
+ local key=$2
+ local value=$3
+ local temp_lsb_release="$rootfs/etc/temp-lsb-release"
+ echo "$key=$value" | sudo tee "$temp_lsb_release" > /dev/null
+ grep -Ev "^$key=" "$rootfs/etc/lsb-release" \
+ | sudo tee -a "$temp_lsb_release" > /dev/null
+ sudo sort -o "$rootfs/etc/lsb-release" "$temp_lsb_release"
+ sudo rm -f "$temp_lsb_release"
+}
+
+main() {
+ set -e
+
+ if [[ $(( $# % 2 )) -eq 0 ]]; then
+ cat < [ [ ...]]
+
+Examples:
+
+$ $PROG chromiumos_image.bin
+
+Dumps /etc/lsb-release from chromiumos_image.bin to stdout.
+
+$ $PROG chromiumos_image.bin CHROMEOS_RELEASE_DESCRIPTION "New description"
+
+Sets the CHROMEOS_RELEASE_DESCRIPTION key's value to "New description"
+in /etc/lsb-release in chromiumos_image.bin, sorts the keys and dumps
+the updated file to stdout.
+
+EOF
+ exit 1
+ fi
+
+ local image=$1
+ shift
+ local rootfs=$(make_temp_dir)
+
+ # If there are no key/value pairs to process, we don't need write access.
+ if [[ $# -eq 0 ]]; then
+ mount_image_partition_ro "${image}" 3 "${rootfs}"
+ else
+ mount_image_partition "${image}" 3 "${rootfs}"
+ touch "${image}" # Updates the image modification time.
+ fi
+
+ # Process all the key/value pairs.
+ local key value
+ while [[ $# -ne 0 ]]; do
+ key=$1 value=$2
+ shift 2
+ set_lsb_release_keyval "${rootfs}" "${key}" "${value}"
+ done
+
+ # Dump the final state.
+ cat "${rootfs}/etc/lsb-release"
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/sign_android_image.sh b/nichrome/scripts/vboot/bin/sign_android_image.sh
new file mode 100755
index 000000000..92e4b65d0
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/sign_android_image.sh
@@ -0,0 +1,243 @@
+#!/bin/bash
+
+# Copyright 2016 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+. "$(dirname "$0")/common.sh"
+
+set -e
+
+# Print usage string
+usage() {
+ cat < /dev/null
+ zipalign 4 "${signed_apk}" "${aligned_apk}"
+
+ # Copy the content instead of mv to avoid owner/mode changes.
+ sudo cp "${aligned_apk}" "${apk}" && rm -f "${aligned_apk}"
+
+ : $(( counter_${keyname} += 1 ))
+ : $(( counter_total += 1 ))
+ done < <(find "${system_mnt}/system" -type f -name '*.apk' -print0)
+
+ # Sanity check.
+ if [[ ${counter_platform} -lt 2 || ${counter_media} -lt 2 ||
+ ${counter_shared} -lt 2 || ${counter_releasekey} -lt 2 ||
+ ${counter_total} -lt 25 ]]; then
+ die "Number of re-signed package seems to be wrong"
+ fi
+}
+
+# Platform key is part of the SELinux policy. Since we are re-signing framework
+# apks, we need to replace the key in the policy as well.
+update_sepolicy() {
+ local system_mnt=$1
+ local key_dir=$2
+
+ # Only platform is used at this time.
+ local public_platform_key="${key_dir}/platform.x509.pem"
+
+ info "Start updating sepolicy"
+
+ local new_cert=$(sed -E '/(BEGIN|END) CERTIFICATE/d' \
+ "${public_platform_key}" | tr -d '\n' \
+ | base64 --decode | hexdump -v -e '/1 "%02x"')
+
+ if [[ -z "${new_cert}" ]]; then
+ die "Unable to get the public platform key"
+ fi
+
+ local orig=$(make_temp_file)
+ local xml="${system_mnt}/system/etc/security/mac_permissions.xml"
+ local pattern='( /dev/null
+ cp "${release_cert}" .
+ local temp_zip=$(make_temp_file)
+ zip -q -r "${temp_zip}.zip" .
+ # Copy the content instead of mv to avoid owner/mode changes.
+ sudo cp "${temp_zip}.zip" "${ota_zip}"
+ popd > /dev/null
+}
+
+# Restore SELinux context. This has to run after all file changes, before
+# creating the new squashfs image.
+reapply_file_security_context() {
+ local system_mnt=$1
+ local root_fs_dir=$2
+
+ info "Reapplying file security context"
+
+ sudo /sbin/setfiles -v -r "${system_mnt}" \
+ "${root_fs_dir}/etc/selinux/arc/contexts/files/android_file_contexts" \
+ "${system_mnt}"
+}
+
+# Snapshot file properties in a directory recursively.
+snapshot_file_properties() {
+ local dir=$1
+ sudo find "${dir}" -exec stat -c '%n:%u:%g:%a:%C' {} + | sort
+}
+
+main() {
+ local root_fs_dir=$1
+ local key_dir=$2
+ local android_dir="${root_fs_dir}/opt/google/containers/android"
+ local system_img="${android_dir}/system.raw.img"
+ # Use the versions in $PATH rather than the system ones.
+ local unsquashfs=$(which unsquashfs)
+ local mksquashfs=$(which mksquashfs)
+
+ if [[ $# -ne 2 ]]; then
+ usage "command takes exactly 2 args"
+ fi
+
+ if [[ ! -f "${system_img}" ]]; then
+ die "System image does not exist: ${system_img}"
+ fi
+
+ if ! type -P zipalign &>/dev/null || ! type -P signapk &>/dev/null; then
+ # TODO(victorhsieh): Make this an error. This is not treating as error
+ # just to make an unrelated test pass by skipping this signing.
+ warn "Skip signing Android apks (some of executables are not found)."
+ exit 0
+ fi
+
+ local working_dir=$(make_temp_dir)
+ local system_mnt="${working_dir}/mnt"
+ local compression_method=$(sudo unsquashfs -s "${system_img}" | \
+ awk '$1 == "Compression" { print $2 }')
+
+ info "Unpacking squashfs image to ${system_img}"
+ sudo "${unsquashfs}" -x -f -no-progress -d "${system_mnt}" "${system_img}"
+
+ snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.orig"
+
+ sign_framework_apks "${system_mnt}" "${key_dir}"
+ update_sepolicy "${system_mnt}" "${key_dir}"
+ replace_ota_cert "${system_mnt}" "${key_dir}/releasekey.x509.pem"
+ reapply_file_security_context "${system_mnt}" "${root_fs_dir}"
+
+ # Sanity check.
+ snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.new"
+ local d
+ if ! d=$(diff "${working_dir}"/properties.{orig,new}); then
+ die "Unexpected change of file property, diff\n${d}"
+ fi
+
+ info "Repacking squashfs image"
+ local old_size=$(stat -c '%s' "${system_img}")
+ # Overwrite the original image.
+ sudo "${mksquashfs}" "${system_mnt}" "${system_img}" \
+ -no-progress -comp "${compression_method}" -noappend
+ local new_size=$(stat -c '%s' "${system_img}")
+ info "Android system image size change: ${old_size} -> ${new_size}"
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/sign_firmware.sh b/nichrome/scripts/vboot/bin/sign_firmware.sh
new file mode 100755
index 000000000..947b455ec
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/sign_firmware.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Wrapper script for re-signing a firmware image.
+
+# Determine script directory.
+SCRIPT_DIR=$(dirname "$0")
+
+# Load common constants and variables.
+. "${SCRIPT_DIR}/common_minimal.sh"
+
+# Abort on error.
+set -e
+
+usage() {
+ cat< [firmware_version] \
+[loem_output_dir]
+
+Signs with keys in , setting firmware version
+to . Outputs signed firmware to .
+The and paths may be the same.
+If no firmware version is specified, it is set as 1.
+EOF
+ exit 1
+}
+
+gbb_update() {
+ local in_firmware="$1"
+ local key_dir="$2"
+ local out_firmware="$3"
+ local rootkey="$4"
+
+ # Replace the root and recovery key in the Google Binary Block of the
+ # firmware. Note: This needs to happen after calling resign_firmwarefd.sh
+ # since it needs to be able to verify the firmware using the root key to
+ # determine the preamble flags.
+ futility gbb \
+ -s \
+ --recoverykey="${key_dir}/recovery_key.vbpubk" \
+ --rootkey="${rootkey}" \
+ "${in_firmware}" \
+ "${out_firmware}"
+}
+
+# Sign a single firmware image.
+# ARGS: [loem_key] [loemid]
+sign_one() {
+ local loem_key="$1"
+ local loemid="$2"
+
+ # Resign the firmware with new keys.
+ "${SCRIPT_DIR}/resign_firmwarefd.sh" \
+ "${in_firmware}" \
+ "${temp_fw}" \
+ "${key_dir}/firmware_data_key${loem_key}.vbprivk" \
+ "${key_dir}/firmware${loem_key}.keyblock" \
+ "${key_dir}/dev_firmware_data_key${loem_key}.vbprivk" \
+ "${key_dir}/dev_firmware${loem_key}.keyblock" \
+ "${key_dir}/kernel_subkey.vbpubk" \
+ "${firmware_version}" \
+ "" \
+ "${loem_output_dir}" \
+ "${loemid}"
+}
+
+# Process all the keysets in the loem.ini file.
+sign_loems() {
+ local line loem_section=false loem_index loemid
+ local rootkey
+
+ while read line; do
+ # Find the [loem] section.
+ if ! ${loem_section}; then
+ if grep -q "^ *\[loem\] *$" <<<"${line}"; then
+ loem_section=true
+ fi
+ continue
+ # Abort when we hit the next section.
+ elif [[ ${line} == *"["* ]]; then
+ break
+ fi
+
+ # Strip comments/whitespace.
+ line=$(sed -e 's:#.*::' -e 's:^ *::' -e 's: *$::' <<<"${line}")
+ loem_index=$(cut -d= -f1 <<<"${line}" | sed 's: *$::')
+ loemid=$(cut -d= -f2 <<<"${line}" | sed 's:^ *::')
+
+ echo "### Processing LOEM ${loem_index} ${loemid}"
+ sign_one ".loem${loem_index}" "${loemid}"
+
+ rootkey="${key_dir}/root_key.loem${loem_index}.vbpubk"
+ cp "${rootkey}" "${loem_output_dir}/rootkey.${loemid}"
+
+ if [[ ${loem_index} == "1" ]]; then
+ gbb_update "${temp_fw}" "${key_dir}" "${out_firmware}" "${rootkey}"
+ fi
+ echo
+ done <"${key_dir}/loem.ini"
+}
+
+main() {
+ if [[ $# -lt 3 || $# -gt 5 ]]; then
+ usage
+ fi
+
+ local in_firmware=$1
+ local key_dir=$2
+ local out_firmware=$3
+ local firmware_version=${4:-1}
+ local loem_output_dir=${5:-}
+
+ local temp_fw=$(make_temp_file)
+
+ if [[ -e ${key_dir}/loem.ini ]]; then
+ if [[ -z ${loem_output_dir} ]]; then
+ die "need loem_output_dir w/loem keysets"
+ fi
+ sign_loems
+ else
+ sign_one
+ gbb_update "${temp_fw}" "${key_dir}" "${out_firmware}" \
+ "${key_dir}/root_key.vbpubk"
+
+ # Additional signing step for nVidia T210 SoC.
+ # Currently, cbootimage is unable to handle path with double slash.
+ if [[ -e ${key_dir}/nv_pkc.pem ]]; then
+ "${SCRIPT_DIR}/sign_nv_cbootimage.sh" \
+ "bootloader" \
+ "${key_dir%/}/nv_pkc.pem" \
+ "${out_firmware}" \
+ tegra210
+ fi
+ fi
+}
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/sign_nv_cbootimage.sh b/nichrome/scripts/vboot/bin/sign_nv_cbootimage.sh
new file mode 100755
index 000000000..da978e840
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/sign_nv_cbootimage.sh
@@ -0,0 +1,262 @@
+#!/bin/bash
+# Copyright 2015 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Wrapper script for signing firmware image using cbootimage.
+
+# Determine script directory.
+SCRIPT_DIR=$(dirname "$0")
+
+# Load common constants and variables.
+. "${SCRIPT_DIR}/common_minimal.sh"
+
+# Abort on error.
+set -e
+
+usage() {
+ cat<
+
+Signs of with using cbootimage for .
+where type is one of
+ bootloader = sign bootloader image
+ lp0_firmware = sign lp0 firmware
+EOF
+ exit 1
+}
+
+# Signs bootloader image using pkc_key provided for given soc
+# Args: TYPE=bootloader PKC_KEY FIRMWARE_IMAGE SOC
+sign_bootloader() {
+ local type=$1
+ local pkc_key="$(readlink -f "$2")"
+ local firmware_image="$(readlink -f "$3")"
+ local soc=$4
+
+ local work_dir=$(make_temp_dir)
+ local config_file=$(make_temp_file)
+ local signed_fw=$(make_temp_file)
+
+ pushd "${work_dir}" >/dev/null
+
+ # Get bootloader length.
+ #
+ # Example:
+ # $ bct_dump image.fastboot.bin
+ # Version = 0x00210001;
+ # BlockSize = 0x00008000;
+ # ...
+ # ...
+ # # Bootloader[0].Length = 69324;
+ # ...
+ # ...
+ #
+ # then, bl_length=69324 (size of bootloader that needs to be signed)
+ local bl_length=$(bct_dump "${firmware_image}" | \
+ sed -n '/Bootloader\[0\].Length/{ s/.*=\s*//; s/;//; p; q}')
+
+ # Extract bootloader to sign.
+ dd \
+ if="${firmware_image}" \
+ of="${signed_fw}.bl.tosig" \
+ count="${bl_length}" \
+ ibs=1 \
+ skip=32768 >/dev/null 2>&1
+
+ # Calculate rsa signature for bootloader.
+ openssl \
+ dgst -sha256 \
+ -sigopt rsa_padding_mode:pss \
+ -sigopt rsa_pss_saltlen:-1 \
+ -sign "${pkc_key}" \
+ -out "${signed_fw}.bl.sig" \
+ "${signed_fw}.bl.tosig"
+
+ # Update bootloader's rsa signature, aes hash and bct's aes hash.
+ echo "RsaPssSigBlFile = ${signed_fw}.bl.sig;" > "${config_file}"
+ echo "RehashBl;" >> "${config_file}"
+ cbootimage \
+ -s "${soc}" \
+ -u "${config_file}" \
+ "${firmware_image}" \
+ "${signed_fw}.tmp" >/dev/null
+
+ # Extract the part of bct which needs to be rsa signed.
+ dd \
+ if="${signed_fw}.tmp" \
+ of="${signed_fw}.bct.tosig" \
+ count=8944 \
+ ibs=1 \
+ skip=1296 >/dev/null 2>&1
+
+ # Calculate rsa signature for bct.
+ openssl \
+ dgst -sha256 \
+ -sigopt rsa_padding_mode:pss \
+ -sigopt rsa_pss_saltlen:-1 \
+ -sign "${pkc_key}" \
+ -out "${signed_fw}.bct.sig" \
+ "${signed_fw}.bct.tosig"
+
+ # Create public key modulus from key file.
+ openssl \
+ rsa -in "${pkc_key}" \
+ -noout \
+ -modulus \
+ -out "${signed_fw}.key.mod"
+
+ # Remove prefix.
+ cut \
+ -d= \
+ -f2 "${signed_fw}.key.mod" > "${signed_fw}.key.mod.tmp1"
+ dd \
+ if="${signed_fw}.key.mod.tmp1" \
+ of="${signed_fw}.key.mod.tmp" \
+ count=512 \
+ ibs=1 >/dev/null 2>&1
+
+ # Convert from hexdecimal to binary.
+ perl -pe 's/([0-9a-f]{2})/chr hex $1/gie' \
+ < "${signed_fw}.key.mod.tmp" \
+ > "${signed_fw}.key.mod.bin"
+
+ # Update bct's rsa signature and modulus.
+ echo "RsaPssSigBctFile = ${signed_fw}.bct.sig;" > "${config_file}"
+ echo "RsaKeyModulusFile = ${signed_fw}.key.mod.bin;" >> "${config_file}"
+ cbootimage \
+ -s "${soc}" \
+ -u "${config_file}" \
+ "${signed_fw}.tmp" \
+ "${signed_fw}" >/dev/null
+
+ # Calculate hash of public key modulus.
+ objcopy \
+ -I binary \
+ --reverse-bytes=256 \
+ "${signed_fw}.key.mod.bin" \
+ "${signed_fw}.key.mod.bin.rev"
+ openssl \
+ dgst -sha256 \
+ -binary \
+ -out "${signed_fw}.key.sha" \
+ "${signed_fw}.key.mod.bin.rev"
+
+ popd >/dev/null
+
+ # Copy signed firmware image and public key hash to current directory..
+ mv "${signed_fw}" "${firmware_image}"
+ mv "${signed_fw}.key.sha" "${firmware_image}.pubkey.sha"
+}
+
+# Signs lp0 firmware image using pkc_key provided for given soc
+# Args: TYPE=lp0_firmware PKC_KEY FIRMWARE_IMAGE SOC
+sign_lp0_firmware() {
+ local type=$1
+ local pkc_key="$(readlink -f "$2")"
+ local firmware_image="$(readlink -f "$3")"
+ local soc=$4
+
+ local work_dir=$(make_temp_dir)
+ local signed_fw=$(make_temp_file)
+
+ pushd "${work_dir}" >/dev/null
+
+ cp "${firmware_image}" "${signed_fw}"
+
+ # Extract the part of the binary which needs to be signed.
+ dd \
+ if="${firmware_image}" \
+ of="${signed_fw}.tosig" \
+ ibs=1 \
+ skip=544 >/dev/null 2>&1
+
+ # Calculate rsa-pss signature.
+ openssl \
+ dgst -sha256 \
+ -sigopt rsa_padding_mode:pss \
+ -sigopt rsa_pss_saltlen:-1 \
+ -sign "${pkc_key}" \
+ -out "${signed_fw}.rsa.sig" \
+ "${signed_fw}.tosig"
+
+ # Reverse rsa signature to meet tegra soc ordering requirement.
+ objcopy \
+ -I binary \
+ --reverse-bytes=256 \
+ "${signed_fw}.rsa.sig" \
+ "${signed_fw}.rsa.sig.rev"
+
+ # Inject rsa-pss signature into the binary image's header.
+ dd \
+ if="${signed_fw}.rsa.sig.rev" \
+ of="${signed_fw}" \
+ count=256 \
+ obs=1 \
+ seek=288 \
+ conv=notrunc >/dev/null 2>&1
+
+ # Generate public key modulus from key file.
+ openssl \
+ rsa -in "${pkc_key}" \
+ -noout \
+ -modulus \
+ -out "${signed_fw}.key.mod"
+
+ # Remove prefix.
+ cut \
+ -d= \
+ -f2 "${signed_fw}.key.mod" > "${signed_fw}.key.mod.tmp1"
+
+ dd \
+ if="${signed_fw}.key.mod.tmp1" \
+ of="${signed_fw}.key.mod.tmp" \
+ count=512 \
+ ibs=1 >/dev/null 2>&1
+
+ # Convert from hexdecimal to binary.
+ perl -pe 's/([0-9a-f]{2})/chr hex $1/gie' \
+ < "${signed_fw}.key.mod.tmp" \
+ > "${signed_fw}.key.mod.bin"
+
+ # Reverse byte order.
+ objcopy \
+ -I binary \
+ --reverse-bytes=256 \
+ "${signed_fw}.key.mod.bin" \
+ "${signed_fw}.key.mod.bin.rev"
+
+ # Inject public key modulus into the binary image's header.
+ dd \
+ if="${signed_fw}.key.mod.bin.rev" \
+ of="${signed_fw}" \
+ count=256 \
+ obs=1 \
+ seek=16 \
+ conv=notrunc >/dev/null 2>&1
+
+ popd >/dev/null
+ mv "${signed_fw}" "${firmware_image}"
+}
+
+main() {
+ if [[ $# -ne 4 ]]; then
+ usage
+ fi
+
+ local type=$1
+
+ case ${type} in
+ bootloader)
+ sign_bootloader "$@"
+ ;;
+ lp0_firmware)
+ sign_lp0_firmware "$@"
+ ;;
+ *)
+ usage
+ ;;
+ esac
+}
+
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/sign_oci_container.sh b/nichrome/scripts/vboot/bin/sign_oci_container.sh
new file mode 100755
index 000000000..793e5f80d
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/sign_oci_container.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+# Copyright 2017 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+. "$(dirname "$0")/common.sh"
+
+load_shflags || exit 1
+
+DEFINE_string output "" \
+ "Where to write signed output to (default: sign in-place)"
+
+FLAGS_HELP="Usage: ${PROG} [options]
+
+Signs with keys in . Should have an imageloader.json
+file which imageloader can understand and will use to mount the squashfs
+image that provides the container's rootfs and OCI configuration.
+
+Input can be an unpacked imageloader image, or a CRX/ZIP file.
+"
+
+# Parse command line.
+FLAGS "$@" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+# Abort on error.
+set -e
+
+# Sign the directory holding OCI container(s). We look for an imageloader.json
+# file.
+sign_oci_container() {
+ [[ $# -eq 3 ]] || die "Usage: sign_oci_container "
+ local input="${1%/}"
+ local key_file="$2"
+ local output="$3"
+
+ if [[ "${input}" != "${output}" ]]; then
+ rsync -a "${input}/" "${output}/"
+ fi
+
+ local manifest out_manifest
+ while read -d $'\0' -r manifest; do
+ out_manifest="${output}/${manifest%.json}.sig.2"
+ manifest="${input}/${manifest}"
+ info "Signing: ${manifest}"
+ if ! openssl dgst -sha256 -sign "${key_file}" \
+ -out "${out_manifest}" "${manifest}"; then
+ die "Failed to sign"
+ fi
+ done < <(find "${input}/" -name imageloader.json -printf '%P\0')
+}
+
+# Sign the crx/zip holding OCI container(s). We look for an imageloader.json
+# file.
+sign_oci_container_zip() {
+ [[ $# -eq 3 ]] || die "Usage: sign_oci_container_zip "
+ local input="$1"
+ local key_file="$2"
+ local output="$3"
+ local tempdir=$(make_temp_dir)
+
+ info "Unpacking archive: ${input}"
+ unzip -q "${input}" -d "${tempdir}"
+
+ sign_oci_container "${tempdir}" "${key_file}" "${tempdir}"
+
+ rm -f "${output}"
+ info "Packing archive: ${output}"
+ (
+ cd "${tempdir}"
+ zip -q -r - ./
+ ) >"${output}"
+}
+
+main() {
+ if [[ $# -ne 2 ]]; then
+ flags_help
+ exit 1
+ fi
+
+ local input="${1%/}"
+ local key_dir="$2"
+
+ local key_file="${key_dir}/cros-oci-container.pem"
+ if [[ ! -e "${key_file}" ]]; then
+ die "Missing key file: ${key_file}"
+ fi
+
+ : "${FLAGS_output:=${input}}"
+
+ if [[ -f "${input}" ]]; then
+ sign_oci_container_zip "${input}" "${key_file}" "${FLAGS_output}"
+ else
+ sign_oci_container "${input}" "${key_file}" "${FLAGS_output}"
+ fi
+}
+main "$@"
diff --git a/nichrome/scripts/vboot/bin/sign_official_build.sh b/nichrome/scripts/vboot/bin/sign_official_build.sh
new file mode 100755
index 000000000..f31bd622b
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/sign_official_build.sh
@@ -0,0 +1,966 @@
+#!/bin/bash
+
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Sign the final build image using the "official" keys.
+#
+# Prerequisite tools needed in the system path:
+#
+# futility (from src/platform/vboot_reference)
+# vbutil_kernel (from src/platform/vboot_reference)
+# cgpt (from src/platform/vboot_reference)
+# dump_kernel_config (from src/platform/vboot_reference)
+# verity (from src/platform/verity)
+# load_kernel_test (from src/platform/vboot_reference)
+# dumpe2fs
+# sha1sum
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+# Print usage string
+usage() {
+ cat < input_image /path/to/keys/dir [output_image] [version_file]
+where is one of:
+ ssd (sign an SSD image)
+ base (sign a base image, similar to an SSD image)
+ recovery (sign a USB recovery image)
+ factory (sign a factory install image)
+ install (old alias to "factory")
+ update_payload (sign a delta update hash)
+ kernel (sign a kernel image)
+ recovery_kernel (sign a recovery_kernel image)
+ firmware (sign a firmware image)
+ usb (sign an image to boot directly from USB)
+ verify (verify an image including rootfs hashes)
+ nv_lp0_firmware (sign nvidia lp0 firmware)
+ accessory_usbpd (sign USB-PD accessory firmware)
+ accessory_rwsig (sign accessory RW firmware)
+ oci-container (sign an OCI container)
+
+output_image: File name of the signed output image
+version_file: File name of where to read the kernel and firmware versions.
+
+If you are signing an image, you must specify an [output_image] and
+optionally, a [version_file].
+
+EOF
+ if [[ $# -gt 0 ]]; then
+ error "$*"
+ exit 1
+ fi
+ exit 0
+}
+
+# Verify we have as many arguments as we expect, else show usage & quit.
+# Usage:
+# check_argc
+# check_argc
+check_argc() {
+ case $# in
+ 2)
+ if [[ $1 -ne $2 ]]; then
+ usage "command takes exactly $2 args"
+ fi
+ ;;
+ 3)
+ if [[ $1 -lt $2 || $1 -gt $3 ]]; then
+ usage "command takes $2 to $3 args"
+ fi
+ ;;
+ *)
+ die "check_argc: incorrect number of arguments"
+ esac
+}
+
+# Abort on errors.
+set -e
+
+# Add to the path since some tools reside here and may not be in the non-root
+# system path.
+PATH=$PATH:/usr/sbin:/sbin
+
+# Make sure the tools we need are available.
+for prereqs in futility vbutil_kernel cgpt dump_kernel_config verity \
+ load_kernel_test dumpe2fs sha1sum e2fsck; do
+ type -P "${prereqs}" &>/dev/null || \
+ die "${prereqs} tool not found."
+done
+
+TYPE=$1
+INPUT_IMAGE=$2
+KEY_DIR=$3
+OUTPUT_IMAGE=$4
+VERSION_FILE=$5
+
+FIRMWARE_VERSION=1
+KERNEL_VERSION=1
+
+# Get current rootfs hash and kernel command line
+# ARGS: IMAGE KERNELPART
+grab_kernel_config() {
+ local image=$1
+ local kernelpart=$2 # Kernel partition number to grab.
+ # Grab the existing kernel partition and get the kernel config.
+ temp_kimage=$(make_temp_file)
+ extract_image_partition ${image} ${kernelpart} ${temp_kimage}
+ dump_kernel_config ${temp_kimage}
+}
+
+# TODO(gauravsh): These are duplicated from chromeos-setimage. We need
+# to move all signing and rootfs code to one single place where it can be
+# reused. crosbug.com/19543
+
+# get_verity_arg ->
+get_verity_arg() {
+ echo "$1" | sed -n "s/.*\b$2=\([^ \"]*\).*/\1/p"
+}
+
+is_old_verity_argv() {
+ local depth=$(echo "$1" | cut -f7 -d' ')
+ if [ "$depth" = "0" ]; then
+ return 0
+ fi
+ return 1
+}
+
+# Get the dmparams parameters from a kernel config.
+get_dmparams_from_config() {
+ local kernel_config=$1
+ echo ${kernel_config} | sed -nre 's/.*dm="([^"]*)".*/\1/p'
+}
+# Get the verity root digest hash from a kernel config command line.
+get_hash_from_config() {
+ local kernel_config=$1
+ local dm_config=$(get_dmparams_from_config "${kernel_config}")
+ local vroot_dev=$(get_dm_slave "${dm_config}" vroot)
+ if is_old_verity_argv "${vroot_dev}"; then
+ echo ${vroot_dev} | cut -f9 -d ' '
+ else
+ echo $(get_verity_arg "${vroot_dev}" root_hexdigest)
+ fi
+}
+
+# Get the slave device and its args
+# get_dm_ags $dm_config [vboot|vroot]
+# Assumes we have only one slave device per device
+get_dm_slave() {
+ local dm=$1
+ local device=$2
+ echo $(echo "${dm}" | sed -nre "s/.*${device}[^,]*,([^,]*).*/\1/p")
+}
+
+# Set the slave device and its args for a device
+# get_dm_ags $dm_config [vboot|vroot] args
+# Assumes we have only one slave device per device
+set_dm_slave() {
+ local dm=$1
+ local device=$2
+ local slave=$3
+ echo $(echo "${dm}" |
+ sed -nre "s#(.*${device}[^,]*,)([^,]*)(.*)#\1${slave}\3#p")
+}
+
+CALCULATED_KERNEL_CONFIG=
+CALCULATED_DM_ARGS=
+# Calculate rootfs hash of an image
+# Args: ROOTFS_IMAGE KERNEL_CONFIG HASH_IMAGE
+#
+# rootfs calculation parameters are grabbed from KERNEL_CONFIG
+#
+# Updated dm-verity arguments (to be replaced in kernel config command line)
+# with the new hash is stored in $CALCULATED_DM_ARGS and the new hash image is
+# written to the file HASH_IMAGE.
+calculate_rootfs_hash() {
+ local rootfs_image=$1
+ local kernel_config=$2
+ local hash_image=$3
+ local dm_config=$(get_dmparams_from_config "${kernel_config}")
+
+ if [ -z "${dm_config}" ]; then
+ warn "Couldn't grab dm_config. Aborting rootfs hash calculation."
+ return 1
+ fi
+ local vroot_dev=$(get_dm_slave "${dm_config}" vroot)
+
+ local rootfs_sectors
+ local verity_depth
+ local verity_algorithm
+ local root_dev
+ local hash_dev
+ local verity_bin="verity"
+ if is_old_verity_argv "${vroot_dev}"; then
+ # dm="0 2097152 verity ROOT_DEV HASH_DEV 2097152 1 \
+ # sha1 63b7ad16cb9db4b70b28593f825aa6b7825fdcf2"
+ rootfs_sectors=$(echo ${vroot_dev} | cut -f2 -d' ')
+ verity_depth=$(echo ${vroot_dev} | cut -f7 -d' ')
+ verity_algorithm=$(echo ${vroot_dev} | cut -f8 -d' ')
+ root_dev=$(echo ${vroot_dev} | cut -f4 -d ' ')
+ hash_dev=$(echo ${vroot_dev} | cut -f5 -d ' ')
+ # Hack around the fact that the signer needs to use the old version of
+ # verity to generate legacy verity kernel parameters. If we find it,
+ # we use it.
+ type -P "verity-old" &>/dev/null && verity_bin="verity-old"
+ else
+ # Key-value parameters.
+ rootfs_sectors=$(get_verity_arg "${vroot_dev}" hashstart)
+ verity_depth=0
+ verity_algorithm=$(get_verity_arg "${vroot_dev}" alg)
+ root_dev=$(get_verity_arg "${vroot_dev}" payload)
+ hash_dev=$(get_verity_arg "${vroot_dev}" hashtree)
+ salt=$(get_verity_arg "${vroot_dev}" salt)
+ fi
+
+ local salt_arg
+ if [ -n "$salt" ]; then
+ salt_arg="salt=$salt"
+ fi
+
+ # Run the verity tool on the rootfs partition.
+ local slave=$(sudo ${verity_bin} mode=create \
+ alg=${verity_algorithm} \
+ payload="${rootfs_image}" \
+ payload_blocks=$((rootfs_sectors / 8)) \
+ hashtree="${hash_image}" ${salt_arg})
+ # Reconstruct new kernel config command line and replace placeholders.
+ slave="$(echo "${slave}" |
+ sed -s "s|ROOT_DEV|${root_dev}|g;s|HASH_DEV|${hash_dev}|")"
+ CALCULATED_DM_ARGS="$(set_dm_slave "${dm_config}" vroot "${slave}")"
+ CALCULATED_KERNEL_CONFIG="$(echo "${kernel_config}" |
+ sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${CALCULATED_DM_ARGS}\3#g")"
+}
+
+# Re-calculate rootfs hash, update rootfs and kernel command line(s).
+# Args: IMAGE DM_PARTNO KERN_A_KEYBLOCK KERN_A_PRIVKEY KERN_B_KEYBLOCK \
+# KERN_B_PRIVKEY
+#
+# The rootfs is hashed by tool 'verity', and the hash data is stored after the
+# rootfs. A hash of those hash data (also known as final verity hash) may be
+# contained in kernel 2 or kernel 4 command line.
+#
+# This function reads dm-verity configuration from DM_PARTNO, rebuilds rootfs
+# hash, and then resigns kernel A & B by their keyblock and private key files.
+update_rootfs_hash() {
+ local image=$1 # Input image.
+ local dm_partno="$2" # Partition number of kernel that contains verity args.
+ local kern_a_keyblock="$3" # Keyblock file for kernel A.
+ local kern_a_privkey="$4" # Private key file for kernel A.
+ local kern_b_keyblock="$5" # Keyblock file for kernel B.
+ local kern_b_privkey="$6" # Private key file for kernel A.
+
+ # Note even though there are two kernels, there is one place (after rootfs)
+ # for hash data, so we must assume both kernel use same hash algorithm (i.e.,
+ # DM config).
+ info "Updating rootfs hash and updating config for Kernel partitions"
+
+ # If we can't find dm parameters in the kernel config, bail out now.
+ local kernel_config=$(grab_kernel_config "${image}" "${dm_partno}")
+ local dm_config=$(get_dmparams_from_config "${kernel_config}")
+ if [ -z "${dm_config}" ]; then
+ error "Couldn't grab dm_config from kernel partition ${dm_partno}"
+ error " (config: ${kernel_config})"
+ return 1
+ fi
+
+ # check and clear need_to_resign tag
+ local rootfs_dir=$(make_temp_dir)
+ mount_image_partition_ro "${image}" 3 "${rootfs_dir}"
+ if has_needs_to_be_resigned_tag "${rootfs_dir}"; then
+ # remount as RW
+ sudo umount "${rootfs_dir}"
+ mount_image_partition "${image}" 3 "${rootfs_dir}"
+ sudo rm -f "${rootfs_dir}/${TAG_NEEDS_TO_BE_SIGNED}"
+ fi
+ sudo umount "${rootfs_dir}"
+
+ local rootfs_image=$(make_temp_file)
+ extract_image_partition ${image} 3 ${rootfs_image}
+ local hash_image=$(make_temp_file)
+
+ # Disable rw mount support prior to hashing.
+ disable_rw_mount "${rootfs_image}"
+
+ if ! calculate_rootfs_hash "${rootfs_image}" "${kernel_config}" \
+ "${hash_image}"; then
+ error "calculate_rootfs_hash failed!"
+ error "Aborting rootfs hash update!"
+ return 1
+ fi
+
+ local rootfs_blocks=$(sudo dumpe2fs "${rootfs_image}" 2> /dev/null |
+ grep "Block count" |
+ tr -d ' ' |
+ cut -f2 -d:)
+ local rootfs_sectors=$((rootfs_blocks * 8))
+
+ # Overwrite the appended hashes in the rootfs
+ dd if=${hash_image} of=${rootfs_image} bs=512 \
+ seek=${rootfs_sectors} conv=notrunc 2>/dev/null
+ replace_image_partition ${image} 3 ${rootfs_image}
+
+ # Update kernel command lines
+ local dm_args="${CALCULATED_DM_ARGS}"
+ local temp_config=$(make_temp_file)
+ local temp_kimage=$(make_temp_file)
+ local updated_kimage=$(make_temp_file)
+ local kernelpart=
+ local keyblock=
+ local priv_key=
+ local new_kernel_config=
+
+ for kernelpart in 2 4; do
+ if ! new_kernel_config="$(
+ grab_kernel_config "${image}" "${kernelpart}" 2>/dev/null)" &&
+ [[ "${kernelpart}" == 4 ]]; then
+ # Legacy images don't have partition 4.
+ info "Skipping empty kernel partition 4 (legacy images)."
+ continue
+ fi
+ new_kernel_config="$(echo "${new_kernel_config}" |
+ sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${dm_args}\3#g")"
+ info "New config for kernel partition ${kernelpart} is:"
+ echo "${new_kernel_config}" | tee "${temp_config}"
+ extract_image_partition "${image}" "${kernelpart}" "${temp_kimage}"
+ # Re-calculate kernel partition signature and command line.
+ if [[ "$kernelpart" == 2 ]]; then
+ keyblock="${kern_a_keyblock}"
+ priv_key="${kern_a_privkey}"
+ else
+ keyblock="${kern_b_keyblock}"
+ priv_key="${kern_b_privkey}"
+ fi
+ vbutil_kernel --repack ${updated_kimage} \
+ --keyblock ${keyblock} \
+ --signprivate ${priv_key} \
+ --version "${KERNEL_VERSION}" \
+ --oldblob ${temp_kimage} \
+ --config ${temp_config}
+ replace_image_partition ${image} ${kernelpart} ${updated_kimage}
+ done
+}
+
+# Update the SSD install-able vblock file on stateful partition.
+# ARGS: Loopdev
+# This is deprecated because all new images should have a SSD boot-able kernel
+# in partition 4. However, the signer needs to be able to sign new & old images
+# (crbug.com/449450#c13) so we will probably never remove this.
+update_stateful_partition_vblock() {
+ local loopdev="$1"
+ local temp_out_vb="$(make_temp_file)"
+
+ local loop_kern="${loopdev}p4"
+ if [[ -z "$(sudo dump_kernel_config "${loop_kern}" 2>/dev/null)" ]]; then
+ info "Building vmlinuz_hd.vblock from legacy image partition 2."
+ loop_kern="${loopdev}p2"
+ fi
+
+ # vblock should always use kernel keyblock.
+ sudo vbutil_kernel --repack "${temp_out_vb}" \
+ --keyblock "${KEY_DIR}/kernel.keyblock" \
+ --signprivate "${KEY_DIR}/kernel_data_key.vbprivk" \
+ --oldblob "${loop_kern}" \
+ --vblockonly
+
+ # Copy the installer vblock to the stateful partition.
+ local stateful_dir=$(make_temp_dir)
+ sudo mount "${loopdev}p1" "${stateful_dir}"
+ sudo cp ${temp_out_vb} ${stateful_dir}/vmlinuz_hd.vblock
+ sudo umount "${stateful_dir}"
+}
+
+# Do a sanity check on the image's rootfs
+# ARGS: Image
+verify_image_rootfs() {
+ local rootfs=$1
+ # This flips the read-only compatibility flag, so that e2fsck does not
+ # complain about unknown file system capabilities.
+ enable_rw_mount "${rootfs}"
+ info "Running e2fsck to check root file system for errors"
+ sudo e2fsck -fn "${rootfs}" ||
+ die "Root file system has errors!"
+ # Flip the bit back so we don't break hashes.
+ disable_rw_mount "${rootfs}"
+}
+
+# Extracts a firmware updater bundle (for firmware image binaries) file
+# (generated by src/platform/firmware/pack_firmware.sh).
+# Args: INPUT_FILE OUTPUT_DIR
+extract_firmware_bundle() {
+ local input="$(readlink -f "$1")"
+ local output_dir="$2"
+ if [ ! -s "${input}" ]; then
+ return 1
+ elif grep -q '^##CUTHERE##' "${input}"; then
+ # Bundle supports self-extraction.
+ "$input" --sb_extract "${output_dir}" ||
+ die "Extracting firmware autoupdate (--sb_extract) failed."
+ else
+ # Legacy bundle - try uudecode.
+ uudecode -o - ${input} | tar -C ${output_dir} -zxf - 2>/dev/null ||
+ die "Extracting firmware autoupdate failed."
+ fi
+}
+
+# Repacks firmware updater bundle content from given folder.
+# Args: INPUT_DIR TARGET_SCRIPT
+repack_firmware_bundle() {
+ local input_dir="$1"
+ local target="$(readlink -f "$2")"
+
+ if [ ! -s "${target}" ]; then
+ return 1
+ elif grep -q '^##CUTHERE##' "${target}"; then
+ # Bundle supports repacking.
+ # Workaround issue crosbug.com/p/33719
+ sed -i \
+ 's/shar -Q -q -x -m -w/shar -Q -q -x -m --no-character-count/' \
+ "${target}"
+ "$target" --sb_repack "${input_dir}" ||
+ die "Updating firmware autoupdate (--sb_repack) failed."
+ else
+ # Legacy bundle using uuencode + tar.gz.
+ # Replace MD5 checksum in the firmware update payload.
+ local newfd_checksum="$(md5sum ${input_dir}/bios.bin | cut -f 1 -d ' ')"
+ local temp_version="$(make_temp_file)"
+ cat ${input_dir}/VERSION |
+ sed -e "s#\(.*\)\ \(.*bios.bin.*\)#${newfd_checksum}\ \2#" > ${temp_version}
+ mv ${temp_version} ${input_dir}/VERSION
+
+ # Re-generate firmware_update.tgz and copy over encoded archive in
+ # the original shell ball.
+ sed -ine '/^begin .*firmware_package/,/end/D' "$target"
+ tar zcf - -C "${input_dir}" . |
+ uuencode firmware_package.tgz >>"${target}"
+ fi
+}
+
+# Sign a firmware in-place with the given keys.
+# Args: FIRMWARE_IMAGE KEY_DIR FIRMWARE_VERSION [LOEM_OUTPUT_DIR]
+sign_firmware() {
+ local image=$1
+ local key_dir=$2
+ local firmware_version=$3
+ local loem_output_dir=${4:-}
+
+ # Resign the firmware with new keys, also replacing the root and recovery
+ # public keys in the GBB.
+ "${SCRIPT_DIR}/sign_firmware.sh" "${image}" "${key_dir}" "${image}" \
+ "${firmware_version}" "${loem_output_dir}"
+ info "Signed firmware image output to ${image}"
+}
+
+# Sign nvidia lp0 firmware with the given keys.
+# Args: NV_LP0_FIRMWARE_IMAGE KEY_DIR
+sign_nv_lp0_firmware() {
+ local nv_lp0_fw_image=$1
+ local key_dir=$2
+
+ "${SCRIPT_DIR}/sign_nv_cbootimage.sh" "lp0_firmware" \
+ "${key_dir%/}/nv_pkc.pem" "${nv_lp0_fw_image}" "tegra210"
+ info "Signed nvidia lp0 firmware image output to ${nv_lp0_fw_image}"
+}
+
+# Sign a kernel in-place with the given keys.
+# Args: KERNEL_IMAGE KEY_DIR KERNEL_VERSION
+sign_kernel() {
+ local image=$1
+ local key_dir=$2
+ local kernel_version=$3
+
+ # Note: Although vbutil_kernel may correctly handle specifying the same
+ # output file as the input file, we do not want to rely on it correctly
+ # handing that. Hence, the use of a temporary file.
+ local temp_kernel=$(make_temp_file)
+
+ # Resign the kernel with new keys.
+ vbutil_kernel --repack "${temp_kernel}" \
+ --keyblock "${key_dir}/kernel.keyblock" \
+ --signprivate "${key_dir}/kernel_data_key.vbprivk" \
+ --version "${kernel_version}" \
+ --oldblob "${image}"
+
+ mv "${temp_kernel}" "${image}"
+ info "Signed kernel image output to ${image}"
+}
+
+# Sign a recovery kernel in-place with the given keys.
+# Args: KERNEL_IMAGE KEY_DIR KERNEL_VERSION
+sign_recovery_kernel() {
+ local image=$1
+ local key_dir=$2
+ local kernel_version=$3
+
+ # Note: Although vbutil_kernel may correctly handle specifying the same
+ # output file as the input file, we do not want to rely on it correctly
+ # handing that. Hence, the use of a temporary file.
+ local temp_kernel=$(make_temp_file)
+
+ # Resign the kernel with new recovery keys.
+ vbutil_kernel --repack "${temp_kernel}" \
+ --keyblock "${key_dir}/recovery_kernel.keyblock" \
+ --signprivate "${key_dir}/recovery_kernel_data_key.vbprivk" \
+ --version "${kernel_version}" \
+ --oldblob "${image}"
+
+ mv "${temp_kernel}" "${image}"
+ info "Signed recovery_kernel image output to ${image}"
+}
+
+# Sign a delta update payload (usually created by paygen).
+# Args: INPUT_IMAGE KEY_DIR OUTPUT_IMAGE
+sign_update_payload() {
+ local image=$1
+ local key_dir=$2
+ local output=$3
+ local key_size key_file="${key_dir}/update_key.pem"
+ # Maps key size to verified boot's algorithm id (for pad_digest_utility).
+ # Hashing algorithm is always SHA-256.
+ local algo algos=(
+ [1024]=1
+ [2048]=4
+ [4096]=7
+ [8192]=10
+ )
+
+ key_size=$(openssl rsa -text -noout -in "${key_file}" | \
+ sed -n -r '1{s/Private-Key: \(([0-9]*) bit\)/\1/p}')
+ algo=${algos[${key_size}]}
+ if [[ -z ${algo} ]]; then
+ die "Unknown algorithm specified by key_size=${key_size}"
+ fi
+
+ pad_digest_utility ${algo} "${image}" | \
+ openssl rsautl -sign -pkcs -inkey "${key_file}" -out "${output}"
+}
+
+# Re-sign the firmware AU payload inside the image rootfs with a new keys.
+# Args: IMAGE
+resign_firmware_payload() {
+ local image=$1
+
+ if [ -n "${NO_FWUPDATE}" ]; then
+ info "Skipping firmware update."
+ return
+ fi
+
+ # Grab firmware image from the autoupdate bundle (shellball).
+ local rootfs_dir=$(make_temp_dir)
+ mount_image_partition ${image} 3 ${rootfs_dir}
+ local firmware_bundle="${rootfs_dir}/usr/sbin/chromeos-firmwareupdate"
+ local shellball_dir=$(make_temp_dir)
+
+ # extract_firmware_bundle can fail if the image has no firmware update.
+ if ! extract_firmware_bundle "${firmware_bundle}" "${shellball_dir}"; then
+ # Unmount now to prevent changes.
+ sudo umount "${rootfs_dir}"
+ info "Didn't find a firmware update. Not signing firmware."
+ return
+ fi
+ info "Found a valid firmware update shellball."
+
+ if [[ -d "${shellball_dir}/models" ]]; then
+ info "Signing firmware for all of the models in the unified build."
+ local model_dir
+ for model_dir in "${shellball_dir}"/models/*; do
+ local image_file sign_args=() loem_sfx loem_output_dir
+ for image_file in "${model_dir}"/bios*.bin; do
+ local model_name=$(sed -r 's:.*/models/(.*)/bios.*[.]bin$:\1:'\
+ <<<"${model_dir}")
+ if [[ -e "${KEY_DIR}/loem.ini" ]]; then
+ # Extract the extended details from "bios.bin" and use that, along
+ # with the model name, as the subdir for the keyset.
+ loem_sfx=$(sed -r "s:.*/models/${model_name}/bios([^/]*)[.]bin$:\1:"\
+ <<<"${image_file}")
+ loem_output_dir="${shellball_dir}/keyset${loem_sfx}${model_name}"
+ sign_args=( "${loem_output_dir}" )
+ mkdir -p "${loem_output_dir}"
+ fi
+ sign_firmware "${image_file}" "${KEY_DIR}" "${FIRMWARE_VERSION}" \
+ "${sign_args[@]}"
+ done
+ done
+ else
+ local image_file sign_args=() loem_sfx loem_output_dir
+ for image_file in "${shellball_dir}"/bios*.bin; do
+ if [[ -e "${KEY_DIR}/loem.ini" ]]; then
+ # Extract the extended details from "bios.bin" and use that in the
+ # subdir for the keyset.
+ loem_sfx=$(sed -r 's:.*/bios([^/]*)[.]bin$:\1:' <<<"${image_file}")
+ loem_output_dir="${shellball_dir}/keyset${loem_sfx}"
+ sign_args=( "${loem_output_dir}" )
+ mkdir -p "${loem_output_dir}"
+ fi
+ sign_firmware "${image_file}" "${KEY_DIR}" "${FIRMWARE_VERSION}" \
+ "${sign_args[@]}"
+ done
+ fi
+
+ local signer_notes="${shellball_dir}/VERSION.signer"
+ echo "" >"$signer_notes"
+ info "Signed with keyset in $(readlink -f "${KEY_DIR}") ." >>"${signer_notes}"
+
+ new_shellball=$(make_temp_file)
+ cp -f "${firmware_bundle}" "${new_shellball}"
+ chmod a+rx "${new_shellball}"
+ repack_firmware_bundle "${shellball_dir}" "${new_shellball}"
+ sudo cp -f "${new_shellball}" "${firmware_bundle}"
+ sudo chmod a+rx "${firmware_bundle}"
+ # Unmount now to flush changes.
+ sudo umount "${rootfs_dir}"
+ info "Re-signed firmware AU payload in ${image}"
+}
+
+# Re-sign Android image if exists.
+resign_android_image_if_exists() {
+ local image=$1
+
+ local rootfs_dir=$(make_temp_dir)
+ mount_image_partition "${image}" 3 "${rootfs_dir}"
+
+ local system_img="${rootfs_dir}/opt/google/containers/android/system.raw.img"
+ local arc_version=$(grep CHROMEOS_ARC_VERSION= \
+ "${rootfs_dir}/etc/lsb-release" | cut -d= -f2)
+ if [[ ! -e "${system_img}" || -z "${arc_version}" ]]; then
+ info "ARC image not found. Not signing Android APKs."
+ sudo umount "${rootfs_dir}"
+ return
+ fi
+
+ "${SCRIPT_DIR}/sign_android_image.sh" "${rootfs_dir}" "${KEY_DIR}/android"
+
+ sudo umount "${rootfs_dir}"
+ info "Re-signed Android image"
+}
+
+# Sign an oci container with the given keys.
+# Args: CONTAINER KEY_DIR [OUTPUT_CONTAINER]
+sign_oci_container() {
+ local image=$1
+ local key_dir=$2
+ local output=$3
+
+ "${SCRIPT_DIR}/sign_oci_container.sh" \
+ "${image}" "${key_dir}" --output "${output}"
+}
+
+# Verify an image including rootfs hash using the specified keys.
+verify_image() {
+ local loopdev=$(loopback_partscan "${INPUT_IMAGE}")
+ local loop_rootfs="${loopdev}p3"
+
+ info "Verifying RootFS hash..."
+ # What we get from image.
+ local kernel_config
+ # What we calculate from the rootfs.
+ local new_kernel_config
+ # Depending on the type of image, the verity parameters may
+ # exist in either kernel partition 2 or kernel partition 4
+ local partnum
+ for partnum in 2 4; do
+ info "Considering Kernel partition ${partnum}"
+ kernel_config=$(sudo dump_kernel_config "${loopdev}p${partnum}")
+ local hash_image=$(make_temp_file)
+ if ! calculate_rootfs_hash "${loop_rootfs}" "${kernel_config}" \
+ "${hash_image}"; then
+ info "Trying next kernel partition."
+ continue
+ fi
+ new_kernel_config="$CALCULATED_KERNEL_CONFIG"
+ break
+ done
+
+ # Note: If calculate_rootfs_hash succeeded above, these should
+ # be non-empty.
+ expected_hash=$(get_hash_from_config "${new_kernel_config}")
+ got_hash=$(get_hash_from_config "${kernel_config}")
+
+ if [ -z "${expected_hash}" ] || [ -z "${got_hash}" ]; then
+ die "Couldn't verify RootFS hash on the image."
+ fi
+
+ if [ ! "${got_hash}" = "${expected_hash}" ]; then
+ cat </dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+ echo -n "With Recovery Key (Recovery Mode ON, Dev Mode ON): " && \
+ { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 3 >/dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+
+ try_key=${KEY_DIR}/kernel_subkey.vbpubk
+ # The SSD key is only used in non-recovery mode.
+ echo -n "With SSD Key (Recovery Mode OFF, Dev Mode OFF): " && \
+ { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 0 >/dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+ echo -n "With SSD Key (Recovery Mode OFF, Dev Mode ON): " && \
+ { load_kernel_test "${INPUT_IMAGE}" "${try_key}" -b 1 >/dev/null 2>&1 && \
+ echo "YES"; } || echo "NO"
+ set -e
+
+ verify_image_rootfs "${loop_rootfs}"
+
+ # TODO(gauravsh): Check embedded firmware AU signatures.
+}
+
+# Re-calculate recovery kernel hash.
+# Args: IMAGE_BIN
+update_recovery_kernel_hash() {
+ image_bin=$1
+
+ # Update the Kernel B hash in Kernel A command line
+ local old_kerna_config=$(grab_kernel_config "${image_bin}" 2)
+ local new_kernb=$(make_temp_file)
+ extract_image_partition ${image_bin} 4 ${new_kernb}
+ local new_kernb_hash=$(sha1sum ${new_kernb} | cut -f1 -d' ')
+
+ new_kerna_config=$(make_temp_file)
+ echo "$old_kerna_config" |
+ sed -e "s#\(kern_b_hash=\)[a-z0-9]*#\1${new_kernb_hash}#" \
+ > ${new_kerna_config}
+ info "New config for kernel partition 2 is"
+ cat ${new_kerna_config}
+
+ local temp_kimagea=$(make_temp_file)
+ extract_image_partition ${image_bin} 2 ${temp_kimagea}
+
+ # Re-calculate kernel partition signature and command line.
+ local updated_kimagea=$(make_temp_file)
+ vbutil_kernel --repack ${updated_kimagea} \
+ --keyblock ${KEY_DIR}/recovery_kernel.keyblock \
+ --signprivate ${KEY_DIR}/recovery_kernel_data_key.vbprivk \
+ --version "${KERNEL_VERSION}" \
+ --oldblob ${temp_kimagea} \
+ --config ${new_kerna_config}
+
+ replace_image_partition ${image_bin} 2 ${updated_kimagea}
+}
+
+# Update the legacy bootloader templates in EFI partition if available.
+# Args: IMAGE_BIN DM_PARTNO
+update_legacy_bootloader() {
+ local image="$1"
+ local dm_partno="$2"
+
+ local esp_partnum=12
+ local esp_offset=$(( $(partoffset "${image}" "${esp_partnum}") * 512 ))
+ # Check if the image has an ESP partition.
+ if [[ "${esp_offset}" == "0" ]]; then
+ info "Not updating legacy bootloader configs: ${image}"
+ return 0
+ fi
+
+ local esp_dir="$(make_temp_dir)"
+ # We use the 'unsafe' variant because the EFI system partition is vfat type
+ # and can be mounted in RW mode.
+ if ! _mount_image_partition_retry "${image}" "${esp_partnum}" \
+ "${esp_dir}"; then
+ error "Could not mount EFI partition for updating legacy bootloader cfg."
+ return 1
+ fi
+
+ # If we can't find the dm parameter in the kernel config, bail out now.
+ local kernel_config=$(grab_kernel_config "${image}" "${dm_partno}")
+ local root_hexdigest="$(get_hash_from_config "${kernel_config}")"
+ if [[ -z "${root_hexdigest}" ]]; then
+ error "Couldn't grab root_digest from kernel partition ${dm_partno}"
+ error " (config: ${kernel_config})"
+ return 1
+ fi
+ # Update syslinux configs for legacy BIOS systems.
+ if [[ -d "${esp_dir}/syslinux" ]]; then
+ local cfg=("${esp_dir}"/syslinux/*.cfg)
+ if ! sudo sed -i -r \
+ "s/\broot_hexdigest=[a-z0-9]+/root_hexdigest=${root_hexdigest}/g" \
+ "${cfg[@]}"; then
+ error "Updating syslinux configs failed: '${cfg[*]}'"
+ return 1
+ fi
+ fi
+ # Update grub configs for EFI systems.
+ local grub_cfg="${esp_dir}/efi/boot/grub.cfg"
+ if [[ -f "${grub_cfg}" ]]; then
+ if ! sudo sed -i -r \
+ "s/\broot_hexdigest=[a-z0-9]+/root_hexdigest=${root_hexdigest}/g" \
+ "${grub_cfg}"; then
+ error "Updating grub config failed: '${grub_cfg}'"
+ return 1
+ fi
+ fi
+}
+
+# Sign an image file with proper keys.
+# Args: IMAGE_TYPE INPUT OUTPUT DM_PARTNO KERN_A_KEYBLOCK KERN_A_PRIVKEY \
+# KERN_B_KEYBLOCK KERN_B_PRIVKEY
+#
+# A ChromiumOS image file (INPUT) always contains 2 partitions (kernel A & B).
+# This function will rebuild hash data by DM_PARTNO, resign kernel partitions by
+# their KEYBLOCK and PRIVKEY files, and then write to OUTPUT file. Note some
+# special images (specified by IMAGE_TYPE, like 'recovery' or 'factory_install')
+# may have additional steps (ex, tweaking verity hash or not stripping files)
+# when generating output file.
+sign_image_file() {
+ local image_type="$1"
+ local input="$2"
+ local output="$3"
+ local dm_partno="$4"
+ local kernA_keyblock="$5"
+ local kernA_privkey="$6"
+ local kernB_keyblock="$7"
+ local kernB_privkey="$8"
+
+ info "Preparing ${image_type} image..."
+ cp --sparse=always "${input}" "${output}"
+
+ local loopdev=$(loopback_partscan "${output}")
+ local loop_kern="${loopdev}p${dm_partno}"
+
+ resign_firmware_payload "${output}"
+ resign_android_image_if_exists "${output}"
+ # We do NOT strip /boot for factory installer, since some devices need it to
+ # boot EFI. crbug.com/260512 would obsolete this requirement.
+ #
+ # We also do NOT strip /boot for legacy BIOS or EFI devices. This is because
+ # "cros_installer postinst" on BIOS or EFI systems relies on presence of
+ # /boot in rootfs to update kernel. We infer the BIOS type from the kernel
+ # config.
+ local loop_kerna="${loopdev}p2"
+ local kerna_config="$(sudo dump_kernel_config "${loop_kerna}")"
+ if [[ "${image_type}" != "factory_install" &&
+ " ${kerna_config} " != *" cros_legacy "* &&
+ " ${kerna_config} " != *" cros_efi "* ]]; then
+ "${SCRIPT_DIR}/strip_boot_from_image.sh" --image "${output}"
+ fi
+ update_rootfs_hash "${output}" "${dm_partno}" \
+ "${kernA_keyblock}" "${kernA_privkey}" \
+ "${kernB_keyblock}" "${kernB_privkey}"
+ update_stateful_partition_vblock "${loopdev}"
+ if [[ "${image_type}" == "recovery" ]]; then
+ update_recovery_kernel_hash "${output}"
+ fi
+ if ! update_legacy_bootloader "${output}" "${dm_partno}"; then
+ # Error is already logged.
+ return 1
+ fi
+ info "Signed ${image_type} image output to ${output}"
+}
+
+# Verification
+case ${TYPE} in
+dump_config)
+ check_argc $# 2
+ for partnum in 2 4; do
+ info "kernel config in partition number ${partnum}:"
+ grab_kernel_config "${INPUT_IMAGE}" ${partnum}
+ echo
+ done
+ exit 0
+ ;;
+verify)
+ check_argc $# 2
+ verify_image
+ exit 0
+ ;;
+*)
+ # All other signing commands take 4 to 5 args.
+ if [ -z "${OUTPUT_IMAGE}" ]; then
+ # Friendlier message.
+ usage "Missing output image name"
+ fi
+ check_argc $# 4 5
+ ;;
+esac
+
+# If a version file was specified, read the firmware and kernel
+# versions from there.
+if [ -n "${VERSION_FILE}" ]; then
+ FIRMWARE_VERSION=$(sed -n 's#^firmware_version=\(.*\)#\1#pg' ${VERSION_FILE})
+ KERNEL_VERSION=$(sed -n 's#^kernel_version=\(.*\)#\1#pg' ${VERSION_FILE})
+fi
+info "Using firmware version: ${FIRMWARE_VERSION}"
+info "Using kernel version: ${KERNEL_VERSION}"
+
+# Make all modifications on output copy.
+if [[ "${TYPE}" == "ssd" || "${TYPE}" == "base" ]]; then
+ sign_image_file "SSD" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \
+ "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk" \
+ "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk"
+elif [[ "${TYPE}" == "usb" ]]; then
+ sign_image_file "USB" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \
+ "${KEY_DIR}/recovery_kernel.keyblock" \
+ "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \
+ "${KEY_DIR}/kernel.keyblock" \
+ "${KEY_DIR}/kernel_data_key.vbprivk"
+elif [[ "${TYPE}" == "recovery" ]]; then
+ sign_image_file "recovery" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 4 \
+ "${KEY_DIR}/recovery_kernel.keyblock" \
+ "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \
+ "${KEY_DIR}/kernel.keyblock" \
+ "${KEY_DIR}/kernel_data_key.vbprivk"
+elif [[ "${TYPE}" == "factory" ]] || [[ "${TYPE}" == "install" ]]; then
+ sign_image_file "factory_install" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \
+ "${KEY_DIR}/installer_kernel.keyblock" \
+ "${KEY_DIR}/installer_kernel_data_key.vbprivk" \
+ "${KEY_DIR}/kernel.keyblock" \
+ "${KEY_DIR}/kernel_data_key.vbprivk"
+elif [[ "${TYPE}" == "firmware" ]]; then
+ if [[ -e "${KEY_DIR}/loem.ini" ]]; then
+ die "LOEM signing not implemented yet for firmware images"
+ fi
+ cp ${INPUT_IMAGE} ${OUTPUT_IMAGE}
+ sign_firmware ${OUTPUT_IMAGE} ${KEY_DIR} ${FIRMWARE_VERSION}
+elif [[ "${TYPE}" == "nv_lp0_firmware" ]]; then
+ if [[ -e "${KEY_DIR}/loem.ini" ]]; then
+ die "LOEM signing not implemented yet for nv_lp0_firmware images"
+ fi
+ cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
+ sign_nv_lp0_firmware "${OUTPUT_IMAGE}" "${KEY_DIR}"
+elif [[ "${TYPE}" == "kernel" ]]; then
+ if [[ -e "${KEY_DIR}/loem.ini" ]]; then
+ die "LOEM signing not implemented yet for kernel images"
+ fi
+ cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
+ sign_kernel "${OUTPUT_IMAGE}" "${KEY_DIR}" "${KERNEL_VERSION}"
+elif [[ "${TYPE}" == "recovery_kernel" ]]; then
+ if [[ -e "${KEY_DIR}/loem.ini" ]]; then
+ die "LOEM signing not implemented yet for recovery_kernel images"
+ fi
+ cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
+ sign_recovery_kernel "${OUTPUT_IMAGE}" "${KEY_DIR}" "${KERNEL_VERSION}"
+elif [[ "${TYPE}" == "update_payload" ]]; then
+ sign_update_payload ${INPUT_IMAGE} ${KEY_DIR} ${OUTPUT_IMAGE}
+elif [[ "${TYPE}" == "accessory_usbpd" ]]; then
+ KEY_NAME="${KEY_DIR}/key_$(basename $(dirname ${INPUT_IMAGE}))"
+ if [[ ! -e "${KEY_NAME}.pem" ]]; then
+ KEY_NAME="${KEY_DIR}/key"
+ fi
+ cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
+ futility sign --type usbpd1 --pem "${KEY_NAME}.pem" "${OUTPUT_IMAGE}"
+elif [[ "${TYPE}" == "accessory_rwsig" ]]; then
+ KEY_NAME="${KEY_DIR}/key_$(basename $(dirname ${INPUT_IMAGE}))"
+ if [[ ! -e "${KEY_NAME}.vbprik2" ]]; then
+ KEY_NAME="${KEY_DIR}/key"
+ fi
+ cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}"
+ futility sign --type rwsig --prikey "${KEY_NAME}.vbprik2" "${OUTPUT_IMAGE}"
+elif [[ "${TYPE}" == "oci-container" ]]; then
+ sign_oci_container "${INPUT_IMAGE}" "${KEY_DIR}" "${OUTPUT_IMAGE}"
+else
+ die "Invalid type ${TYPE}"
+fi
diff --git a/nichrome/scripts/vboot/bin/strip_boot_from_image.sh b/nichrome/scripts/vboot/bin/strip_boot_from_image.sh
new file mode 100755
index 000000000..5e650af66
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/strip_boot_from_image.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to remove /boot directory from an image.
+
+# Load common constants. This should be the first executable line.
+# The path to common.sh should be relative to your script's location.
+. "$(dirname "$0")/common.sh"
+
+load_shflags
+
+DEFINE_string image "chromiumos_image.bin" \
+ "Input file name of Chrome OS image to strip /boot from."
+
+# Parse command line.
+FLAGS "$@" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+# Abort on error.
+set -e
+
+if [ -z "${FLAGS_image}" ] || [ ! -s "${FLAGS_image}" ] ; then
+ die "Error: need a valid file by --image"
+fi
+
+# Swiped/modifed from $SRC/src/scripts/base_library/base_image_util.sh.
+zero_free_space() {
+ local rootfs="$1"
+
+ info "Zeroing freespace in ${rootfs}"
+ # dd is a silly thing and will produce a "No space left on device" message
+ # that cannot be turned off and is confusing to unsuspecting victims.
+ ( sudo dd if=/dev/zero of="${rootfs}/filler" bs=4096 conv=fdatasync \
+ status=noxfer || true ) 2>&1 | grep -v "No space left on device"
+ sudo rm "${rootfs}/filler"
+}
+
+
+strip_boot() {
+ local image=$1
+
+ # Mount image so we can modify it.
+ local rootfs_dir=$(make_temp_dir)
+ mount_image_partition ${image} 3 ${rootfs_dir}
+
+ sudo rm -rf "${rootfs_dir}/boot" &&
+ info "/boot directory was removed."
+
+ # To prevent the files we just removed from the FS from remaining as non-
+ # zero trash blocks that bloat payload sizes, need to zero them. This was
+ # done when the image was built, but needs to be repeated now that we've
+ # modified it in a non-trivial way.
+ zero_free_space "${rootfs_dir}"
+}
+
+
+IMAGE=$(readlink -f "${FLAGS_image}")
+if [[ -z "${IMAGE}" || ! -f "${IMAGE}" ]]; then
+ die "Missing required argument: --from (image to update)"
+fi
+
+strip_boot "${IMAGE}"
diff --git a/nichrome/scripts/vboot/bin/tag_image.sh b/nichrome/scripts/vboot/bin/tag_image.sh
new file mode 100755
index 000000000..5aa6dbf36
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/tag_image.sh
@@ -0,0 +1,230 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to manipulate the tag files in the output of build_image
+
+# Load common constants. This should be the first executable line.
+# The path to common.sh should be relative to your script's location.
+. "$(dirname "$0")/common.sh"
+
+load_shflags
+
+DEFINE_string from "chromiumos_image.bin" \
+ "Input file name of Chrome OS image to tag/stamp."
+DEFINE_string dev_mode "" \
+ "(build-info) Tag as a developer mode build (1 to enable, 0 to disable)"
+DEFINE_string update_firmware "" \
+ "(auto-update) Force updating firmware (1 to enable, 0 to disable)"
+DEFINE_string leave_firmware_alone "" \
+ "(auto-update) For BIOS development use ONLY (1 to enable, 0 to disable)"
+DEFINE_string leave_core "" \
+ "(crash-reporter) Leave core dumps (1 to enable, 0 to disable)"
+DEFINE_string crosh_workarounds "" \
+ "(crosh) Keep crosh (1 to keep, 0 to disable *irreversible*)"
+
+# Parameters for manipulating /etc/lsb-release.
+DEFINE_boolean remove_test_label false \
+ "(build-info) Remove 'test' suffix in /etc/lsb-release"
+DEFINE_boolean change_dev_to_beta false \
+ "(build-info) Change 'dev' -> 'beta' in /etc/lsb-release"
+
+
+# TODO(hungte) we can add factory_installer and factory_test,
+# but I don't see any reason to tweak/check these values.
+
+# Parse command line.
+FLAGS "$@" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+# Abort on error.
+set -e
+
+if [ -z "${FLAGS_from}" ] || [ ! -s "${FLAGS_from}" ] ; then
+ echo "Error: need a valid file by --from"
+ exit 1
+fi
+
+# Global variable to track if the image is modified.
+g_modified=${FLAGS_FALSE}
+
+# Processes (enable, disable, or simply report) a tag file.
+# Args: DO_MODIFICATION NAME ROOT TAG_FILE ACTION
+#
+# When DO_MODIFICATION=${FLAGS_TRUE},
+# Creates (ACTION=1) the TAG_FILE in ROOT, or
+# removes (ACTION=0) the TAG_FILE in ROOT, then
+# reports the status (and change) to the tag file.
+# When DO_MODIFICATION=${FLAGS_FALSE},
+# make a dry-run and only change ${g_modified}
+function process_tag() {
+ local tag_status_text=""
+ local do_modification="$1"
+ local name="$2"
+ local root="$3"
+ local tag_file_path="$3/$4"
+ local action="$5"
+ local do_enable=${FLAGS_FALSE}
+ local do_disable=${FLAGS_FALSE}
+
+ # only 1, 0, and "" are valid params to action.
+ case "${action}" in
+ "1" )
+ do_enable=${FLAGS_TRUE}
+ ;;
+ "0" )
+ do_disable=${FLAGS_TRUE}
+ ;;
+ "" )
+ ;;
+ * )
+ echo "Error: invalid param to ${name}: ${action} (must be 1 or 0)."
+ exit 1
+ ;;
+ esac
+
+ if [ -f "${tag_file_path}" ]; then
+ tag_status_text="ENABLED"
+ if [ "${do_disable}" = ${FLAGS_TRUE} ]; then
+ # disable the tag
+ if [ "${do_modification}" = ${FLAGS_TRUE} ]; then
+ sudo rm "${tag_file_path}"
+ fi
+ g_modified=${FLAGS_TRUE}
+ tag_status_text="${tag_status_text} => disabled"
+ elif [ "${do_disable}" != ${FLAGS_FALSE} ]; then
+ # internal error
+ echo "Internal error for tag ${name}: need disable param." 1>&2
+ exit 1
+ fi
+ else
+ tag_status_text="disabled"
+ if [ "${do_enable}" = ${FLAGS_TRUE} ]; then
+ # enable the tag
+ if [ "${do_modification}" = ${FLAGS_TRUE} ]; then
+ sudo touch "${tag_file_path}"
+ fi
+ g_modified=${FLAGS_TRUE}
+ tag_status_text="${tag_status_text} => ENABLED"
+ elif [ "${do_enable}" != ${FLAGS_FALSE} ]; then
+ # internal error
+ echo "Internal error for tag ${name}: need enable param." 1>&2
+ exit 1
+ fi
+ fi
+
+ # report tag status
+ if [ "${do_modification}" != ${FLAGS_TRUE} ]; then
+ echo "${name}: ${tag_status_text}"
+ fi
+}
+
+# Iterates all tags to a given partition root.
+# Args: ROOTFS DO_MODIFICATION
+#
+# Check process_tag for the meaning of parameters.
+process_all_tags() {
+ local rootfs="$1"
+ local do_modification="$2"
+
+ process_tag "${do_modification}" \
+ "(build-info) dev_mode" \
+ "${rootfs}" \
+ /root/.dev_mode \
+ "${FLAGS_dev_mode}"
+
+ process_tag "${do_modification}" \
+ "(auto-update) update_firmware" \
+ "${rootfs}" \
+ /root/.force_update_firmware \
+ "${FLAGS_update_firmware}"
+
+ process_tag "${do_modification}" \
+ "(auto-update) leave_firmware_alone" \
+ "${rootfs}" \
+ /root/.leave_firmware_alone \
+ "${FLAGS_leave_firmware_alone}"
+
+ process_tag "${do_modification}" \
+ "(crash-reporter) leave_core" \
+ "${rootfs}" \
+ /root/.leave_core \
+ "${FLAGS_leave_core}"
+
+ process_tag "${do_modification}" \
+ "(crosh) crosh_workarounds" \
+ "${rootfs}" \
+ /usr/bin/crosh-workarounds \
+ "${FLAGS_crosh_workarounds}"
+}
+
+# Iterates through all options for manipulating the lsb-release.
+# Args: ROOTFS DO_MODIFICATION
+process_all_lsb_mods() {
+ local rootfs="$1"
+ local do_modifications="$2"
+ local lsb="${rootfs}/etc/lsb-release"
+ local sudo
+
+ if [ ! -w "${lsb}" ]; then
+ sudo="sudo"
+ fi
+
+ if [ ${FLAGS_remove_test_label} = ${FLAGS_TRUE} ]; then
+ if grep -wq "test" "${lsb}"; then
+ g_modified=${FLAGS_TRUE}
+ fi
+ if [ ${do_modifications} = ${FLAGS_TRUE} ]; then
+ ${sudo} sed -i 's/\btest\b//' "${lsb}" &&
+ echo "Test Label removed from /etc/lsb-release"
+ fi
+ fi
+
+ if [ ${FLAGS_change_dev_to_beta} = ${FLAGS_TRUE} ]; then
+ if grep -wq "dev" "${lsb}"; then
+ g_modified=${FLAGS_TRUE}
+ fi
+ if [ ${do_modifications} = ${FLAGS_TRUE} ]; then
+ ${sudo} sed -i 's/\bdev\b/beta/' "${lsb}" &&
+ echo "Dev Channel Label was changed to Beta"
+ fi
+ fi
+}
+
+
+IMAGE=$(readlink -f "${FLAGS_from}")
+if [[ -z "${IMAGE}" || ! -f "${IMAGE}" ]]; then
+ echo "Missing required argument: --from (image to update)"
+ usage
+ exit 1
+fi
+
+# First round, mount as read-only and check if we need any modifications.
+rootfs=$(make_temp_dir)
+mount_image_partition_ro "${IMAGE}" 3 "${rootfs}"
+
+# we don't have tags in stateful partition yet...
+# stateful_dir=$(make_temp_dir)
+# mount_image_partition ${IMAGE} 1 ${stateful_dir}
+
+process_all_tags "${rootfs}" ${FLAGS_FALSE}
+process_all_lsb_mods "${rootfs}" ${FLAGS_FALSE}
+
+if [ ${g_modified} = ${FLAGS_TRUE} ]; then
+ # remount as RW (we can't use mount -o rw,remount because of loop device)
+ sudo umount "${rootfs}"
+ mount_image_partition "${IMAGE}" 3 "${rootfs}"
+
+ # second round, apply the modification to image.
+ process_all_tags "${rootfs}" ${FLAGS_TRUE}
+ process_all_lsb_mods "${rootfs}" ${FLAGS_TRUE}
+
+ # this is supposed to be automatically done in mount_image_partition,
+ # but it's no harm to explicitly make it again here.
+ tag_as_needs_to_be_resigned "${rootfs}"
+ echo "IMAGE IS MODIFIED. PLEASE REMEMBER TO RESIGN YOUR IMAGE."
+else
+ echo "Image is not modified."
+fi
diff --git a/nichrome/scripts/vboot/bin/tofactory.sh b/nichrome/scripts/vboot/bin/tofactory.sh
new file mode 100755
index 000000000..1871c384e
--- /dev/null
+++ b/nichrome/scripts/vboot/bin/tofactory.sh
@@ -0,0 +1,185 @@
+#!/bin/sh
+#
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This script converts a Chrome OS device to a pre-factory-install state:
+# * Firmware write protect disabled
+# * H2O BIOS, with RO VPD area copied from the current BIOS
+# * Original EC firmware
+# * Blank SSD (no GPT)
+#
+# Minimal usage:
+# tofactory.sh -b H2OBIOS.bin -e ec_shellball.sh
+
+SCRIPT_BASE="$(dirname "$0")"
+. "$SCRIPT_BASE/common_minimal.sh"
+load_shflags || exit 1
+
+# Constants used by DEFINE_*
+VBOOT_BASE='/usr/share/vboot'
+
+# DEFINE_string name default_value description flag
+DEFINE_string bios "" "Path of system firmware (BIOS) binary to write" "b"
+DEFINE_string ec "" "Path of EC shellball to execute" "e"
+DEFINE_string backup_dir "" "Path of directory in whoch to store backups" "k"
+DEFINE_string asset_tag "unspecified_tag" \
+ "Asset tag of device, used to name backups" "a"
+DEFINE_string ssd "/dev/sda" "Path to SSD / target drive" "s"
+DEFINE_boolean wipe_ssd $FLAGS_TRUE "Wipe SSD after firmware updates" ""
+DEFINE_boolean nothing $FLAGS_FALSE \
+ "Print commands but do not modify device" "n"
+
+# Parse command line
+FLAGS "$@" || exit 1
+eval set -- "$FLAGS_ARGV"
+
+# Globals
+# ----------------------------------------------------------------------------
+set -e
+
+# Flashrom commands with device overrides
+FLASHROM_BIOS="flashrom -p host"
+FLASHROM_EC="flashrom -p ec"
+
+# A log file to keep the output results of executed command
+EXEC_LOG="$(make_temp_file)"
+
+# Temporary Work directory
+WORK_DIR="$(make_temp_dir)"
+OLD_BIOS="$WORK_DIR/old_bios.bin"
+NEW_BIOS="$WORK_DIR/new_bios.bin"
+
+# Functions
+# ----------------------------------------------------------------------------
+
+# Error message for write protect disable failure, with reminder
+wp_error() {
+ local which_rom=$1
+ shift
+ echo "ERROR: Unable to disable $which_rom write protect: $*" 1>&2
+ echo "Is hardware write protect still enabled?" 1>&2
+ exit 1
+}
+
+# Disable write protect for an EEPROM
+disable_wp() {
+ local which_rom=$1 # EC or BIOS
+ shift
+ local flash_rom="$*" # Flashrom command to use
+
+ debug_msg "Disabling $which_rom write protect"
+ $NOTHING ${flash_rom} --wp-disable || wp_error "$which_rom" "--wp-disable"
+ $NOTHING ${flash_rom} --wp-range 0 0 || wp_error "$which_rom" "--wp-range"
+
+ # WP status bits should report WP: status: 0x00
+ local wp_status="$(${flash_rom} --wp-status | grep "WP: status:")"
+ if [ "$wp_status" != "WP: status: 0x00" ]; then
+ if [ "$FLAGS_nothing" = $FLAGS_FALSE ]; then
+ wp_error "$which_rom" "$wp_status"
+ fi
+ fi
+}
+
+# Back up current firmware and partition table
+make_backups() {
+ debug_msg "Backing up current firmware to $FLAGS_backup_dir"
+ mkdir -p "$FLAGS_backup_dir"
+ cp "$OLD_BIOS" "$FLAGS_backup_dir/$FLAGS_asset_tag.bios.bin"
+ ${FLASHROM_EC} -r "$FLAGS_backup_dir/$FLAGS_asset_tag.ec.bin"
+
+ # Copy the VPD info from RAM, since we can't extract it as text
+ # from the BIOS binary. Failure of this is only a warning, since
+ # the information is still in the old BIOS.
+ mosys vpd print all > "$FLAGS_backup_dir/$FLAGS_asset_tag.vpd.txt" ||
+ echo "WARNING: unable to save VPD as text."
+
+ # Copy the first part of the drive, so we can recreate the partition
+ # table.
+ local gpt_backup="$FLAGS_backup_dir/$FLAGS_asset_tag.gpt.bin"
+ debug_msg "Backing up current GPT table."
+ dd if="$FLAGS_ssd" of="$gpt_backup" bs=512 count=34
+
+ # Add a script to restore the BIOS and GPT
+ local restore_script="$FLAGS_backup_dir/$FLAGS_asset_tag.restore.sh"
+ cat >"$restore_script" </dev/null || \
+ { echo "mosys tool not found."; exit 1; }
+
+src_fd=$1
+
+# Grab GBB Area offset and size
+match_str="GBB Area"
+line=$(mosys -f -k eeprom map $1 | grep "$match_str")
+offset="$(echo $line | sed -e 's/.*area_offset=\"\([a-f0-9x]*\)\".*/\1/')"
+let gbb_offset="$offset"
+size="$(echo $line | sed -e 's/.*area_size=\"\([a-f0-9x]*\)\".*/\1/')"
+let gbb_size="$size"
+
+# Grab Firmware A and B offset and size
+for i in "A" "B"
+do
+ match_str="$i Key"
+ line=$(mosys -f -k eeprom map $1 | grep "$match_str")
+ offset="$(echo $line | sed -e 's/.*area_offset=\"\([a-f0-9x]*\)\".*/\1/')"
+ eval let \
+ fw${i}_vblock_offset="$offset"
+ size="$(echo $line | sed -e 's/.*area_size=\"\([a-f0-9x]*\)\".*/\1/')"
+ eval let \
+ fw${i}_vblock_size="$size"
+
+ match_str="$i Data"
+ line=$(mosys -f -k eeprom map $1 | grep "$match_str")
+ offset="$(echo $line | sed -e 's/.*area_offset=\"\([a-f0-9x]*\)\".*/\1/')"
+ eval let \
+ fw${i}_offset="$offset"
+ size="$(echo $line | sed -e 's/.*area_size=\"\([a-f0-9x]*\)\".*/\1/')"
+ eval let \
+ fw${i}_size="$size"
+done
+
+echo "Extracting GBB"
+dd if="${src_fd}" of="firmware.gbb" skip="${gbb_offset}" bs=1 \
+ count="${gbb_size}"
+echo "Extracting Firmware data and vblock(s)"
+dd if="${src_fd}" of="firmwareA.data" skip="${fwA_offset}" bs=1 \
+ count="${fwA_size}"
+dd if="${src_fd}" of="firmwareA.vblock" skip="${fwA_vblock_offset}" bs=1 \
+ count="${fwA_vblock_size}"
+dd if="${src_fd}" of="firmwareB.data" skip="${fwB_offset}" bs=1 \
+ count="${fwB_size}"
+dd if="${src_fd}" of="firmwareB.vblock" skip="${fwB_vblock_offset}" bs=1 \
+ count="${fwB_vblock_size}"
diff --git a/nichrome/scripts/vboot/devkeys/cros-oci-container-pub.pem b/nichrome/scripts/vboot/devkeys/cros-oci-container-pub.pem
new file mode 100644
index 000000000..ac433a1de
--- /dev/null
+++ b/nichrome/scripts/vboot/devkeys/cros-oci-container-pub.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzDOi7z2ltATFnJnBU+Tb7TSkdTVE
+X2c12jDUzvhAA4EVtcbj4jph02YrzULzHzCmo8FjR0puYqmbOEkQA+JLzA==
+-----END PUBLIC KEY-----
diff --git a/nichrome/scripts/vboot/devkeys/cros-oci-container.pem b/nichrome/scripts/vboot/devkeys/cros-oci-container.pem
new file mode 100644
index 000000000..1c6992c9f
--- /dev/null
+++ b/nichrome/scripts/vboot/devkeys/cros-oci-container.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEICVrXoiL33vHU0clsTBn/XenWILpkvSFkL+x/Uczzvb9oAoGCCqGSM49
+AwEHoUQDQgAEzDOi7z2ltATFnJnBU+Tb7TSkdTVEX2c12jDUzvhAA4EVtcbj4jph
+02YrzULzHzCmo8FjR0puYqmbOEkQA+JLzA==
+-----END EC PRIVATE KEY-----
diff --git a/nichrome/scripts/vboot/devkeys/ec.keyblock b/nichrome/scripts/vboot/devkeys/ec.keyblock
new file mode 100644
index 000000000..6b088f325
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/ec.keyblock differ
diff --git a/nichrome/scripts/vboot/devkeys/ec_data_key.vbprivk b/nichrome/scripts/vboot/devkeys/ec_data_key.vbprivk
new file mode 100644
index 000000000..9f194ce9b
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/ec_data_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/ec_data_key.vbpubk b/nichrome/scripts/vboot/devkeys/ec_data_key.vbpubk
new file mode 100644
index 000000000..5804dfd61
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/ec_data_key.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/ec_root_key.vbprivk b/nichrome/scripts/vboot/devkeys/ec_root_key.vbprivk
new file mode 100644
index 000000000..491447208
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/ec_root_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/ec_root_key.vbpubk b/nichrome/scripts/vboot/devkeys/ec_root_key.vbpubk
new file mode 100644
index 000000000..76c26f94a
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/ec_root_key.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/firmware.keyblock b/nichrome/scripts/vboot/devkeys/firmware.keyblock
new file mode 100644
index 000000000..1e2273e54
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/firmware.keyblock differ
diff --git a/nichrome/scripts/vboot/devkeys/firmware_bmpfv.bin b/nichrome/scripts/vboot/devkeys/firmware_bmpfv.bin
new file mode 100644
index 000000000..3e9af9760
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/firmware_bmpfv.bin differ
diff --git a/nichrome/scripts/vboot/devkeys/firmware_data_key.vbprivk b/nichrome/scripts/vboot/devkeys/firmware_data_key.vbprivk
new file mode 100644
index 000000000..49e57513f
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/firmware_data_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/firmware_data_key.vbpubk b/nichrome/scripts/vboot/devkeys/firmware_data_key.vbpubk
new file mode 100644
index 000000000..804d566cb
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/firmware_data_key.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/installer_kernel.keyblock b/nichrome/scripts/vboot/devkeys/installer_kernel.keyblock
new file mode 100644
index 000000000..cfa3bd187
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/installer_kernel.keyblock differ
diff --git a/nichrome/scripts/vboot/devkeys/installer_kernel_data_key.vbprivk b/nichrome/scripts/vboot/devkeys/installer_kernel_data_key.vbprivk
new file mode 100644
index 000000000..037959520
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/installer_kernel_data_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/installer_kernel_data_key.vbpubk b/nichrome/scripts/vboot/devkeys/installer_kernel_data_key.vbpubk
new file mode 100644
index 000000000..3e9e67c5c
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/installer_kernel_data_key.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/kernel.keyblock b/nichrome/scripts/vboot/devkeys/kernel.keyblock
new file mode 100644
index 000000000..9740be4e6
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/kernel.keyblock differ
diff --git a/nichrome/scripts/vboot/devkeys/kernel_data_key.vbprivk b/nichrome/scripts/vboot/devkeys/kernel_data_key.vbprivk
new file mode 100644
index 000000000..8d392fb29
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/kernel_data_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/kernel_data_key.vbpubk b/nichrome/scripts/vboot/devkeys/kernel_data_key.vbpubk
new file mode 100644
index 000000000..80910b77c
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/kernel_data_key.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/kernel_subkey.vbprivk b/nichrome/scripts/vboot/devkeys/kernel_subkey.vbprivk
new file mode 100644
index 000000000..195b1bf5b
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/kernel_subkey.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/kernel_subkey.vbpubk b/nichrome/scripts/vboot/devkeys/kernel_subkey.vbpubk
new file mode 100644
index 000000000..a24a036d1
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/kernel_subkey.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/key.versions b/nichrome/scripts/vboot/devkeys/key.versions
new file mode 100644
index 000000000..59d8748eb
--- /dev/null
+++ b/nichrome/scripts/vboot/devkeys/key.versions
@@ -0,0 +1,4 @@
+firmware_key_version=1
+firmware_version=1
+kernel_key_version=1
+kernel_version=1
diff --git a/nichrome/scripts/vboot/devkeys/recovery_kernel.keyblock b/nichrome/scripts/vboot/devkeys/recovery_kernel.keyblock
new file mode 100644
index 000000000..ad16e3997
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/recovery_kernel.keyblock differ
diff --git a/nichrome/scripts/vboot/devkeys/recovery_kernel_data_key.vbprivk b/nichrome/scripts/vboot/devkeys/recovery_kernel_data_key.vbprivk
new file mode 100644
index 000000000..037959520
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/recovery_kernel_data_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/recovery_kernel_data_key.vbpubk b/nichrome/scripts/vboot/devkeys/recovery_kernel_data_key.vbpubk
new file mode 100644
index 000000000..3e9e67c5c
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/recovery_kernel_data_key.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/recovery_key.vbprivk b/nichrome/scripts/vboot/devkeys/recovery_key.vbprivk
new file mode 100644
index 000000000..6c7ab3630
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/recovery_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/recovery_key.vbpubk b/nichrome/scripts/vboot/devkeys/recovery_key.vbpubk
new file mode 100644
index 000000000..86d2471a0
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/recovery_key.vbpubk differ
diff --git a/nichrome/scripts/vboot/devkeys/root_key.vbprivk b/nichrome/scripts/vboot/devkeys/root_key.vbprivk
new file mode 100644
index 000000000..74c47dd78
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/root_key.vbprivk differ
diff --git a/nichrome/scripts/vboot/devkeys/root_key.vbpubk b/nichrome/scripts/vboot/devkeys/root_key.vbpubk
new file mode 100644
index 000000000..dfca9d054
Binary files /dev/null and b/nichrome/scripts/vboot/devkeys/root_key.vbpubk differ
diff --git a/nichrome/sound_progress.md b/nichrome/sound_progress.md
new file mode 100644
index 000000000..1fad838cd
--- /dev/null
+++ b/nichrome/sound_progress.md
@@ -0,0 +1,113 @@
+## Sound Progress (or lack thereof)
+### What We've Done
+#### Build kernel with sound and PWM drivers:
+
+Enable Device Drivers > Sound card support > ALSA
+
+in ALSA panel of kernel configuration, enable:
+
+* Sequencer support
+* Sequencer dummy client
+* PCM timer interface
+* HR-timer backend support
+* Use HR-timer as default sequencer timer
+* Dynamic device file minor numbers
+* Support old ALSA API
+* Sound Proc FS Support
+* Verbose procfs contents
+* Generic sound devices
+* PCI sound devices
+
+ * Enable all Intel drivers
+* HD-Audio
+
+ * Enable all options
+* SPI sound devices
+* USB sound devices
+* PCMCIA sound devices
+* ALSA for SoC audio support
+
+ * Enable all Intel Cherrytrail & Braswell drivers
+ * Enable all SKL drivers
+
+Enable Device Drivers > Pulse-Width Modulation > ChromeOS EC PWM driver
+
+
+*This kernel may include many unnecessary drivers, or be missing something important. We're not sure.*
+
+#### Use TinyCore to install ALSA packages:
+After connecting to the internet in Nichrome:
+
+`tcz -i -skip alsa-modules-KERNEL alsa alsa-config alsa-plugins`
+
+*this gives us access to aplay, alsamixer, speaker-test, etc*
+
+`aplay -l` has shown us most of the Chromebooks we have looked at (3 total) have 5 HDMI audio devices. `alsamixer` shows 5 S/PDIF digital outputs locked at 00, and (depending on the machine) a functioning PCM slider. Digital out usually does not mean output to speakers, which makes me think it has something to do with CRAS.
+
+#### Make "staff" group:
+`godit /etc/group`, writing `staff::1:root,user` to that file. This is just to appease `speaker-test`, which requires a group named "staff" to run.
+
+#### Make ALSA config file:
+`godit /etc/asound.conf` and write the following:
+```
+pcm.!default {
+ type hw
+ card 0
+ device 3
+}
+```
+
+As seen using `aplay -l`, the five HDMI outputs are listed as devices 3, 7, 8, 9, and 10. We've arbitrarily chosen 3 as the default device.
+
+At this point, `speaker-test` will force you to run with output to 2 channels, `-c 2`. Everything seems good to go, speaker-test outputs sound to the default audio device as configured in /etc/asound.conf, but no sound comes out of any speakers. This is where we are stuck.
+
+### Ideas
+
+* Lots of ALSA documentation (for other Linux distros) heavily refers to modular kernels. Making the ALSA drivers modular may be a possible solution. Pulling the config from Chrome OS is a good way to see what's enabled/disabled/modular when it comes to sound.
+
+* Relying on TinyCore's ALSA implementation may be a bad idea. It seems that many ALSA configurations are pretty kernel/device specific. We could build the ALSA tools ourselves and add them to Nichrome manually, rather than using TinyCore's version of ALSA.
+
+* Chrome OS uses it's own audio server (CRAS) to interface with ALSA and do most of the dirty work. This may be why ALSA's only listed outputs are digital. In that case, we might need to pull in CRAS as well.
+
+### Websites
+
+ALSA: http://www.alsa-project.org/main/index.php/Main_Page
+
+asound.conf format: http://www.alsa-project.org/main/index.php/Asoundrc
+
+In-depth ALSA config: https://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture
+
+TinyCore Packages: http://tinycorelinux.net/9.x/x86_64/tcz/
+
+CRAS source: https://chromium.googlesource.com/chromiumos/third_party/adhd/+/master/cras
+
+### Other helpful things
+
+#### Getting ChromeOS kernel configuration file:
+ 1. boot into ChromeOS in developer mode
+ 2. open VT2 and run:
+ ```
+ modprobe configs
+ cat /proc/config.gz > path/to/save/config
+ ```
+
+From here, you can copy this file to Google Drive/USB stick and open it using the kernel config tools on your build machine.
+
+#### Saving NiChrome ALSA data:
+Since Nichrome isn't stateful yet, you can use the stateful partition on your chromebook to backup your modifications to etc and tcz.
+
+to backup:
+```
+mkdir mnt
+mount -t ext4 /dev/mmcblk*p1 /mnt
+cp -r /etc /mnt
+cp -r /tcz /mnt
+```
+to reload after a restart:
+```
+mkdir mnt
+mount -t ext4 /dev/mmcblk*p1 /mnt
+cp -r /mnt/etc /
+cp -r /mnt/tcz /
+tcz -i alsa alsa-config alsa-plugins`
+```
diff --git a/nichrome/travis.sh b/nichrome/travis.sh
new file mode 100755
index 000000000..545f30095
--- /dev/null
+++ b/nichrome/travis.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+if [ -z "${GOPATH}" ]; then
+ export GOPATH=/home/travis/gopath
+fi
+set -e
+
+#echo "Check vendored dependencies"
+#(dep status)
+
+(cd usb && go build .)
+./usb/usb --apt=true --fetch=true --dev=/dev/null
+
+# in case of emergency break glass
+# cpio -ivt < initramfs.linux_amd64.cpio
+# cpio -ivt < linux-stabld/initramfs.linux_amd64.cpio
diff --git a/nichrome/usb/tczlist.go b/nichrome/usb/tczlist.go
new file mode 100644
index 000000000..8c6082985
--- /dev/null
+++ b/nichrome/usb/tczlist.go
@@ -0,0 +1,50 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.11
+
+package main
+
+var (
+ // Note the -skip needs to be first
+ tczList = []string{
+ "-skip", "graphics-KERNEL alsa-modules-KERNEL wireless-KERNEL",
+ "alsa", "alsa-config", "alsa-plugins",
+ "aterm",
+ "bash",
+ "strace",
+ "freetype",
+ "glib2",
+ "harfbuzz",
+ "imlib2-bin",
+ "imlib2",
+ "libffi",
+ "libfontenc",
+ "libICE",
+ "libjpeg-turbo",
+ "libpng",
+ "libSM",
+ "libX11",
+ "libXau",
+ "libxcb",
+ "libXdmcp",
+ "libXext",
+ "libXfont",
+ "libXi",
+ "libXmu",
+ "libXpm",
+ "libXrandr",
+ "libXrender",
+ "libXt",
+ "pcre",
+ "wbar",
+ "Xfbdev",
+ "xf86-video-intel",
+ "Xlibs",
+ "Xorg-fonts",
+ "Xprogs",
+ "Xorg-7.7",
+ "wifi",
+ }
+)
diff --git a/nichrome/usb/urootlist.go b/nichrome/usb/urootlist.go
new file mode 100644
index 000000000..9c9646716
--- /dev/null
+++ b/nichrome/usb/urootlist.go
@@ -0,0 +1,25 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.11
+
+package main
+
+var (
+ staticCmdList = []string{
+ "./cmds/install",
+ "./cmds/uinit",
+ }
+ dynamicCmdList = append(staticCmdList, []string{
+ "./cmds/install",
+ "./cmds/uinit",
+ /*
+ "../wingo",
+ "github.com/nsf/godit",
+ "upspin.io/cmd/upspin",
+ "upspin.io/cmd/upspinfs"}...
+ */
+ }...
+ )
+)
diff --git a/nichrome/usb/usb.go b/nichrome/usb/usb.go
new file mode 100644
index 000000000..9b2cf1a0f
--- /dev/null
+++ b/nichrome/usb/usb.go
@@ -0,0 +1,506 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.11
+
+package main
+
+//include a loading bar
+//TODO proper output channels when you run commands
+//TODO in the newest kernel pull the stable one if it fails, then go back to what was there, see the notes on the PR)
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ flag "github.com/spf13/pflag"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "os/exec"
+ "os/user"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+ "syscall"
+
+ "github.com/u-root/u-root/pkg/mount/gpt"
+)
+
+const initramfs = "initramfs.linux_amd64.cpio"
+
+var (
+ configTxt = `loglevel=1
+ init=/init
+rootwait
+`
+ apt = flag.Bool("apt", true, "apt-get all the things we need")
+ fetch = flag.Bool("fetch", false, "Fetch all the things we need")
+ skiproot = flag.Bool("skiproot", false, "Don't put the root onto usb")
+ skipkern = flag.Bool("skipkern", false, "Don't put the kern onto usb")
+ keys = flag.String("keys", "vboot/tests/devkeys", "where the keys live")
+ dev = flag.String("dev", "/dev/null", "What device to use")
+ config = flag.String("config", "CONFIG", "Linux config file")
+ extra = flag.String("extra", "", "Comma-separated list of extra packages to include")
+ kernDev string
+ rootDev string
+ kernPart = 2
+
+ kernelVersion = "v5.10"
+ workingDir = ""
+ linuxVersion = "linux-stable"
+ homeDir = ""
+ packageList = []string{
+ "bc",
+ "git",
+ "golang",
+ "build-essential",
+ "git-core",
+ "subversion",
+ "curl",
+ "python2.7",
+ "libyaml-dev",
+ "liblzma-dev",
+ "uuid-dev",
+ "libssl-dev",
+ }
+ optional = map[string]bool{
+ ".ssh": true,
+ "upspin": true,
+ "etc": true,
+ }
+ threads = runtime.NumCPU() + 2 // Number of threads to use when calling make.
+)
+
+func cp(inputLoc string, outputLoc string) error {
+ // Don't check for an error, there are all kinds of
+ // reasons a remove can fail even if the file is
+ // writeable
+ os.Remove(outputLoc)
+
+ if _, err := os.Stat(inputLoc); err != nil {
+ return err
+ }
+ fileContent, err := ioutil.ReadFile(inputLoc)
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(outputLoc, fileContent, 0777)
+}
+
+func tildeExpand(input string) string {
+ if strings.Contains(input, "~") {
+ input = strings.Replace(input, "~", homeDir, 1)
+ fmt.Printf("Full filepath is : %s", input)
+ }
+ return input
+}
+
+func checkDevice(n string) error {
+ if filepath.Dir(n) != "/dev" {
+ return nil
+ }
+ fi, err := os.Stat(n)
+ if err != nil {
+ return err
+ }
+ if fi.Mode()&os.ModeDevice != os.ModeDevice {
+ return fmt.Errorf("%q is in /dev and is not a device?", n)
+ }
+ return nil
+}
+
+func setup() error {
+ dir, err := os.Getwd()
+ syscall.Umask(0)
+ if err != nil {
+ return err
+ }
+ workingDir = dir
+ fmt.Printf("Working dir is %s\n", workingDir)
+ usr, err := user.Current()
+ if err != nil {
+ return err
+ }
+ homeDir = usr.HomeDir
+ fmt.Printf("Home dir is %s\n", homeDir)
+
+ if *dev == "/dev/null" {
+ kernDev, rootDev = *dev, *dev
+ return nil
+ }
+ kernDev, rootDev = *dev+"2", *dev+"3"
+ if err := checkDevice(kernDev); err != nil {
+ return err
+ }
+ if err := checkDevice(rootDev); err != nil {
+ return err
+ }
+ return nil
+}
+
+func aptget() error {
+ missing := []string{}
+ for _, packageName := range packageList {
+ cmd := exec.Command("dpkg", "-s", packageName)
+ if err := cmd.Run(); err != nil {
+ missing = append(missing, packageName)
+ }
+ }
+
+ if len(missing) == 0 {
+ fmt.Println("No missing dependencies to install")
+ return nil
+ }
+
+ fmt.Printf("Using apt-get to get %v\n", missing)
+ get := []string{"apt-get", "-y", "install"}
+ get = append(get, missing...)
+ cmd := exec.Command("sudo", get...)
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ return cmd.Run()
+
+}
+
+func cleanup() error {
+ filesToRemove := [...]string{"linux-stable", "vboot", "linux-firmware"}
+ fmt.Printf("-------- Removing problematic files %v\n", filesToRemove)
+ for _, file := range filesToRemove {
+ if _, err := os.Stat(file); err != nil {
+ if os.IsNotExist(err) {
+ continue
+ }
+ }
+ err := os.RemoveAll(file)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func goGet() error {
+ return nil
+ cmd := exec.Command("go", append([]string{"get", "github.com/u-root/u-root"}, dynamicCmdList...)...)
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ return cmd.Run()
+}
+
+func goBuildStatic() error {
+ oFile := filepath.Join(workingDir, "linux-stable", initramfs)
+ n, err := filepath.Glob("../u-root/cmds/core/*")
+ if err != nil {
+ return fmt.Errorf("../u-root/cmds/core/*: %v", err)
+ }
+ args := append([]string{"-o", oFile}, n...)
+ cmd := exec.Command("u-root", append(args, staticCmdList...)...)
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ fmt.Printf("Created %v\n", oFile)
+ return nil
+}
+
+func goBuildDynamic() error {
+ args := []string{"-o", filepath.Join(workingDir, initramfs)}
+ for _, v := range []string{"usr", "lib", "tcz", "etc", "upspin", ".ssh"} {
+ if _, err := os.Stat(v); err != nil {
+ continue
+ }
+ args = append(args, "-files", filepath.Join(workingDir, v)+":"+v)
+ }
+ log.Print("WARNING: skipping pkg/sos/html; fix me")
+ if false {
+ args = append(args, "-files", "pkg/sos/html:etc/sos/html")
+ }
+ args = append(args, dynamicCmdList...)
+ n, err := filepath.Glob("../u-root/cmds/*/*")
+ if err != nil {
+ return fmt.Errorf("../u-root/cmds/*/*: %v", err)
+ }
+ args = append(args, n...)
+ log.Printf("Run u-root with args %v", args)
+ cmd := exec.Command("u-root", args...)
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ fmt.Printf("Created %v", initramfs)
+ return nil
+}
+
+func getSUIDbinaries() error {
+ if err := os.MkdirAll("usr/bin", 0755); err != nil {
+ return err
+ }
+ binaries := []string{"/bin/fusermount"}
+ for _, b := range binaries {
+ cmd := exec.Command("sudo", "rsync", "-av", b, "usr/bin/")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ cmd.Env = os.Environ()
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func chrome() error {
+ if err := os.MkdirAll("usr/bin", 0755); err != nil {
+ return err
+ }
+ resp, err := http.Get("https://nichromeos.org/index.php/s/NEC5bZOqm0atPYe/download")
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != 200 {
+ return fmt.Errorf("non-200 HTTP status: %d", resp.StatusCode)
+ }
+ o, err := os.OpenFile("usr/bin/chrome", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0755)
+ if err != nil {
+ return err
+ }
+ defer o.Close()
+ if _, err := io.Copy(o, resp.Body); err != nil {
+ return err
+ }
+ return nil
+}
+
+func kernelGet() error {
+ var args = []string{"clone", "--depth", "1", "-b", kernelVersion, "git://git.kernel.org/pub/scm/linux/kernel/git/stable/" + linuxVersion + ".git"}
+ fmt.Printf("-------- Getting the kernel via git %v\n", args)
+ cmd := exec.Command("git", args...)
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ fmt.Printf("didn't clone kernel %v", err)
+ return err
+ }
+ return nil
+}
+
+func firmwareGet() error {
+ var args = []string{"clone", "git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/linux-firmware.git"}
+ fmt.Printf("-------- Getting the firmware via git %v\n", args)
+ cmd := exec.Command("git", args...)
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ fmt.Printf("didn't clone firmware %v", err)
+ return err
+ }
+ return nil
+}
+func buildKernel() error {
+ if err := cp(*config, "linux-stable/.config"); err != nil {
+ fmt.Printf("copying %v to linux-stable/.config: %v", *config, err)
+ }
+ // load NiChrome logo into kernel
+ cp("logo/logo_linux_clut224.ppm", "linux-stable/drivers/video/logo/logo_linux_clut224.ppm")
+
+ cmd := exec.Command("make", "--directory", "linux-stable", "-j"+strconv.Itoa(threads))
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ // TODO: this is OK for now. Later we'll need to do something
+ // with a map and GOARCH.
+ cmd.Env = append(os.Environ(), "ARCH=x86_64")
+ err := cmd.Run()
+ if err != nil {
+ return err
+ }
+ if _, err := os.Stat(filepath.Join("linux-stable", "/arch/x86/boot/bzImage")); err != nil {
+ return err
+ }
+ fmt.Printf("bzImage created")
+ return nil
+}
+
+func getVbutil() error {
+ fmt.Printf("-------- Building in Vbutil\n")
+ cmd := exec.Command("git", "clone", "https://github.com/coreboot/vboot")
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ return cmd.Run()
+}
+
+func buildVbutil() error {
+ cmd := exec.Command("make", "-j"+strconv.Itoa(threads))
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ cmd.Dir = "vboot"
+ if err := cmd.Run(); err != nil {
+ fmt.Printf("Make failed. Please try to manually install vbutil")
+ return err
+ }
+ return nil
+
+}
+
+func installUrootGpt() error {
+ cmd := exec.Command("go", "install", "-x", "github.com/u-root/u-root/cmds/core/gpt/")
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
+ return cmd.Run()
+}
+
+func vbutilIt() error {
+ // Try to read a GPT header from our output file. If we can, add a root_guid
+ // to config.txt, otherwise, don't bother.
+ args := []string{"gpt", *dev}
+ msg, err := exec.Command("sudo", args...).Output()
+ if err != nil {
+ log.Printf("gpt %v failed (warning only): %v", args, err)
+ }
+ var pg gpt.GUID
+ if err == nil {
+ var pt = &gpt.PartitionTable{}
+ if err := json.NewDecoder(bytes.NewBuffer(msg)).Decode(&pt); err != nil {
+ log.Printf("Reading in GPT JSON, warning only: %v", err)
+ } else if pt.Primary == nil || pt.MasterBootRecord == nil {
+ // With new changes to u-root/gpt we need to check to see if the contents
+ // of the struct are nil
+ log.Printf("Unable to parse GPT header of %v", *dev)
+ } else {
+ pg = gpt.GUID(pt.Primary.Parts[kernPart-1].UniqueGUID)
+ // We may not be able to read a GPT, consider the case that dev is /dev/null.
+ // But it is an error for it to be zero if we succeeded in reading it.
+ var zeropg gpt.GUID
+ if pg == zeropg {
+ log.Fatalf("Partition GUID for part %d is zero", kernPart-1)
+ }
+ }
+ }
+ newKern := "newKern"
+ configTxt := fmt.Sprintf("%sguid_root=%s\n", configTxt, pg.String())
+ if err := ioutil.WriteFile("config.txt", []byte(configTxt), 0644); err != nil {
+ return err
+ }
+ if err := ioutil.WriteFile("nocontent.efi", []byte("no content"), 0777); err != nil {
+ return err
+ }
+ bzImage := "linux-stable/arch/x86/boot/bzImage"
+ fmt.Printf("Bz image is located at %s \n", bzImage)
+ keyblock := filepath.Join(*keys, "recovery_kernel.keyblock")
+ sign := filepath.Join(*keys, "recovery_kernel_data_key.vbprivk")
+ cmd := exec.Command("./vboot/build/futility/futility", "vbutil_kernel", "--pack", newKern, "--keyblock", keyblock, "--signprivate", sign, "--version", "1", "--vmlinuz", bzImage, "--bootloader", "nocontent.efi", "--config", "config.txt", "--arch", "x86")
+ stdoutStderr, err := cmd.CombinedOutput()
+ fmt.Printf("%s\n", stdoutStderr)
+ return err
+}
+
+func dd(name, dev, file string) error {
+ fmt.Printf("Running dd to put %v onto %v", file, dev)
+ args := []string{"dd", "if=" + file, "of=" + dev}
+ msg, err := exec.Command("sudo", args...).CombinedOutput()
+ if err != nil {
+ return fmt.Errorf("dd %v failed: %v: %v", args, string(msg), err)
+ }
+ return nil
+}
+
+func kerndd() error {
+ return dd("Kernel image", kernDev, "newKern")
+}
+
+func rootdd() error {
+ return dd("tcz initramfs CPIO archive", rootDev, filepath.Join(workingDir, "initramfs.linux_amd64.cpio"))
+}
+
+func lsr(dirs []string, w io.Writer) error {
+ var err error
+ for _, n := range dirs {
+ err = filepath.Walk(n, func(name string, fi os.FileInfo, err error) error {
+ if err != nil {
+ if optional[name] {
+ return nil
+ }
+ return err
+ }
+ if fi.IsDir() {
+ return nil
+ }
+ fmt.Fprintf(w, "%v\n", name)
+ return nil
+ })
+ }
+ return err
+}
+
+func run(name string, args ...string) error {
+ cmd := exec.Command(name, args...)
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("%v %v: %v", name, args, err)
+ }
+ return nil
+}
+
+func tcz() error {
+ return run("tcz", append([]string{"-d", "-i=false", "-r=tcz"}, tczList...)...)
+}
+
+func check() error {
+ return nil
+}
+
+//TODO : final Error
+//TODO: absolute filepath things
+func allFunc() error {
+ var cmds = []struct {
+ f func() error
+ skip bool
+ ignore bool
+ n string
+ }{
+ {f: check, skip: false, ignore: false, n: "check environment"},
+ {f: setup, skip: false, ignore: false, n: "setup"},
+ {f: cleanup, skip: *skipkern || *skiproot || !*fetch, ignore: false, n: "cleanup"},
+ {f: goGet, skip: *skipkern || !*fetch, ignore: false, n: "Get u-root source"},
+ {f: tcz, skip: *skiproot || !*fetch, ignore: false, n: "run tcz to create the directory of packages"},
+ {f: getSUIDbinaries, skip: *skiproot, ignore: false, n: "Get SUID binaries"},
+ {f: chrome, skip: true || *skiproot || !*fetch, ignore: false, n: "to hell with chrome -- let's get firefox"},
+ {f: aptget, skip: !*apt, ignore: false, n: "apt get"},
+ {f: goBuildDynamic, skip: *skiproot, ignore: false, n: "Build dynamic initramfs"},
+ {f: rootdd, skip: *skiproot, ignore: false, n: "Put the tcz cpio onto the stick"},
+ {f: kernelGet, skip: *skipkern || !*fetch, ignore: false, n: "Git clone the kernel"},
+ {f: goBuildStatic, skip: *skipkern, ignore: false, n: "Build static initramfs"},
+ {f: firmwareGet, skip: *skipkern || !*fetch, ignore: false, n: "Git clone the firmware files"},
+ {f: buildKernel, skip: *skipkern, ignore: false, n: "build the kernel"},
+ {f: getVbutil, skip: *skipkern || !*fetch, ignore: false, n: "git clone vbutil"},
+ {f: buildVbutil, skip: *skipkern, ignore: false, n: "build vbutil"},
+ {f: installUrootGpt, skip: *skipkern, ignore: false, n: "install u-root gpt"},
+ {f: vbutilIt, skip: *skipkern, ignore: false, n: "vbutil and create a kernel image"},
+ {f: kerndd, skip: *skipkern, ignore: false, n: "Put the kernel image onto the stick"},
+ }
+
+ for _, c := range cmds {
+ log.Printf("-----> Step %v: ", c.n)
+ if c.skip {
+ log.Printf("-------> Skip")
+ continue
+ }
+ log.Printf("----------> Start")
+ err := c.f()
+ if c.ignore {
+ log.Printf("----------> Ignore result")
+ continue
+ }
+ if err != nil {
+ return fmt.Errorf("%v: %v", c.n, err)
+ }
+ log.Printf("----------> Finished %v\n", c.n)
+ }
+ return nil
+}
+
+func main() {
+ flag.Parse()
+ if *extra != "" {
+ dynamicCmdList = append(dynamicCmdList, strings.Split(*extra, ",")...)
+ }
+ log.Printf("Using kernel %v\n", kernelVersion)
+ if err := allFunc(); err != nil {
+ log.Fatalf("fail error is : %v", err)
+ }
+ log.Printf("execution completed successfully\n")
+}
diff --git a/nichrome/verified_boot.md b/nichrome/verified_boot.md
new file mode 100644
index 000000000..442aab86f
--- /dev/null
+++ b/nichrome/verified_boot.md
@@ -0,0 +1,53 @@
+# Booting in Verified Mode
+
+*This process is known to work on all devices listed below. Feel free to try it out on others, and add it to the list if it works!*
+
+### Part 1: Enter Developer mode
+*Warning: this deletes all local data. Back up any important files before continuing*
+ 1. On your Chromebook, press Esc-Reload-Power to enter Recovery mode.
+ 2. Press Ctrl-D then Enter to reboot in Developer mode.
+
+### Part 2: Build and install NiChrome
+ 1. On your Chromebook, install the Chrome OS Recovery tool from the Chrome Web Store and format the USB stick.
+ 2. On your build machine, run `go get github.com/u-root/u-root github.com/u-root/NiChrome` to fetch the source code.
+ 3. Navigate to $GOPATH/src/github.com/u-root/NiChrome/usb and run `go build .` to compile the USB build tool.
+ 4. Insert your formatted USB stick and determine its dev directory (/dev/sdX)
+ 5. Move back up to the NiChrome directory and run `./usb/usb --fetch=true --dev=/dev/sdX` to build NiChrome and load it onto the USB.
+ 6. On your Chromebook, boot into NiChrome by inserting the USB and pressing Ctrl-U. If this fails, see the Notes below.
+ 7. Run `install /dev/mmcblkX` to install NiChrome on the secondary boot partition (X will be either 0 or 1, depending on your system. Tab-complete to be safe)
+ 8. Set NiChrome's boot priority by rebooting into Chrome OS and running `cgpt add -i 4 -P 2 -T 1 -S 0 /dev/mmcblkX`
+
+*On your next reboot, press Ctrl-D to boot into NiChrome from disk*
+
+### Part 3: Re-key your Chromebook and return to Verified mode
+ 1. Disable firmware write protection by cracking open the laptop's shell and removing the WP screw (older devices only) or disconnecting the battery.
+ 2. Boot into Chrome OS. If you're stuck in NiChrome, continue to reboot until you're dropped in to Chrome OS.
+ 3. Open the VT2 terminal on Chrome OS by pressing Ctrl-Alt-Forward, login as root.
+ 4. Sign your Chromebook firmware with developer keys by running `/usr/share/vboot/bin/make_dev_firmware.sh`
+ 5. Sign Chrome OS by running `/usr/share/vboot/bin/make_dev_ssd.sh --partitions 2`
+ 5. Sign NiChrome by running `/usr/share/vboot/bin/make_dev_ssd.sh --partitions 4`
+ 6. Save the key backups externally. When you exit Developer mode, your data will be wiped and you will not be able to revert
+ to default keys in the future.
+ 7. Reset NiChrome's boot priority by running `cgpt add -i 4 -P 2 -T 1 /dev/mmcblkX`. If you want to stay in NiChrome, run this command with `-P 2 -T 0 -S 1`.
+ 8. Reboot and press Spacebar then Enter to return to Verified mode!
+
+*You should now be able to boot into NiChrome/Chrome OS in verified mode with the Developer keys*
+
+### Notes
+ * From the Developer mode warning screen, press Ctrl-D to boot from disk, and Ctrl-U to boot from USB.
+
+ * We format the USB using the Chrome Recovery tool so that the partition system is in a form the bootloader can understand. It does not matter what Chromebook you format the USB for, as NiChrome overwrites it anyway.
+
+ * If the Developer mode warning yells at you when trying to boot from USB, boot into Chrome OS, enter VT2, and run `enable_dev_usb_boot`.
+
+ * Tries gets decremented on each boot. To remain in NiChrome, run cgpt with flags `-P 2 -T 0 -S 1`. WARNING: this locks you into NiChrome, with no easy way to return to Chrome OS. NiChrome's `gpt` command will eventually implement cgpt-style priority settings, but this does not yet exist.
+
+ * If you create your own signing keys, add `-k /path/to/keys` to all `make_dev_*` commands in Part 3. Also, insert the NiChrome USB and run `/usr/share/vboot/bin/make_dev_ssd.sh -i /dev/sdX -k /path/to/keys --recovery_key` to sign your USB as a recovery stick. This way, you can boot from your USB in Verified mode.
+
+### Known Working Boards
+
+*Find your board name in Recovery mode at the bottom of your screen, without a USB stick inserted.*
+
+ * Basking
+ * Lava
+ * Sentry
diff --git a/webboot/.github/ISSUE_TEMPLATE/bug_report.md b/webboot/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 000000000..471baed24
--- /dev/null
+++ b/webboot/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,20 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/webboot/.github/ISSUE_TEMPLATE/feature_request.md b/webboot/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 000000000..bbcbbe7d6
--- /dev/null
+++ b/webboot/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/webboot/.github/workflows/ci.yml b/webboot/.github/workflows/ci.yml
new file mode 100644
index 000000000..31ec6b8b9
--- /dev/null
+++ b/webboot/.github/workflows/ci.yml
@@ -0,0 +1,50 @@
+name: CI
+on:
+ # Triggers the workflow on push or pull request events but only for the
+ # main branch
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# A workflow run is made up of one or more jobs that can run sequentially or in
+# parallel
+jobs:
+ # This workflow contains a single job called "build"
+ build:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ # Environment variables
+ env:
+ # GOPATH is the current directory.
+ GOPATH: ${{ github.workspace }}
+ # Turn off modules because they are broken.
+ GO111MODULE: off
+
+ # Set the working directory to the correct place in $GOPATH.
+ defaults:
+ run:
+ working-directory: ${{ env.GOPATH }}/src/github.com/${{ github.repository }}
+
+ # Steps represent a sequence of tasks that will be executed as part of the
+ # job
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v2
+ with:
+ go-version: 1.16.x
+ - name: Checkout code
+ uses: actions/checkout@v2
+ with:
+ path: ${{ env.GOPATH }}/src/github.com/${{ github.repository }}
+ - name: Checkout dependencies
+ run: |
+ sudo apt-get update
+ ./firsttime.sh
+ - name: Build and test webboot
+ run: |
+ ./ci.sh
diff --git a/webboot/.github/workflows/nightly.yml b/webboot/.github/workflows/nightly.yml
new file mode 100644
index 000000000..229a08f89
--- /dev/null
+++ b/webboot/.github/workflows/nightly.yml
@@ -0,0 +1,105 @@
+name: nightly
+on:
+ # Triggers the workflow every day at 23:00.
+ schedule:
+ - cron: '0 23 * * *'
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# A workflow run is made up of one or more jobs that can run sequentially or in
+# parallel.
+jobs:
+ # This job will build the linux kernel.
+ buildKernel:
+ runs-on: ubuntu-latest
+ # Environment variables
+ env:
+ # GOPATH is the current directory.
+ GOPATH: ${{ github.workspace }}
+ # Turn off modules because they are broken.
+ GO111MODULE: off
+ # WEBBOOT is the where the code is checked out.
+ WEBBOOT: ${{ github.workspace }}/src/github.com/${{ github.repository }}
+ # Set the working directory to the correct place in $GOPATH.
+ defaults:
+ run:
+ working-directory: ${{ env.WEBBOOT }}
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ with:
+ path: ${{ env.WEBBOOT }}
+ - name: Kernel Build
+ run: |
+ ./nightly.sh
+ ls -l linux/arch/x86/boot/bzImage
+ - uses: actions/upload-artifact@v2
+ with:
+ name: nightly-kernel-build
+ path: ${{ env.WEBBOOT }}/linux/arch/x86/boot/bzImage
+ if-no-files-found: error
+ retention-days: 30
+
+ # This job will run the matrix of distros.
+ runDistros:
+ needs: buildKernel
+ runs-on: ubuntu-latest
+ # Environment variables
+ env:
+ # GOPATH is the current directory.
+ GOPATH: ${{ github.workspace }}
+ # Turn off modules because they are broken.
+ GO111MODULE: off
+ # WEBBOOT is the where the code is checked out.
+ WEBBOOT: ${{ github.workspace }}/src/github.com/${{ github.repository }}
+ # qemu binary and kernel for integration test
+ UROOT_QEMU: qemu-system-x86_64
+ UROOT_KERNEL: ${{ github.workspace }}/src/github.com/${{ github.repository }}/linux/arch/x86/boot/bzImage
+ # Set the working directory to the correct place in $GOPATH.
+ defaults:
+ run:
+ working-directory: ${{ env.WEBBOOT }}
+ strategy:
+ # Run at most 2 distros at a time.
+ max-parallel: 2
+ # Continue testing other distros on failure.
+ fail-fast: false
+ # List of distros
+ matrix:
+ distro:
+ - TinyCore
+ - Arch
+ - CentOS 7
+ - CentOS 8
+ - Debian
+ - Fedora
+ - Kali
+ - Linux Mint
+ - Manjaro
+ - Ubuntu
+ # Steps represent a sequence of tasks that will be executed as part of the
+ # job
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v2
+ with:
+ go-version: 1.16.x
+ - name: Checkout code
+ uses: actions/checkout@v2
+ with:
+ path: ${{ env.WEBBOOT }}
+ - name: Checkout dependencies
+ run: |
+ sudo apt-get update
+ ./firsttime.sh
+ - uses: actions/download-artifact@v2
+ with:
+ name: nightly-kernel-build
+ # Note that the ../ is required; otherwise, github creates a
+ # directory called bzImage containing bzImage.
+ path: ${{ env.UROOT_KERNEL }}/../
+ - name: Test TestScript
+ run: |
+ ls -l ${{ env.UROOT_KERNEL }}
+ WEBBOOT_DISTRO="${{ matrix.distro }}" go test -v ./integration
diff --git a/webboot/.gitignore b/webboot/.gitignore
new file mode 100644
index 000000000..6ac8ee5c1
--- /dev/null
+++ b/webboot/.gitignore
@@ -0,0 +1,26 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, build with `go test -c`
+*.test
+
+# Busybox directories.
+.bb/
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+*~
+
+# ignore kernels we build here, and firmware we download.
+linux
+linux-firmware
+
+# Ignore wpa_supplicant builds.
+wpa_supplicant-*.tar.gz
+wpa_supplicant-*.tar.gz.asc
+wpa_supplicant-*/
diff --git a/webboot/CONTRIBUTING.md b/webboot/CONTRIBUTING.md
new file mode 100644
index 000000000..847fba4cc
--- /dev/null
+++ b/webboot/CONTRIBUTING.md
@@ -0,0 +1,103 @@
+# Contributing to u-root
+
+We need help with this project. Contributions are very welcome. See the [roadmap](roadmap.md), open [issues](https://github.com/u-root/webboot/issues), and join us in [Slack](CONTRIBUTING.md#communication) to talk about your cool ideas for the project.
+
+## Developer Sign-Off
+
+For purposes of tracking code-origination, we follow a simple sign-off
+process. If you can attest to the [Developer Certificate of
+Origin](https://developercertificate.org/) then you append in each git
+commit text a line such as:
+```
+Signed-off-by: Your Name
+```
+## Code of Conduct
+
+Conduct collaboration in accordance to the [Code of
+Conduct](https://github.com/u-root/u-root/wiki/Code-of-Conduct).
+
+## Communication
+
+- [Slack](https://u-root.slack.com), sign up
+[here](http://slack.u-root.com/)
+
+## Bugs
+
+- Please submit issues to https://github.com/u-root/webboot/issues
+
+## Coding Style
+
+The ``webboot`` project aims to follow the standard formatting recommendations
+and language idioms set out in the [Effective Go](https://golang.org/doc/effective_go.html)
+guide, for example [formatting](https://golang.org/doc/effective_go.html#formatting)
+and [names](https://golang.org/doc/effective_go.html#names).
+
+`gofmt` and `golint` are law, although this is not automatically enforced
+yet and some housecleaning needs done to achieve that.
+
+We have a few rules not covered by these tools:
+
+- Standard imports are separated from other imports. Example:
+ ```
+ import (
+ "regexp"
+ "time"
+
+ dhcp "github.com/krolaw/dhcp4"
+ )
+ ```
+
+## Patch Format
+
+Well formatted patches aide code review pre-merge and code archaeology in
+the future. The abstract form should be:
+```
+: Change summary
+
+More detailed explanation of your changes: Why and how.
+Wrap it to 72 characters.
+See [here] (http://chris.beams.io/posts/git-commit/)
+for some more good advices.
+
+Signed-off-by:
+```
+
+An example from this repo:
+```
+tcz: quiet it down
+
+It had a spurious print that was both annoying and making
+boot just a tad slower.
+
+Signed-off-by: Ronald G. Minnich
+```
+
+## General Guidelines
+
+Webboot aims to be able to boot (optionally) signed distros from URLs.
+
+## Pull Requests
+
+We accept GitHub pull requests.
+
+Fork the project on GitHub, work in your fork and in branches, push
+these to your GitHub fork, and when ready, do a GitHub pull requests
+against https://github.com/u-root/webboot.
+
+`webboot` uses go modules. Do not clone webboot into your GOPATH.
+If you add new dependencies, use the appropriate go modules command
+to update things.
+
+Every commit in your pull request needs to be able to build and pass the CI tests.
+
+If the pull request closes an issue please note it as: `"Fixes #NNN"`.
+
+## Code Reviews
+
+Look at the area of code you're modifying, its history, and consider
+tagging some of the [maintainers](https://u-root.tk/#contributors) when doing a
+pull request in order to instigate some code review.
+
+## Quality Controls
+
+We use Azure pipelines for our CI.
diff --git a/webboot/Gopkg.lock b/webboot/Gopkg.lock
new file mode 100644
index 000000000..cb4b85e72
--- /dev/null
+++ b/webboot/Gopkg.lock
@@ -0,0 +1,180 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ digest = "1:27a44a693abe815173ff862b763f95ccc228dd788fbfb71d7d15699048b49d74"
+ name = "github.com/cenkalti/backoff"
+ packages = ["."]
+ pruneopts = ""
+ revision = "18fe4ce5a8550e0d0919b680ad3c080a5455bddf"
+ version = "v4.0.2"
+
+[[projects]]
+ digest = "1:dec9486211fe71cc00a66bc9677b776b8926c3336c09509a16394e30e4b18b74"
+ name = "github.com/gizak/termui"
+ packages = [
+ "v3",
+ "v3/drawille",
+ "v3/widgets",
+ ]
+ pruneopts = ""
+ revision = "4cca61d83fa2cc0f485c478ff768b0108f6591d6"
+ version = "v3.1.0"
+
+[[projects]]
+ digest = "1:d19d74ba2e4f95118d88c357fe6ad30840e28343e75023ffa96830d779974566"
+ name = "github.com/insomniacslk/dhcp"
+ packages = [
+ "dhcpv4",
+ "dhcpv4/nclient4",
+ "dhcpv6",
+ "dhcpv6/nclient6",
+ "iana",
+ "interfaces",
+ "rfc1035label",
+ ]
+ pruneopts = ""
+ revision = "e1b69ee5fb3318ca17418526efa5bc41c98ff29b"
+
+[[projects]]
+ digest = "1:59794624db141f0f0a893d110111b962984c9844cf565efa91c35bedb882c9ff"
+ name = "github.com/mattn/go-runewidth"
+ packages = ["."]
+ pruneopts = ""
+ revision = "14e809f6d78fcf9f48ff9b70981472b64c05f754"
+ version = "v0.0.9"
+
+[[projects]]
+ branch = "master"
+ digest = "1:784945b75874aebb12fbba657773e9fce33b53c6832c7bd26cffd3253a9087c4"
+ name = "github.com/mdlayher/ethernet"
+ packages = ["."]
+ pruneopts = ""
+ revision = "0394541c37b7f86a10e0b49492f6d4f605c34163"
+
+[[projects]]
+ branch = "master"
+ digest = "1:ae8c7c747b36590d55929526d450231ebaacbce50937d065b58088e41ed413be"
+ name = "github.com/mdlayher/raw"
+ packages = ["."]
+ pruneopts = ""
+ revision = "50f2db8cc0658568575938a39dbaa46172921d98"
+
+[[projects]]
+ digest = "1:713b341855f1480e4baca1e7c5434e1d266441340685ecbde32d59bdc065fb3f"
+ name = "github.com/mitchellh/go-wordwrap"
+ packages = ["."]
+ pruneopts = ""
+ revision = "9e67c67572bc5dd02aef930e2b0ae3c02a4b5a5c"
+ version = "v1.0.0"
+
+[[projects]]
+ branch = "master"
+ digest = "1:1942df3305c51265563afcfea827a6b1207117acb7667d6870c03add7165bb1f"
+ name = "github.com/nsf/termbox-go"
+ packages = ["."]
+ pruneopts = ""
+ revision = "38ba6e5628f1d70bac606cfd210b9ad1a16c3027"
+
+[[projects]]
+ branch = "master"
+ digest = "1:c93c9eb031ecd6d4cee79cb880396811fea330f5170abb803f5be4bb417a80aa"
+ name = "github.com/rekby/gpt"
+ packages = ["."]
+ pruneopts = ""
+ revision = "7da10aec5566349f29875dad4a59c8341b01e00a"
+
+[[projects]]
+ branch = "master"
+ digest = "1:d7038d6b145dcc8ab8bd70301510cd12e85952daa8b68b96cbb851aa8e9b7f9e"
+ name = "github.com/u-root/u-root"
+ packages = [
+ "pkg/boot",
+ "pkg/boot/ibft",
+ "pkg/boot/kexec",
+ "pkg/boot/multiboot",
+ "pkg/boot/multiboot/internal/trampoline",
+ "pkg/boot/syslinux",
+ "pkg/cmdline",
+ "pkg/curl",
+ "pkg/dhclient",
+ "pkg/mount",
+ "pkg/mount/block",
+ "pkg/mount/loop",
+ "pkg/pci",
+ "pkg/rand",
+ "pkg/shlex",
+ "pkg/ubinary",
+ "pkg/uio",
+ ]
+ pruneopts = ""
+ revision = "ad067b0a53cbe49d5b0c000ccb1acbe9ee0da08c"
+
+[[projects]]
+ branch = "master"
+ digest = "1:f923218863b1b913b1db4b1afc1a1204a203ccbf8b0bdb86bcd4a4da24f1f2ee"
+ name = "github.com/vishvananda/netlink"
+ packages = [
+ ".",
+ "nl",
+ ]
+ pruneopts = ""
+ revision = "98629f7ffc4b05a38794a4aa327ac810602a6d2e"
+
+[[projects]]
+ branch = "master"
+ digest = "1:096ba1cd91d38ee0bac7f4917c8f0d877b01c1fa7c61a8c4005e9eb79d140a86"
+ name = "github.com/vishvananda/netns"
+ packages = ["."]
+ pruneopts = ""
+ revision = "db3c7e526aae966c4ccfa6c8189b693d6ac5d202"
+
+[[projects]]
+ branch = "master"
+ digest = "1:92cf07fb2067987a7b46e1f63aa50ccde3ee8a7315ffca3e4e8a3a147ac9a717"
+ name = "golang.org/x/net"
+ packages = ["bpf"]
+ pruneopts = ""
+ revision = "ab34263943818b32f575efc978a3d24e80b04bd7"
+
+[[projects]]
+ branch = "master"
+ digest = "1:0ab3a6e867e19170427903297d997455ec237b4226fdd0778f25719b479cff7a"
+ name = "golang.org/x/sys"
+ packages = [
+ "internal/unsafeheader",
+ "unix",
+ ]
+ pruneopts = ""
+ revision = "5acd03effb828bdfdbad4e129e7daf84af6670b4"
+
+[[projects]]
+ branch = "master"
+ digest = "1:484f9b541e8ce421abeacddf297ea1f2db4461896854bc64fc6c1dc60b97821d"
+ name = "pack.ag/tftp"
+ packages = [
+ ".",
+ "netascii",
+ ]
+ pruneopts = ""
+ revision = "07909dfbde3c4e388a7e353351191fbb987ce5a5"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ input-imports = [
+ "github.com/gizak/termui/v3",
+ "github.com/gizak/termui/v3/widgets",
+ "github.com/u-root/u-root/pkg/boot",
+ "github.com/u-root/u-root/pkg/boot/kexec",
+ "github.com/u-root/u-root/pkg/boot/syslinux",
+ "github.com/u-root/u-root/pkg/dhclient",
+ "github.com/u-root/u-root/pkg/mount",
+ "github.com/u-root/u-root/pkg/mount/block",
+ "github.com/u-root/u-root/pkg/mount/loop",
+ "github.com/u-root/u-root/pkg/uio",
+ "github.com/vishvananda/netlink",
+ "golang.org/x/sys/unix",
+ ]
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/webboot/Gopkg.toml b/webboot/Gopkg.toml
new file mode 100644
index 000000000..1206db5e3
--- /dev/null
+++ b/webboot/Gopkg.toml
@@ -0,0 +1,42 @@
+
+# Gopkg.toml example
+#
+# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+# name = "github.com/user/project"
+# version = "1.0.0"
+#
+# [[constraint]]
+# name = "github.com/user/project2"
+# branch = "dev"
+# source = "github.com/myfork/project2"
+#
+# [[override]]
+# name = "github.com/x/y"
+# version = "2.4.0"
+
+
+[[constraint]]
+ name = "github.com/gizak/termui"
+ version = "3.1.0"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/u-root/u-root"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/vishvananda/netlink"
+
+[[constraint]]
+ branch = "master"
+ name = "golang.org/x/sys"
+
+[[override]]
+ name = "github.com/insomniacslk/dhcp"
+ revision = "e1b69ee5fb3318ca17418526efa5bc41c98ff29b"
\ No newline at end of file
diff --git a/webboot/LICENSE b/webboot/LICENSE
new file mode 100644
index 000000000..aab611fed
--- /dev/null
+++ b/webboot/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2012-2019, u-root Authors
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/webboot/README.md b/webboot/README.md
new file mode 100644
index 000000000..ba9af9939
--- /dev/null
+++ b/webboot/README.md
@@ -0,0 +1,349 @@
+# About
+
+`webboot` offers tools to let a u-root instance boot signed live distro images over the web.
+
+## Concept
+
+The `webboot` bootloader works as follows:
+
+1. fetch an OS distro release ISO from the web
+2. save the ISO to a local cache (ex. USB stick)
+3. mount the ISO and copy out the kernel and initrd
+4. load the extracted kernel with the initrd
+5. kexec that kernel with parameters to tell the next distro where to locate its ISO file (ex. iso-scan/filename=)
+
+The current version offers a user interface based on [termui](https://github.com/gizak/termui) to help locate and boot the ISO file.
+
+For reference, webboot developers should familiarize themselves with:
+
+- [cpio tutorial](https://www.gnu.org/software/cpio/manual/html_node/Tutorial.html)
+- [initrd usage](https://www.kernel.org/doc/html/latest/admin-guide/initrd.html)
+- [kernel parameters](https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html)
+
+
+## Supported Operating Systems
+
+### Requirements
+ISOs must have the following to be fully compatible with `webboot`.
+
+1. 64-bit kernel
+2. Parsable `grub` or `syslinux` config file
+3. Init process than can locate an ISO file (ex. casper's iso-scan)
+
+Additional operating systems can be added by appending an entry to the `supportedDistros` map in `/cmds/webboot/types.go`.
+
+If the config file is not compatible with our parser, we can manually specify the configuration by adding a `Config` object to the distro's entry in `supportedDistros`. See the entries for Arch and Manjaro as an example.
+
+### Currently Supported
+| Name | Required Kernel Parameters | Notes |
+| ----- | ------ | ----- |
+| Arch | `img_dev=/dev/disk/by-uuid/UUID img_loop=PATH_TO_ISO` | Unable to parse config file. Configuration is specified in a `Config` object.
+| CentOS | `iso-scan/filename=PATH_TO_ISO` | CentOS 7 supports live mode. CentOS 8 will boot to the graphical installer.
+| Debian | `findiso=PATH_TO_ISO` |
+| Fedora | `iso-scan/filename=PATH_TO_ISO` |
+| Kali | `findiso=PATH_TO_ISO` |
+| Linux Mint | `iso-scan/filename=PATH_TO_ISO` |
+| Manjaro | `img_dev=/dev/disk/by-uuid/UUID img_loop=PATH_TO_ISO` | Unable to parse config file. Configuration is specified in a `Config` object.
+| Tinycore | `iso=UUID/PATH_TO_ISO` |
+| Ubuntu | `iso-scan/filename=PATH_TO_ISO` |
+
+### In Progress
+| Name | Required Kernel Parameters | Issue |
+| --- | --- | --- |
+| OpenSUSE | `root=live:CDLABEL=ISO_LABEL iso-scan/filename=PATH_TO_ISO` | `grub` config file is too complicated for our parser. We could specify the configuration manually, but that would involve hardcoding the ISO_LABEL (see [Issue 185](https://github.com/u-root/webboot/issues/185)).|
+
+## Usage
+
+### Build initramfs with added webboot commands
+
+Download u-root with `GO111MODULE=off go get github.com/u-root/u-root`.
+
+Run `GO111MODULE=off go run .` in the source directory of webboot to build the
+initramfs.
+
+This runs [u-root](https://github.com/u-root/u-root) under the hood. To pass
+extra options, such as to include extra files, use the `-u` switch, e.g.,
+`GO111MODULE=off go run buildimage.go -u "-files path/to/bzImage:bzImage"` to
+add a custom kernel which can be used to test whether kexec works in a small
+setup. That saves a lot of time, because a full webboot flow would always need
+to download large ISO files, copy them, mount and decompress.
+
+#### Convenience
+
+For convenience, you can
+
+- skip the inclusion of Wi-Fi tools by passing `-wifi false`
+- add a custom kernel for within the initramfs via `-bzImage path/to/bzImage`
+- add an ISO file to the initramfs via `-iso path/to/os-distro.iso`
+ * boot that ISO via `webboot -dhcp4=false -dhcp6-false local` later, which
+ requires passing a pmem-enabled kernel via `-bzImage` as described above
+
+#### Compression
+
+You can optionally compress the initramfs with `lzma` or any other compression
+method you configure your kernel for.
+
+```sh
+lzma -f /tmp/initramfs.linux_amd64.cpio
+```
+
+Refer to [u-root's documentation](https://github.com/u-root/u-root#compression)
+for more details on compression.
+
+#### Customization
+
+The `buildimage.go` utility is really just a helper tool. Instead of using it,
+you can build a custom u-root image as you like and add the `webboot` binary to
+it.
+Refer to [u-root's usage documentation](https://github.com/u-root/u-root#usage)
+for details.
+
+### Building a kernel for webboot
+
+webboot uses a standard Linux kernel which should be fairly portable, based on a
+Long Term Stable (LTS) release. It has worked on every Chromebook we tried.
+
+This kernel is built using a config originally from
+[NiChromeOS](github.com/NiChrome/NiChrome).
+If we are building a bootable USB stick formatted with vfat, we don't have the
+space constraints of NiChrome, so we expect this to diverge over time.
+
+Nevertheless, to keep it all simple, we build it as a non-modular kernel with
+Wi-fi firmware built-in. We no longer build the initramfs into the kernel, as
+that's not needed.
+
+Make sure the kernel configuration includes the firmware for your network device.
+For instance, the Thinkpad x240 with Intel Corporation Wireless 7260 uses
+iwlwifi-7260-17.ucode. If you look at the kernel config file, this firmware name
+is included under `CONFIG_EXTRA_FIRMWARE=`.
+
+To build, first be sure you're in a directory you want to be in!
+You can actually do the work in the webboot root directory because the
+`.gitignore` file ignores the two directories you create when following the
+instructions here.
+
+#### Prerequisites
+
+You need to have the following packages installed if on Ubuntu:
+```sh
+sudo apt install libssl-dev build-essential wireless-tools kexec-tools libelf-dev libnl-3-dev libnl-genl-3-dev
+```
+
+#### Fetching, configuring and compiling the kernel
+
+```sh
+git clone --depth 1 -b v5.6.14 \
+ git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git linux
+git clone \
+ git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/linux-firmware.git
+cp config-5.6.14 linux/.config
+(cd linux && make bzImage)
+GO111MODULE=off go run .
+```
+
+### Testing in QEMU
+
+Install QEMU with
+```sh
+sudo apt-get install qemu-system-x86
+```
+
+Run the following, and a QEMU window should pop up:
+
+Tip: Don't use the `-nographic` option for u-root in QEMU as you want to boot
+into a graphical interface.
+
+#### Acceleration
+
+If you have KVM in your host system, you can add `-enable-kvm` for speedup.
+
+```sh
+qemu-system-x86_64 \
+ -enable-kvm \
+ -m 2G \
+ -kernel linux/arch/x86/boot/bzImage \
+ -append 'console=ttyS0 console=tty1 memmap=1G!1G' \
+ -initrd /tmp/initramfs.linux_amd64.cpio \
+ -device virtio-rng-pci \
+ -netdev user,id=network0 \
+ -device rtl8139,netdev=network0
+```
+
+Tip: Don't use the `-nographic` option for u-root in QEMU as you want to boot
+into a graphical interface.
+
+In the QEMU terminal, run
+```sh
+dhclient -ipv6=f
+```
+and then run
+```sh
+webboot
+```
+
+Refer to
+[u-root's documentation](https://github.com/u-root/u-root#testing-in-qemu) for
+more details on virtualization.
+
+### Testing with a USB stick
+
+You can try out webboot from a USB stick. That means that you could run it when
+starting a machine by choosing to boot from USB, which requires a bootloader.
+Although any bootloader would do, we will focus on one here named `syslinux`.
+Furthermore, we will focus on specific preconditions, although there are many
+different ways to create a bootable USB stick.
+
+In the root directory of this repository, there is an example configuration file
+named `syslinux.cfg.example`. If you look at it, you will see that it resembles
+webboot very much: It lists a kernel, an initrd, and extra arguments to append.
+
+Before you continue, please make sure to meet the following conditions:
+
+- your system can boot from MBR (possibly through UEFI CSM)
+- You have a directory `/mnt/usb` to mount the partition to
+
+To [install](https://wiki.syslinux.org/wiki/index.php?title=Install) syslinux as
+a bootloader and configure it, four steps are necessary:
+
+1. Write a Volume Boot Record (VBR) to the stick
+2. Write a Master Boot Record (MBR) to it
+3. Mark the first partition as bootable
+4. Copy the config file, Linux kernel, and initcpio
+
+The following instructions will walk you through these four steps.
+Tip: You may need to replace `sdb1` with the name of your partition.
+
+Install syslinux with
+```sh
+sudo apt-get install syslinux
+```
+
+To prepare your USB stick, run `sudo fdisk /dev/sdb` and use the fdisk instructions to complete the following:
+1. Delete all existing partitions (d)
+2. Add one new partition (n, p, 1)
+3. Change partition type (t) to EFI (ef)
+4. Make partition 1 bootable (a)
+5. Save (w)
+
+Here is a sample fdisk output:
+```sh
+$ sudo fdisk /dev/sdb
+
+Welcome to fdisk (util-linux 2.36.1).
+Changes will remain in memory only, until you decide to write them.
+Be careful before using the write command.
+
+
+Command (m for help): d
+Selected partition 1
+Partition 1 has been deleted.
+
+Command (m for help): n
+Partition type
+ p primary (0 primary, 0 extended, 4 free)
+ e extended (container for logical partitions)
+Select (default p): p
+Partition number (1-4, default 1): 1
+First sector (2048-121061375, default 2048):
+Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-121061375, default 121061375):
+
+Created a new partition 1 of type 'Linux' and of size 57.7 GiB.
+
+Command (m for help): t
+Selected partition 1
+Hex code or alias (type L to list all): L
+
+00 Empty 24 NEC DOS 81 Minix / old Lin bf Solaris
+01 FAT12 27 Hidden NTFS Win 82 Linux swap / So c1 DRDOS/sec (FAT-
+02 XENIX root 39 Plan 9 83 Linux c4 DRDOS/sec (FAT-
+03 XENIX usr 3c PartitionMagic 84 OS/2 hidden or c6 DRDOS/sec (FAT-
+04 FAT16 <32M 40 Venix 80286 85 Linux extended c7 Syrinx
+05 Extended 41 PPC PReP Boot 86 NTFS volume set da Non-FS data
+06 FAT16 42 SFS 87 NTFS volume set db CP/M / CTOS / .
+07 HPFS/NTFS/exFAT 4d QNX4.x 88 Linux plaintext de Dell Utility
+08 AIX 4e QNX4.x 2nd part 8e Linux LVM df BootIt
+09 AIX bootable 4f QNX4.x 3rd part 93 Amoeba e1 DOS access
+0a OS/2 Boot Manag 50 OnTrack DM 94 Amoeba BBT e3 DOS R/O
+0b W95 FAT32 51 OnTrack DM6 Aux 9f BSD/OS e4 SpeedStor
+0c W95 FAT32 (LBA) 52 CP/M a0 IBM Thinkpad hi ea Linux extended
+0e W95 FAT16 (LBA) 53 OnTrack DM6 Aux a5 FreeBSD eb BeOS fs
+0f W95 Ext'd (LBA) 54 OnTrackDM6 a6 OpenBSD ee GPT
+10 OPUS 55 EZ-Drive a7 NeXTSTEP ef EFI (FAT-12/16/
+11 Hidden FAT12 56 Golden Bow a8 Darwin UFS f0 Linux/PA-RISC b
+12 Compaq diagnost 5c Priam Edisk a9 NetBSD f1 SpeedStor
+14 Hidden FAT16 <3 61 SpeedStor ab Darwin boot f4 SpeedStor
+16 Hidden FAT16 63 GNU HURD or Sys af HFS / HFS+ f2 DOS secondary
+17 Hidden HPFS/NTF 64 Novell Netware b7 BSDI fs fb VMware VMFS
+18 AST SmartSleep 65 Novell Netware b8 BSDI swap fc VMware VMKCORE
+1b Hidden W95 FAT3 70 DiskSecure Mult bb Boot Wizard hid fd Linux raid auto
+1c Hidden W95 FAT3 75 PC/IX bc Acronis FAT32 L fe LANstep
+1e Hidden W95 FAT1 80 Old Minix be Solaris boot ff BBT
+
+Aliases:
+ linux - 83
+ swap - 82
+ extended - 05
+ uefi - EF
+ raid - FD
+ lvm - 8E
+ linuxex - 85
+Hex code or alias (type L to list all): EF
+Changed type of partition 'Linux' to 'EFI (FAT-12/16/32)'.
+
+Command (m for help): a
+Selected partition 1
+The bootable flag on partition 1 is enabled now.
+
+Command (m for help): w
+The partition table has been altered.
+Calling ioctl() to re-read partition table.
+Syncing disks.
+```
+
+Generate the partition header
+```sh
+mkfs -t vfat /dev/sdb1
+```
+
+Mount the USB and copy the config file, Linux kernel, and initcpio
+```sh
+sudo mount /dev/sdb1 /mnt/usb
+cp config-5.6.14 /mnt/usb/
+cp arch/x86/boot/bzImage /mnt/usb
+cp /tmp/initramfs.linux_amd64.cpio /mnt/usb
+umount /mnt/usb
+```
+
+Zip initramfs
+```sh
+gzip /tmp/initramfs.linux_amd64.cpio
+```
+
+Now the following commands would need to be run as root:
+
+```sh
+syslinux -i /dev/sdb1
+dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sdb
+parted /dev/sdb set 1 boot on
+# mount the stick and copy the files
+mount /dev/sdb1 /mnt/usb
+cp syslinux.cfg.example /mnt/usb/syslinux.cfg
+mkdir /mnt/usb/boot
+cp linux/arch/x86/boot/bzImage /mnt/usb/boot/webboot
+cp /tmp/initramfs.linux_amd64.cpio.gz /mnt/usb/boot/webboot.cpio.gz
+```
+
+Finally, we need to create a `/Images` directory at the root of the usb stick. Note that the "I" in "Images" needs to be capitalized.
+
+```sh
+mkdir /mnt/usb/Images
+```
+
+You should be able to boot from the USB stick now. Depending on your firmware
+setup, it might be necessary to get into a boot menu or make changes in the
+settings.
+
+To rebuild the USB stick, you can run
+```sh
+sh makeusb.sh sdb1
+```
diff --git a/webboot/RR b/webboot/RR
new file mode 100644
index 000000000..18ae30f21
--- /dev/null
+++ b/webboot/RR
@@ -0,0 +1,15 @@
+RAM_SIZE=${RAM_SIZE:=4G}
+KERNEL=${KERNEL:=linux/arch/x86/boot/bzImage}
+INITRD=${INITRD:=/tmp/initramfs.linux_amd64.cpio}
+
+/usr/bin/qemu-system-x86_64 \
+ -machine q35 \
+ -m $RAM_SIZE \
+ -object rng-random,filename=/dev/urandom,id=rng0 \
+ -device virtio-rng-pci,rng=rng0 \
+ -netdev user,id=u1 -device rtl8139,netdev=u1 \
+ -kernel $KERNEL \
+ -initrd $INITRD \
+ -vga std \
+ -append "earlyprintk=ttyS0,115200,keep console=tty0 vga=ask" \
+ -serial stdio
diff --git a/webboot/ci.sh b/webboot/ci.sh
new file mode 100755
index 000000000..d73e512f3
--- /dev/null
+++ b/webboot/ci.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+set -e
+
+# Check that the code has been formatted correctly.
+GOFMT_DIFF=$(gofmt -s -d *.go pkg cmds)
+if [[ -n "${GOFMT_DIFF}" ]]; then
+ echo 'Error: Go source code is not formatted:'
+ printf '%s\n' "${GOFMT_DIFF}"
+ echo 'Run `gofmt -s -w *.go pkg cmds'
+ exit 1
+fi
+
+go build .
+go run webboot.go --wpa-version=2.9
+if [ ! -f "/tmp/initramfs.linux_amd64.cpio" ]; then
+ echo "Initrd was not created."
+ exit 1
+fi
+
+(cd cmds/webboot && go test -v)
+(cd pkg/menu && go test -v)
+(cd pkg/bootiso && sudo -E env "PATH=$PATH" go test -v) # need sudo to mount the test iso
diff --git a/webboot/cmds/cli/ci.json b/webboot/cmds/cli/ci.json
new file mode 100644
index 000000000..20ac07928
--- /dev/null
+++ b/webboot/cmds/cli/ci.json
@@ -0,0 +1,158 @@
+{
+"Arch":{
+ "isoPattern":"^archlinux-.+",
+ "checksum":"a0862c8189290e037ff156b93c60d6150b9363b3",
+ "checksumType":"sha1",
+ "kernelParams":"img_dev=/dev/disk/by-uuid/{{.UUID}} img_loop={{.IsoPath}}",
+ "customConfigs":[{
+ "Label":"Default Config",
+ "KernelPath":"/arch/boot/x86_64/vmlinuz-linux",
+ "InitrdPath":"/arch/boot/x86_64/archiso.img",
+ "Cmdline":""
+ }],
+ "mirrors":[{
+ "name":"Default",
+ "url":"http://mirrors.acm.wpi.edu/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name":"Arizona",
+ "url":"http://mirror.arizona.edu/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name": "Purdue University",
+ "url": "https://plug-mirror.rcac.purdue.edu/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name": "Constant.com",
+ "url": "http://arch.mirror.constant.com/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name": "Georgia Institute of Technology",
+ "url": "http://www.gtlib.gatech.edu/pub/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ }]
+},
+"CentOS 7":{
+ "isoPattern":"^CentOS-7.+",
+ "checksum":"689531cce9cf484378481ae762fae362791a9be078fda10e4f6977bf8fa71350",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams": "iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://sjc.edge.kernel.org/centos/7/isos/x86_64/CentOS-7-x86_64-Everything-2009.iso"
+ }]
+},
+"CentOS 8":{
+ "isoPattern":"^CentOS-8.+",
+ "checksum":"c79921e24d472144d8f36a0d5f409b12bd016d9d7d022fd703563973ca9c375c",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://sjc.edge.kernel.org/centos/8/isos/x86_64/CentOS-8.4.2105-x86_64-boot.iso"
+ }]
+},
+"Debian":{
+ "isoPattern":"^debian-.+",
+ "checksum":"9b199cb94dab3906d4a414b084572e1ce10f6449b1b20d136cee7e561e19c3ea",
+ "checksumType":"sha256",
+ "bootConfig":"syslinux",
+ "kernelParams":"findiso={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-10.10.0-amd64-xfce.iso"
+ }]
+},
+"Fedora":{
+ "isoPattern":"^Fedora-.+",
+ "checksum":"4d0f6653e2e0860c99ffe0ef274a46d875fb85bd2a40cb896dce1ed013566924",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://download.fedoraproject.org/pub/fedora/linux/releases/32/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-32-1.6.iso"
+ }]
+},
+"Kali":{
+ "isoPattern":"^kali-linux-.+",
+ "checksum":"1a0b2ea83f48861dd3f3babd5a2892a14b30a7234c8c9b5013a6507d1401874f",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"findiso={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://cdimage.kali.org/kali-2020.3/kali-linux-2020.3-live-amd64.iso"
+ }]
+},
+"Linux Mint":{
+ "isoPattern":"^linuxmint-.+",
+ "checksum":"2f6ae466ec9b7c6255e997b82f162ae88bfe640a8df16d3e2f495b6281120af9",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"http://mirrors.kernel.org/linuxmint/stable/20/linuxmint-20-cinnamon-64bit.iso"
+ }]
+},
+"Manjaro":{
+ "isoPattern":"^manjaro-.+",
+ "checksum":"fab9d1bdd03a7e5daab226ccc8e16ba96a5b07e9",
+ "checksumType":"sha1",
+ "kernelParams":"img_dev=/dev/disk/by-uuid/{{.UUID}} img_loop={{.IsoPath}}",
+ "customConfigs":[{
+ "Label":"Default Config",
+ "KernelPath":"/boot/vmlinuz-x86_64",
+ "InitrdPath":"/boot/initramfs-x86_64.img",
+ "Cmdline":"driver=free tz=utc lang=en_US keytable=en"
+ }],
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://download.manjaro.org/xfce/21.0.6/manjaro-xfce-21.0.6-210607-linux510.iso"
+ }]
+},
+"TinyCore":{
+ "isoPattern":".*CorePure64-.+",
+ "checksum":"58bc33523ce10e64f56b9a9ec8a77531",
+ "checksumType":"md5",
+ "bootConfig":"syslinux",
+ "kernelParams":"iso=UUID={{.UUID}}{{.IsoPath}} console=ttyS0 earlyprintk=ttyS0",
+ "mirrors":[{
+ "name":"Default",
+ "url":"http://tinycorelinux.net/11.x/x86_64/release/TinyCorePure64-11.1.iso"
+ }]
+},
+"Ubuntu":{
+ "isoPattern":"^ubuntu-.+",
+ "checksum":"b45165ed3cd437b9ffad02a2aad22a4ddc69162470e2622982889ce5826f6e3d",
+ "checksumType":"sha256",
+ "bootConfig":"syslinux",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://releases.ubuntu.com/20.04.1/ubuntu-20.04.1-desktop-amd64.iso"
+ },
+ {
+ "name":"Constant.com",
+ "url":"http://isos.ubuntu.mirror.constant.com/20.04/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"Rochester Institute of Technology",
+ "url":"http://mirrors.rit.edu/ubuntu-releases/20.04/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"Purdue University",
+ "url":"http://osmirrors.cerias.purdue.edu/pub/ubuntu-releases/20.04/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"University of Utah",
+ "url":"http://ubuntu.cs.utah.edu/releases/focal/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"Washington State University",
+ "url":"http://mirrors.vcea.wsu.edu/ubuntu-releases/focal/ubuntu-20.04.2.0-desktop-amd64.iso"
+ }]
+}
+}
diff --git a/webboot/cmds/cli/main.go b/webboot/cmds/cli/main.go
new file mode 100644
index 000000000..f1200b2d9
--- /dev/null
+++ b/webboot/cmds/cli/main.go
@@ -0,0 +1,179 @@
+// Package main downloads and boots an ISO.
+package main
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "html/template"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "path/filepath"
+
+ "github.com/u-root/u-root/pkg/boot"
+ "github.com/u-root/webboot/pkg/bootiso"
+ "github.com/u-root/webboot/pkg/menu"
+)
+
+var (
+ v = flag.Bool("verbose", false, "Verbose output")
+ verbose = func(string, ...interface{}) {}
+ dir = flag.String("dir", "", "Path of cached directory")
+ dryRun = flag.Bool("dryrun", false, "If dry_run is true we won't boot the iso.")
+ distroName = flag.String("distroName", "", "This is the distro that will be tested.")
+ cacheDev CacheDevice
+ logBuffer bytes.Buffer
+ tmpBuffer bytes.Buffer
+)
+
+// ISO's exec downloads the iso and boot it.
+func (i *ISO) exec(enableBoot bool) error {
+ verbose("Intent to boot %s", i.path)
+
+ distro, ok := supportedDistros[*distroName]
+ if !ok {
+ return fmt.Errorf("Could not infer ISO type based on filename.")
+ }
+
+ verbose("Using distro %s with boot config %s", *distroName, distro.BootConfig)
+
+ var configs []boot.OSImage
+ if distro.BootConfig != "" {
+ parsedConfigs, err := bootiso.ParseConfigFromISO(i.path, distro.BootConfig)
+ if err != nil {
+ return err
+ }
+
+ configs = append(configs, parsedConfigs...)
+ }
+
+ if len(distro.CustomConfigs) != 0 {
+ customConfigs, err := bootiso.LoadCustomConfigs(i.path, distro.CustomConfigs)
+ if err != nil {
+ return err
+ }
+
+ configs = append(configs, customConfigs...)
+ }
+
+ if len(configs) == 0 {
+ return fmt.Errorf("No valid configs were found.")
+ }
+
+ verbose("Get configs: %+v", configs)
+
+ entries := []menu.Entry{}
+ for _, config := range configs {
+ entries = append(entries, &BootConfig{config})
+ }
+
+ config, ok := entries[0].(*BootConfig)
+ if !ok {
+ return fmt.Errorf("Could not convert selection to a boot image.")
+ }
+
+ paramTemplate, err := template.New("template").Parse(distro.KernelParams)
+ if err != nil {
+ return err
+ }
+
+ var kernelParams bytes.Buffer
+ if err = paramTemplate.Execute(&kernelParams, cacheDev); err != nil {
+ return err
+ }
+
+ if !enableBoot {
+ s := fmt.Sprintf("config.image %s, kernelparams.String() %s", config.image, kernelParams.String())
+ return fmt.Errorf("Booting is disabled (see --dryrun flag), but otherwise would be [%s].", s)
+ }
+ err = bootiso.BootCachedISO(config.image, kernelParams.String()+" waitusb=10")
+
+ // If kexec succeeds, we should not arrive here
+ if err == nil {
+ // TODO: We should know whether we tried using /sbin/kexec.
+ err = fmt.Errorf("kexec failed, but gave no error. Consider trying kexec-tools.")
+ }
+
+ return err
+}
+
+// DownloadOption's exec lets user input the name of the iso they want
+// if this iso is existed in the bookmark, use it's url
+// elsewise ask for a download link
+func (d *DownloadOption) exec() (menu.Entry, error) {
+
+ link := supportedDistros[*distroName].Mirrors[0].Url
+
+ filename := path.Base(link)
+
+ // If the cachedir is not find, downloaded the iso to /tmp, else create a Downloaded dir in the cache dir.
+ var fpath string
+ var downloadDir string
+ var err error
+
+ downloadDir = os.TempDir()
+ fpath = filepath.Join(downloadDir, filename)
+
+ if err = download(link, fpath, downloadDir); err != nil {
+ if err == context.Canceled {
+ return nil, fmt.Errorf("Download was canceled.")
+ } else {
+ return nil, err
+ }
+ }
+
+ return &ISO{label: filename, path: fpath}, nil
+}
+
+// distroData downloads and parses the data in distros.json to a map[string]Distro.
+func distroData() error {
+ jsonPath := "/ci.json"
+
+ // Parse the json file.
+ data, err := ioutil.ReadFile(jsonPath)
+ if err != nil {
+ return fmt.Errorf("Could not read JSON file: %v\n", err)
+ }
+
+ err = json.Unmarshal([]byte(data), &supportedDistros)
+ if err != nil {
+ return fmt.Errorf("Could not unmarshal JSON file: %v\n", err)
+ }
+
+ return nil
+}
+
+func main() {
+ flag.Parse()
+ if flag.NArg() != 0 {
+ fmt.Errorf("Unexpected positional arguments: %v", flag.Args())
+ }
+ if *v {
+ verbose = log.Printf
+ }
+
+ var err error
+ var entry menu.Entry
+
+ // get distro data
+ err = distroData()
+ if err != nil {
+ log.Fatalf("Error on distroData(): %v", err.Error())
+ }
+
+ // DownloadOption
+ entry = &DownloadOption{}
+ entry, err = entry.(*DownloadOption).exec()
+ if err != nil {
+ log.Fatalf("Error on (*DownloadOption).exec(): %v", err.Error())
+ }
+
+ // ISO
+ if err = entry.(*ISO).exec(!*dryRun); err != nil {
+ log.Fatalf("Error on (*ISO).exec(): %v", err.Error())
+ }
+}
diff --git a/webboot/cmds/cli/types.go b/webboot/cmds/cli/types.go
new file mode 100644
index 000000000..2322ab043
--- /dev/null
+++ b/webboot/cmds/cli/types.go
@@ -0,0 +1,111 @@
+package main
+
+import (
+ "github.com/u-root/u-root/pkg/boot"
+ "github.com/u-root/u-root/pkg/mount/block"
+ "github.com/u-root/webboot/pkg/bootiso"
+ "github.com/u-root/webboot/pkg/menu"
+)
+
+type Distro struct {
+ IsoPattern string
+ Checksum string
+ ChecksumType string
+ BootConfig string
+ KernelParams string
+ CustomConfigs []bootiso.Config
+ Mirrors []Mirror
+}
+
+type Mirror struct {
+ Name string
+ Url string
+}
+
+func (m *Mirror) Label() string {
+ return m.Name
+}
+
+var supportedDistros = map[string]Distro{}
+
+type CacheDevice struct {
+ Name string
+ UUID string
+ MountPoint string
+ IsoPath string // set after iso is selected
+}
+
+func NewCacheDevice(device *block.BlockDev, mountPoint string) CacheDevice {
+ return CacheDevice{
+ Name: device.Name,
+ UUID: device.FsUUID,
+ MountPoint: mountPoint,
+ }
+}
+
+// ISO contains information of the iso user wants to boot.
+type ISO struct {
+ label string
+ path string
+ checksum string
+}
+
+var _ = menu.Entry(&ISO{})
+
+// Label is the string this iso displays in the menu page.
+func (i *ISO) Label() string {
+ return i.label
+}
+
+// Config represents one kind of configure of booting an iso.
+type Config struct {
+ label string
+}
+
+var _ = menu.Entry(&Config{})
+
+// Label is the string this iso displays in the menu page.
+func (c *Config) Label() string {
+ return c.label
+}
+
+// DownloadOption lets the user download an iso then boot it.
+type DownloadOption struct {
+}
+
+var _ = menu.Entry(&DownloadOption{})
+
+// Label is the string this iso displays in the menu page.
+func (d *DownloadOption) Label() string {
+ return "Download an ISO"
+}
+
+// DirOption represents a directory under cache directory.
+// It displays its sub-directory or iso files.
+type DirOption struct {
+ label string
+ path string
+}
+
+var _ = menu.Entry(&DirOption{})
+
+// Label is the string this option displays in the menu page.
+func (d *DirOption) Label() string {
+ return d.label
+}
+
+type Interface struct {
+ label string
+}
+
+func (i *Interface) Label() string {
+ return i.label
+}
+
+type BootConfig struct {
+ image boot.OSImage
+}
+
+func (b *BootConfig) Label() string {
+ return b.image.Label()
+}
diff --git a/webboot/cmds/cli/utils.go b/webboot/cmds/cli/utils.go
new file mode 100644
index 000000000..e4109d035
--- /dev/null
+++ b/webboot/cmds/cli/utils.go
@@ -0,0 +1,96 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "sort"
+
+ "github.com/u-root/webboot/pkg/menu"
+)
+
+// WriteCounter counts the number of bytes written to it. It implements an io.Writer
+type WriteCounter struct {
+ received float64
+ expected float64
+ progress menu.Progress
+}
+
+func NewWriteCounter(expectedSize int64) WriteCounter {
+ return WriteCounter{0, float64(expectedSize), menu.NewProgress("", false)}
+}
+
+func (wc *WriteCounter) Write(p []byte) (int, error) {
+ n := len(p)
+ wc.received += float64(n)
+ wc.progress.Update(fmt.Sprintf("Downloading... %.2f%% (%.3f MB)\n\nPress to cancel.", 100*(wc.received/wc.expected), wc.received/1000000))
+ return n, nil
+}
+
+func (wc *WriteCounter) Close() {
+ wc.progress.Close()
+}
+
+// download() will download a file from URL and save it to a temp file
+// If the download succeeds, the temp file will be copied to fPath
+func download(URL, fPath, downloadDir string) error {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ req, err := http.NewRequestWithContext(ctx, "GET", URL, nil)
+ if err != nil {
+ return err
+ }
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode != 200 {
+ return fmt.Errorf("Received http status code %s", resp.Status)
+ }
+ defer resp.Body.Close()
+
+ tempFile, err := ioutil.TempFile(downloadDir, "iso-download-")
+ if err != nil {
+ return err
+ }
+ defer os.Remove(tempFile.Name())
+
+ counter := NewWriteCounter(resp.ContentLength)
+
+ if _, err = io.Copy(tempFile, io.TeeReader(resp.Body, &counter)); err != nil {
+ counter.Close()
+ return err
+ }
+
+ counter.Close()
+
+ if _, err = tempFile.Seek(0, 0); err != nil {
+ return err
+ }
+
+ err = os.Rename(tempFile.Name(), fPath)
+ if err != nil {
+ return fmt.Errorf("Error on os.Rename: %v", err)
+ }
+
+ verbose("%q is downloaded at %q\n", URL, fPath)
+ return nil
+}
+
+func supportedDistroEntries() []menu.Entry {
+ entries := []menu.Entry{}
+ for distroName := range supportedDistros {
+ entries = append(entries, &Config{label: distroName})
+ }
+
+ sort.Slice(entries[:], func(i, j int) bool {
+ return entries[i].Label() < entries[j].Label()
+ })
+
+ return entries
+}
diff --git a/webboot/cmds/webboot/Readme.md b/webboot/cmds/webboot/Readme.md
new file mode 100644
index 000000000..e803c2856
--- /dev/null
+++ b/webboot/cmds/webboot/Readme.md
@@ -0,0 +1,21 @@
+### Usage
+The webboot program would do the following:
+ - Present a menu with the existing cached distro options
+ - If the user wants a distro that is not cached, they can download an ISO
+ - After the user decides on an ISO, boot it.
+
+### Test
+Our UI uses a package called Termui. Termui will parse the standard input into keyboard events and insert them into a channel, then from which the Termui get it's input. For implement a unattended test, I manually build a series of keyboard events that reperesent my intented input for test, and insert them into a channel. Then I replace the original input channel with my channel in the test. So the go test could run a test of ui automatically.
+
+See TestDownloadOption for an example:
+ - create a channel by make(chan ui.Event).
+ - use go pressKey(uiEvents, input) to translate the intented test input to keyboard events and push them to the uiEvents chanel.
+ - use the uiEvents channel by call downloadOption.exec(uiEvents). (Main function will always call ui.PollEvents() to get the sandard input channel)
+ - all functions involving in ui input will provide a argument to indicate the input chanel.
+
+ ### Hint
+ If want to set up a cached directory in side the USB stick, the file structure of USB stick should be
++-- USB root
+| +-- Images (<--- the cache directory. It must be named as "Images")
+| +-- subdirectories or iso files
+...
\ No newline at end of file
diff --git a/webboot/cmds/webboot/distros.json b/webboot/cmds/webboot/distros.json
new file mode 100644
index 000000000..d2bb358c1
--- /dev/null
+++ b/webboot/cmds/webboot/distros.json
@@ -0,0 +1,176 @@
+{
+"Arch":{
+ "isoPattern":"^archlinux-.+",
+ "checksum":"a0862c8189290e037ff156b93c60d6150b9363b3",
+ "checksumType":"sha1",
+ "kernelParams":"img_dev=/dev/disk/by-uuid/{{.UUID}} img_loop={{.IsoPath}}",
+ "customConfigs":[{
+ "Label":"Default Config",
+ "KernelPath":"/arch/boot/x86_64/vmlinuz-linux",
+ "InitrdPath":"/arch/boot/x86_64/archiso.img",
+ "Cmdline":""
+ }],
+ "mirrors":[{
+ "name":"Default",
+ "url":"http://mirrors.acm.wpi.edu/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name":"Arizona",
+ "url":"http://mirror.arizona.edu/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name": "Purdue University",
+ "url": "https://plug-mirror.rcac.purdue.edu/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name": "Constant.com",
+ "url": "http://arch.mirror.constant.com/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ },
+ {
+ "name": "Georgia Institute of Technology",
+ "url": "http://www.gtlib.gatech.edu/pub/archlinux/iso/2021.09.01/archlinux-2021.09.01-x86_64.iso"
+ }]
+},
+"CentOS 7":{
+ "isoPattern":"^CentOS-7.+",
+ "checksum":"689531cce9cf484378481ae762fae362791a9be078fda10e4f6977bf8fa71350",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams": "iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://sjc.edge.kernel.org/centos/7/isos/x86_64/CentOS-7-x86_64-Everything-2009.iso"
+ }]
+},
+"CentOS 8":{
+ "isoPattern":"^CentOS-8.+",
+ "checksum":"c79921e24d472144d8f36a0d5f409b12bd016d9d7d022fd703563973ca9c375c",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://sjc.edge.kernel.org/centos/8/isos/x86_64/CentOS-8.4.2105-x86_64-boot.iso"
+ }]
+},
+"Debian":{
+ "isoPattern":"^debian-.+",
+ "checksum":"9b199cb94dab3906d4a414b084572e1ce10f6449b1b20d136cee7e561e19c3ea",
+ "checksumType":"sha256",
+ "bootConfig":"syslinux",
+ "kernelParams":"findiso={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-10.10.0-amd64-xfce.iso"
+ }]
+},
+"Fedora":{
+ "isoPattern":"^Fedora-.+",
+ "checksum":"4d0f6653e2e0860c99ffe0ef274a46d875fb85bd2a40cb896dce1ed013566924",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://download.fedoraproject.org/pub/fedora/linux/releases/32/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-32-1.6.iso"
+ }]
+},
+"Kali":{
+ "isoPattern":"^kali-linux-.+",
+ "checksum":"1a0b2ea83f48861dd3f3babd5a2892a14b30a7234c8c9b5013a6507d1401874f",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"findiso={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://cdimage.kali.org/kali-2020.3/kali-linux-2020.3-live-amd64.iso"
+ }]
+},
+"Linux Mint":{
+ "isoPattern":"^linuxmint-.+",
+ "checksum":"2f6ae466ec9b7c6255e997b82f162ae88bfe640a8df16d3e2f495b6281120af9",
+ "checksumType":"sha256",
+ "bootConfig":"grub",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"http://mirrors.kernel.org/linuxmint/stable/20/linuxmint-20-cinnamon-64bit.iso"
+ }]
+},
+"Manjaro":{
+ "isoPattern":"^manjaro-.+",
+ "checksum":"fab9d1bdd03a7e5daab226ccc8e16ba96a5b07e9",
+ "checksumType":"sha1",
+ "kernelParams":"img_dev=/dev/disk/by-uuid/{{.UUID}} img_loop={{.IsoPath}}",
+ "customConfigs":[{
+ "Label":"Default Config",
+ "KernelPath":"/boot/vmlinuz-x86_64",
+ "InitrdPath":"/boot/initramfs-x86_64.img",
+ "Cmdline":"driver=free tz=utc lang=en_US keytable=en"
+ }],
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://download.manjaro.org/xfce/21.0.6/manjaro-xfce-21.0.6-210607-linux510.iso"
+ }]
+},
+"TinyCore":{
+ "isoPattern":".*CorePure64-.+",
+ "checksum":"58bc33523ce10e64f56b9a9ec8a77531",
+ "checksumType":"md5",
+ "bootConfig":"syslinux",
+ "kernelParams":"iso=UUID={{.UUID}}{{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"http://tinycorelinux.net/11.x/x86_64/release/TinyCorePure64-11.1.iso"
+ }]
+},
+"LHSCowboys":{
+ "isoPattern":".*CorePure64-.+",
+ "bootConfig":"syslinux",
+ "kernelParams":"iso=UUID={{.UUID}}{{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://github.com/u-root/webboot-distro/raw/master/iso/tinycore/10.x/x86_64/release/LHSCowboys.iso"
+ }]
+},
+"DHSGaels":{
+ "isoPattern":".*CorePure64-.+",
+ "bootConfig":"syslinux",
+ "kernelParams":"iso=UUID={{.UUID}}{{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://github.com/u-root/webboot-distro/raw/master/iso/tinycore/10.x/x86_64/release/LHSCowboys.iso"
+ }]
+},
+"Ubuntu":{
+ "isoPattern":"^ubuntu-.+",
+ "checksum":"b45165ed3cd437b9ffad02a2aad22a4ddc69162470e2622982889ce5826f6e3d",
+ "checksumType":"sha256",
+ "bootConfig":"syslinux",
+ "kernelParams":"iso-scan/filename={{.IsoPath}}",
+ "mirrors":[{
+ "name":"Default",
+ "url":"https://releases.ubuntu.com/20.04.1/ubuntu-20.04.1-desktop-amd64.iso"
+ },
+ {
+ "name":"Constant.com",
+ "url":"http://isos.ubuntu.mirror.constant.com/20.04/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"Rochester Institute of Technology",
+ "url":"http://mirrors.rit.edu/ubuntu-releases/20.04/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"Purdue University",
+ "url":"http://osmirrors.cerias.purdue.edu/pub/ubuntu-releases/20.04/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"University of Utah",
+ "url":"http://ubuntu.cs.utah.edu/releases/focal/ubuntu-20.04.2.0-desktop-amd64.iso"
+ },
+ {
+ "name":"Washington State University",
+ "url":"http://mirrors.vcea.wsu.edu/ubuntu-releases/focal/ubuntu-20.04.2.0-desktop-amd64.iso"
+ }]
+}
+}
diff --git a/webboot/cmds/webboot/network.go b/webboot/cmds/webboot/network.go
new file mode 100644
index 000000000..d40a73105
--- /dev/null
+++ b/webboot/cmds/webboot/network.go
@@ -0,0 +1,167 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "os"
+ "time"
+
+ ui "github.com/gizak/termui/v3"
+ "github.com/u-root/webboot/pkg/menu"
+ "github.com/u-root/webboot/pkg/wifi"
+ "github.com/vishvananda/netlink"
+)
+
+// Collect stdout and stderr from the network setup.
+// Declare globally because wifi.Connect() triggers
+// go routines that might still be running after return.
+var wifiStdout, wifiStderr bytes.Buffer
+
+func connected() bool {
+ client := http.Client{
+ Timeout: 10 * time.Second,
+ }
+
+ if _, err := client.Get("http://google.com"); err != nil {
+ return false
+ }
+ return true
+}
+
+func wirelessIfaceEntries() ([]menu.Entry, error) {
+ interfaces, err := netlink.LinkList()
+ if err != nil {
+ return nil, err
+ }
+
+ var ifEntries []menu.Entry
+ for _, iface := range interfaces {
+ if interfaceIsWireless(iface.Attrs().Name) {
+ ifEntries = append(ifEntries, &Interface{label: iface.Attrs().Name})
+ }
+ }
+ return ifEntries, nil
+}
+
+func interfaceIsWireless(ifname string) bool {
+ devPath := fmt.Sprintf("/sys/class/net/%s/wireless", ifname)
+ if _, err := os.Stat(devPath); err != nil {
+ return false
+ }
+ return true
+}
+
+func setupNetwork(uiEvents <-chan ui.Event, menus chan<- string) error {
+ iface, err := selectNetworkInterface(uiEvents, menus)
+ if err != nil {
+ return err
+ }
+
+ return selectWirelessNetwork(uiEvents, menus, iface.Label())
+}
+
+func selectNetworkInterface(uiEvents <-chan ui.Event, menus chan<- string) (menu.Entry, error) {
+ ifEntries, err := wirelessIfaceEntries()
+ if err != nil {
+ return nil, err
+ }
+
+ iface, err := menu.PromptMenuEntry("Network Interfaces", "Choose an option", ifEntries, uiEvents, menus)
+ if err != nil {
+ return nil, err
+ }
+
+ return iface, nil
+}
+
+func selectWirelessNetwork(uiEvents <-chan ui.Event, menus chan<- string, iface string) error {
+ worker, err := wifi.NewIWLWorker(&wifiStdout, &wifiStderr, iface)
+ if err != nil {
+ return err
+ }
+
+ for {
+ progress := menu.NewProgress("Scanning for wifi networks", true)
+ networkScan, err := worker.Scan(&wifiStdout, &wifiStderr)
+ progress.Close()
+ if err != nil {
+ return err
+ }
+
+ netEntries := []menu.Entry{}
+ for _, network := range networkScan {
+ netEntries = append(netEntries, &Network{info: network})
+ }
+
+ entry, err := menu.PromptMenuEntry("Wireless Networks", "Choose an option", netEntries, uiEvents, menus)
+ if err != nil {
+ return err
+ }
+
+ network, ok := entry.(*Network)
+ if !ok {
+ return fmt.Errorf("Bad menu entry.")
+ }
+
+ if err := connectWirelessNetwork(uiEvents, menus, worker, network.info); err != nil {
+ switch err {
+ case menu.ExitRequest: // user typed to exit
+ return err
+ case menu.BackRequest: // user typed to go back
+ continue
+ default: // connection error
+ menu.DisplayResult([]string{err.Error()}, uiEvents, menus)
+ continue
+ }
+ }
+
+ return nil
+ }
+}
+
+func connectWirelessNetwork(uiEvents <-chan ui.Event, menus chan<- string, worker wifi.WiFi, network wifi.Option) error {
+ var setupParams = []string{network.Essid}
+ authSuite := network.AuthSuite
+
+ if authSuite == wifi.NotSupportedProto {
+ return fmt.Errorf("Security protocol is not supported.")
+ } else if authSuite == wifi.WpaPsk || authSuite == wifi.WpaEap {
+ credentials, err := enterCredentials(uiEvents, menus, authSuite)
+ if err != nil {
+ return err
+ }
+ setupParams = append(setupParams, credentials...)
+ }
+
+ progress := menu.NewProgress("Connecting to network", true)
+ err := worker.Connect(&wifiStdout, &wifiStderr, setupParams...)
+ progress.Close()
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func enterCredentials(uiEvents <-chan ui.Event, menus chan<- string, authSuite wifi.SecProto) ([]string, error) {
+ var credentials []string
+ pass, err := menu.PromptTextInput("Enter password:", menu.AlwaysValid, uiEvents, menus)
+ if err != nil {
+ return nil, err
+ }
+
+ credentials = append(credentials, pass)
+ if authSuite == wifi.WpaPsk {
+ return credentials, nil
+ }
+
+ // If not WpaPsk, the network uses WpaEap and also needs an identity
+ identity, err := menu.PromptTextInput("Enter identity:", menu.AlwaysValid, uiEvents, menus)
+ if err != nil {
+ return nil, err
+ }
+
+ credentials = append(credentials, identity)
+ return credentials, nil
+}
diff --git a/webboot/cmds/webboot/testdata/dirlevel1/fakeDistro.iso b/webboot/cmds/webboot/testdata/dirlevel1/fakeDistro.iso
new file mode 100644
index 000000000..85e8b40dd
--- /dev/null
+++ b/webboot/cmds/webboot/testdata/dirlevel1/fakeDistro.iso
@@ -0,0 +1 @@
+This is a fake ISO.
diff --git a/webboot/cmds/webboot/types.go b/webboot/cmds/webboot/types.go
new file mode 100644
index 000000000..c5602df51
--- /dev/null
+++ b/webboot/cmds/webboot/types.go
@@ -0,0 +1,132 @@
+package main
+
+import (
+ "fmt"
+
+ "github.com/u-root/u-root/pkg/boot"
+ "github.com/u-root/u-root/pkg/mount/block"
+ "github.com/u-root/webboot/pkg/bootiso"
+ "github.com/u-root/webboot/pkg/menu"
+ "github.com/u-root/webboot/pkg/wifi"
+)
+
+type Distro struct {
+ IsoPattern string
+ Checksum string
+ ChecksumType string
+ BootConfig string
+ KernelParams string
+ CustomConfigs []bootiso.Config
+ Mirrors []Mirror
+}
+
+type Mirror struct {
+ Name string
+ Url string
+}
+
+func (m *Mirror) Label() string {
+ return m.Name
+}
+
+var supportedDistros = map[string]Distro{}
+
+type CacheDevice struct {
+ Name string
+ UUID string
+ MountPoint string
+ IsoPath string // set after iso is selected
+}
+
+func NewCacheDevice(device *block.BlockDev, mountPoint string) CacheDevice {
+ return CacheDevice{
+ Name: device.Name,
+ UUID: device.FsUUID,
+ MountPoint: mountPoint,
+ }
+}
+
+// ISO contains information of the iso user wants to boot.
+type ISO struct {
+ label string
+ path string
+ checksum string
+}
+
+var _ = menu.Entry(&ISO{})
+
+// Label is the string this iso displays in the menu page.
+func (i *ISO) Label() string {
+ return i.label
+}
+
+// Config represents one kind of configure of booting an iso.
+type Config struct {
+ label string
+}
+
+var _ = menu.Entry(&Config{})
+
+// Label is the string this iso displays in the menu page.
+func (c *Config) Label() string {
+ return c.label
+}
+
+// DownloadOption lets the user download an iso then boot it.
+type DownloadOption struct {
+}
+
+var _ = menu.Entry(&DownloadOption{})
+
+// Label is the string this iso displays in the menu page.
+func (d *DownloadOption) Label() string {
+ return "Download an ISO"
+}
+
+// DirOption represents a directory under cache directory.
+// It displays its sub-directory or iso files.
+type DirOption struct {
+ label string
+ path string
+}
+
+var _ = menu.Entry(&DirOption{})
+
+// Label is the string this option displays in the menu page.
+func (d *DirOption) Label() string {
+ return d.label
+}
+
+type Interface struct {
+ label string
+}
+
+func (i *Interface) Label() string {
+ return i.label
+}
+
+type Network struct {
+ info wifi.Option
+}
+
+func (n *Network) Label() string {
+ switch n.info.AuthSuite {
+ case wifi.NoEnc:
+ return fmt.Sprintf("%s: No Passphrase\n", n.info.Essid)
+ case wifi.WpaPsk:
+ return fmt.Sprintf("%s: WPA-PSK (only passphrase)\n", n.info.Essid)
+ case wifi.WpaEap:
+ return fmt.Sprintf("%s: WPA-EAP (passphrase and identity)\n", n.info.Essid)
+ case wifi.NotSupportedProto:
+ return fmt.Sprintf("%s: Not a supported protocol\n", n.info.Essid)
+ }
+ return "Invalid wifi network."
+}
+
+type BootConfig struct {
+ image boot.OSImage
+}
+
+func (b *BootConfig) Label() string {
+ return b.image.Label()
+}
diff --git a/webboot/cmds/webboot/utils.go b/webboot/cmds/webboot/utils.go
new file mode 100644
index 000000000..d02294daa
--- /dev/null
+++ b/webboot/cmds/webboot/utils.go
@@ -0,0 +1,142 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "regexp"
+ "sort"
+
+ ui "github.com/gizak/termui/v3"
+ "github.com/u-root/webboot/pkg/menu"
+)
+
+// WriteCounter counts the number of bytes written to it. It implements an io.Writer
+type WriteCounter struct {
+ received float64
+ expected float64
+ progress menu.Progress
+}
+
+func NewWriteCounter(expectedSize int64) WriteCounter {
+ return WriteCounter{0, float64(expectedSize), menu.NewProgress("", false)}
+}
+
+func (wc *WriteCounter) Write(p []byte) (int, error) {
+ n := len(p)
+ wc.received += float64(n)
+ wc.progress.Update(fmt.Sprintf("Downloading... %.2f%% (%.3f MB)\n\nPress to cancel.", 100*(wc.received/wc.expected), wc.received/1000000))
+ return n, nil
+}
+
+func (wc *WriteCounter) Close() {
+ wc.progress.Close()
+}
+
+// download() will download a file from URL and save it to a temp file
+// If the download succeeds, the temp file will be copied to fPath
+func download(URL, fPath, downloadDir string, uiEvents <-chan ui.Event) error {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ req, err := http.NewRequestWithContext(ctx, "GET", URL, nil)
+ if err != nil {
+ return err
+ }
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode != 200 {
+ return fmt.Errorf("Received http status code %s", resp.Status)
+ }
+ defer resp.Body.Close()
+
+ tempFile, err := ioutil.TempFile(downloadDir, "iso-download-")
+ if err != nil {
+ return err
+ }
+ defer os.Remove(tempFile.Name())
+
+ go listenForCancel(ctx, cancel, uiEvents)
+ counter := NewWriteCounter(resp.ContentLength)
+
+ if _, err = io.Copy(tempFile, io.TeeReader(resp.Body, &counter)); err != nil {
+ counter.Close()
+ return err
+ }
+
+ counter.Close()
+ copyProgress := menu.NewProgress(fmt.Sprintf("Download complete. Writing ISO to cache (%q)", fPath), true)
+ defer copyProgress.Close()
+
+ if _, err = tempFile.Seek(0, 0); err != nil {
+ return err
+ }
+
+ err = os.Rename(tempFile.Name(), fPath)
+ if err != nil {
+ return fmt.Errorf("Error on os.Rename: %v", err)
+ }
+
+ verbose("%q is downloaded at %q\n", URL, fPath)
+ return nil
+}
+
+func listenForCancel(ctx context.Context, cancel context.CancelFunc, uiEvents <-chan ui.Event) {
+ for {
+ select {
+ case k := <-uiEvents:
+ if k.ID == "" {
+ cancel()
+ return
+ }
+ case <-ctx.Done():
+ return
+ }
+ }
+}
+
+func inferIsoType(isoName string, supportedDistros map[string]Distro) string {
+ for distroName, distroInfo := range supportedDistros {
+ match, _ := regexp.MatchString(distroInfo.IsoPattern, isoName)
+ if match {
+ return distroName
+ }
+ }
+ return ""
+}
+
+func supportedDistroEntries() []menu.Entry {
+ entries := []menu.Entry{}
+ for distroName := range supportedDistros {
+ entries = append(entries, &Config{label: distroName})
+ }
+
+ sort.Slice(entries[:], func(i, j int) bool {
+ return entries[i].Label() < entries[j].Label()
+ })
+
+ return entries
+}
+
+func validURL(url string, ext string) (string, string, bool) {
+ match, _ := regexp.MatchString(fmt.Sprintf("^https*://.+\\.%s$", ext), url)
+ if match {
+ return url, "", true
+ } else {
+ return url, "Invalid URL.", false
+ }
+}
+
+func validIso(url string) (string, string, bool) {
+ return validURL(url, "iso")
+}
+
+func validJson(url string) (string, string, bool) {
+ return validURL(url, "json")
+}
diff --git a/webboot/cmds/webboot/webboot.go b/webboot/cmds/webboot/webboot.go
new file mode 100644
index 000000000..e9d46d605
--- /dev/null
+++ b/webboot/cmds/webboot/webboot.go
@@ -0,0 +1,542 @@
+package main
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "html/template"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+
+ ui "github.com/gizak/termui/v3"
+ Boot "github.com/u-root/u-root/pkg/boot"
+ "github.com/u-root/u-root/pkg/mount"
+ "github.com/u-root/u-root/pkg/mount/block"
+ "github.com/u-root/webboot/pkg/bootiso"
+ "github.com/u-root/webboot/pkg/menu"
+)
+
+var (
+ v = flag.Bool("verbose", false, "Verbose output")
+ verbose = func(string, ...interface{}) {}
+ dir = flag.String("dir", "", "Path of cached directory")
+ network = flag.Bool("network", true, "If network is false we will not set up network")
+ dryRun = flag.Bool("dryrun", false, "If dry_run is true we won't boot the iso.")
+ cacheDev CacheDevice
+ logBuffer bytes.Buffer
+ tmpBuffer bytes.Buffer
+)
+
+const jsonURL = "https://raw.githubusercontent.com/u-root/webboot/main/cmds/webboot/distros.json"
+
+// ISO's exec downloads the iso and boot it.
+func (i *ISO) exec(uiEvents <-chan ui.Event, menus chan<- string, boot bool) error {
+ verbose("Intent to boot %s", i.path)
+
+ distroName := inferIsoType(path.Base(i.path), supportedDistros)
+ distro, ok := supportedDistros[distroName]
+
+ if !ok {
+ // Could not infer ISO type based on filename
+ // Prompt user to identify the ISO's type
+ entries := supportedDistroEntries()
+ entry, err := menu.PromptMenuEntry("ISO Type", "Select the closest distribution:", entries, uiEvents, menus)
+ if err != nil {
+ return err
+ }
+
+ distro = supportedDistros[entry.Label()]
+ }
+
+ verbose("Using distro %s with boot config %s", distroName, distro.BootConfig)
+
+ var configs []Boot.OSImage
+ if distro.BootConfig != "" {
+ parsedConfigs, err := bootiso.ParseConfigFromISO(i.path, distro.BootConfig)
+ if err != nil {
+ return err
+ }
+
+ configs = append(configs, parsedConfigs...)
+ }
+
+ if len(distro.CustomConfigs) != 0 {
+ CustomConfigs, err := bootiso.LoadCustomConfigs(i.path, distro.CustomConfigs)
+ if err != nil {
+ return err
+ }
+
+ configs = append(configs, CustomConfigs...)
+ }
+
+ if len(configs) == 0 {
+ return fmt.Errorf("No valid configs were found.")
+ }
+
+ verbose("Get configs: %+v", configs)
+
+ entries := []menu.Entry{}
+ for _, config := range configs {
+ entries = append(entries, &BootConfig{config})
+ }
+
+ entry, err := menu.PromptMenuEntry("Configs", "Choose an option", entries, uiEvents, menus)
+ if err != nil {
+ return err
+ }
+
+ config, ok := entry.(*BootConfig)
+ if !ok {
+ return fmt.Errorf("Could not convert selection to a boot image.")
+ }
+
+ if err == nil {
+ cacheDev.IsoPath = strings.ReplaceAll(i.path, cacheDev.MountPoint, "")
+ paramTemplate, err := template.New("template").Parse(distro.KernelParams)
+ if err != nil {
+ return err
+ }
+
+ var kernelParams bytes.Buffer
+ if err = paramTemplate.Execute(&kernelParams, cacheDev); err != nil {
+ return err
+ }
+
+ if !boot {
+ s := fmt.Sprintf("config.image %s, kernelparams.String() %s", config.image, kernelParams.String())
+ return fmt.Errorf("Booting is disabled (see --dryrun flag), but otherwise would be [%s].", s)
+ }
+ err = bootiso.BootCachedISO(config.image, kernelParams.String()+" waitusb=10")
+ }
+
+ // If kexec succeeds, we should not arrive here
+ if err == nil {
+ // TODO: We should know whether we tried using /sbin/kexec.
+ err = fmt.Errorf("kexec failed, but gave no error. Consider trying kexec-tools.")
+ }
+
+ return err
+}
+
+// DownloadOption's exec lets user input the name of the iso they want
+// if this iso is existed in the bookmark, use it's url
+// elsewise ask for a download link
+func (d *DownloadOption) exec(uiEvents <-chan ui.Event, menus chan<- string, network bool, cacheDir string) (menu.Entry, error) {
+
+ entries := supportedDistroEntries()
+ customLabel := "Other Distro"
+ entries = append(entries, &Config{customLabel})
+ entry, err := menu.PromptMenuEntry("Linux Distros", "Choose an option:", entries, uiEvents, menus)
+ if err != nil {
+ return nil, err
+ }
+ var link string
+
+ if entry.Label() == customLabel {
+ link, err = menu.PromptTextInput("Enter URL:", validIso, uiEvents, menus)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ link, _, err = mirrorMenu(entry, uiEvents, menus, link)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ filename := path.Base(link)
+
+ // If the cachedir is not find, downloaded the iso to /tmp, else create a Downloaded dir in the cache dir.
+ var fpath string
+ var downloadDir string
+
+ if cacheDir == "" {
+ downloadDir = os.TempDir()
+ fpath = filepath.Join(downloadDir, filename)
+ } else {
+ downloadDir = filepath.Join(cacheDir, "Downloaded")
+ if err = os.MkdirAll(downloadDir, os.ModePerm); err != nil {
+ return nil, fmt.Errorf("Fail to create the downloaded dir :%v", err)
+ }
+ fpath = filepath.Join(downloadDir, filename)
+ }
+
+ if err = download(link, fpath, downloadDir, uiEvents); err != nil {
+ if err == context.Canceled {
+ return nil, fmt.Errorf("Download was canceled.")
+ } else {
+ return nil, err
+ }
+ }
+
+ menu, err := displayChecksumPrompt(uiEvents, menus, supportedDistros, entry.Label(), fpath)
+ if err != nil {
+ return nil, err
+ } else if menu != nil {
+ return menu, nil
+ }
+
+ return &ISO{label: filename, path: fpath}, nil
+}
+
+// DirOption's exec displays subdirectory or cached isos under the path directory
+func (d *DirOption) exec(uiEvents <-chan ui.Event, menus chan<- string) (menu.Entry, error) {
+ entries := []menu.Entry{}
+ readerInfos, err := ioutil.ReadDir(d.path)
+ if err != nil {
+ return nil, err
+ }
+
+ // check the directory, if there is a subdirectory, add a DirOption option to next menu
+ // if there is iso file, add an ISO option
+ for _, info := range readerInfos {
+ if info.IsDir() {
+ entries = append(entries, &DirOption{
+ label: info.Name(),
+ path: filepath.Join(d.path, info.Name()),
+ })
+ } else if filepath.Ext(info.Name()) == ".iso" {
+ iso := &ISO{
+ path: filepath.Join(d.path, info.Name()),
+ label: info.Name(),
+ }
+ entries = append(entries, iso)
+ }
+ }
+
+ return menu.PromptMenuEntry("Distros", "Choose an option:", entries, uiEvents, menus)
+}
+
+// getJsonLink prompts users to choose or enter the url for the JSON file that will be used.
+// It returns a string url, a bool telling whether or not the file needs to be downloaded, and an error.
+func getJsonLink(uiEvents <-chan ui.Event, menus chan<- string) (string, bool, error) {
+ entries := []menu.Entry{
+ &Config{label: "Downloaded (recommended)"},
+ &Config{label: "Local"},
+ &Config{label: "Enter a custom URL"},
+ }
+
+ entry, err := menu.PromptMenuEntry("Which list of distros would you like to choose from?", "Select an option.", entries, uiEvents, menus)
+ if err != nil {
+ return "", false, fmt.Errorf("Failed to display PromptMenuEntry: %v", err)
+ }
+
+ switch entry.Label() {
+ case "Downloaded (recommended)":
+ return jsonURL, true, nil
+ case "Local":
+ return "./distros.json", false, nil
+ case "Enter a custom URL":
+ // get user input
+ customUrl, err := menu.PromptTextInput("Enter URL:", validJson, uiEvents, menus)
+ if err != nil {
+ return "", false, fmt.Errorf("Failed to display PromptMenuEntry: %v", err)
+ }
+ return customUrl, true, nil
+ default:
+ return "", false, fmt.Errorf("No valid option chosen.")
+ }
+}
+
+// distroData downloads and parses the data in distros.json to a map[string]Distro.
+func distroData(uiEvents <-chan ui.Event, menus chan<- string, cacheDir string) (map[string]Distro, error) {
+ jsonPath := "./distros.json"
+
+ // Get the download link.
+ jsonLink, needDownload, err := getJsonLink(uiEvents, menus)
+ if err != nil {
+ return nil, fmt.Errorf("Error in getJsonLink: %v", err)
+ }
+
+ if needDownload {
+ var downloadDir string
+
+ if cacheDir == "" {
+ downloadDir = os.TempDir()
+ jsonPath = filepath.Join(downloadDir, "distros.json")
+ } else {
+ downloadDir = filepath.Join(cacheDir, "Downloaded")
+ if err := os.MkdirAll(downloadDir, os.ModePerm); err != nil {
+ return nil, fmt.Errorf("Fail to create the downloaded dir: %v", err)
+ }
+ jsonPath = filepath.Join(downloadDir, "distros.json")
+ }
+
+ // Download the json file.
+ if err := download(jsonLink, jsonPath, downloadDir, uiEvents); err != nil {
+ if err == context.Canceled {
+ return nil, fmt.Errorf("JSON file download was canceled.")
+ } else {
+ entries := []menu.Entry{&Config{label: "Ok"}}
+ _, err := menu.PromptMenuEntry("Failed to download JSON file.", "Choose \"Ok\" to proceed using default JSON file.", entries, uiEvents, menus)
+ if err != nil {
+ return nil, fmt.Errorf("Could not display PromptMenuEntry: %v", err)
+ }
+ jsonPath = "./distros.json"
+ }
+ }
+ }
+
+ // Parse the json file.
+ data, err := ioutil.ReadFile(jsonPath)
+
+ if err != nil {
+ return nil, fmt.Errorf("Could not read JSON file: %v\n", err)
+ }
+
+ supportedDistros := map[string]Distro{}
+
+ err = json.Unmarshal([]byte(data), &supportedDistros)
+ if err != nil {
+ return nil, fmt.Errorf("Could not unmarshal JSON file: %v\n", err)
+ }
+
+ return supportedDistros, nil
+}
+
+// If the chosen distro has a checksum, verify it.
+// If the checksum is not correct, prompt the user to choose whether they still want to continue.
+func displayChecksumPrompt(uiEvents <-chan ui.Event, menus chan<- string, supportedDistros map[string]Distro, label string, fpath string) (menu.Entry, error) {
+ // Check that the distro is supported
+ if _, ok := supportedDistros[label]; ok {
+ distro := supportedDistros[label]
+ // Check that checksum is available
+ if distro.Checksum == "" {
+ accept, err := menu.PromptConfirmation("This distro does not have a checksum. Proceed anyway?", uiEvents, menus)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to prompt confirmation: %s", err)
+ }
+ if !accept {
+ // Go back to download menu
+ return &DownloadOption{}, nil
+ }
+ } else if valid, calcChecksum, err := bootiso.VerifyChecksum(fpath, distro.Checksum, distro.ChecksumType); err != nil {
+ return nil, fmt.Errorf("Failed to verify checksum: %s", err)
+ } else if !valid {
+ accept, err := menu.PromptConfirmation(fmt.Sprintf("Checksum was not correct. The correct checksum is %s and the downloaded ISO's checksum is %s. Proceed anyway?",
+ distro.Checksum, calcChecksum), uiEvents, menus)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to prompt confirmation: %s", err)
+ }
+ if !accept {
+ // Go back to download menu
+ return &DownloadOption{}, nil
+ }
+ }
+ }
+ return nil, nil
+}
+
+// mirrorMenu fetches the mirror options of the distro the user selects and displays them in a new menu. Finally, it gets
+// the download link of the mirror the user selects.
+func mirrorMenu(entry menu.Entry, uiEvents <-chan ui.Event, menus chan<- string, link string) (url string, mirrorNameForTestPurposes string, err error) {
+ // Code for after the specific distro has been selected.
+ // Looks up the distro.
+ distro := supportedDistros[entry.Label()]
+ if len(distro.Mirrors) > 0 {
+ // Make an array of type menu.Entry to store the mirrors of the
+ // particular distro selected. Then, display the mirror options.
+ entries := make([]menu.Entry, len(distro.Mirrors))
+ for i := range entries {
+ entries[i] = &distro.Mirrors[i]
+ }
+ entry, err = menu.PromptMenuEntry("Available Mirrors", "Choose an option:", entries, uiEvents, menus)
+ if err != nil {
+ return "", "", err
+ }
+ }
+ // Iterate through the mirrors of the distro to select the appropriate link.
+ for i := range distro.Mirrors {
+ if distro.Mirrors[i].Name == entry.Label() {
+ link = distro.Mirrors[i].Url
+ return link, distro.Mirrors[i].Name, err
+ }
+ }
+ return "", "", fmt.Errorf("Mirror not found: %v", entry.Label())
+}
+
+// getCachedDirectory recognizes the usb stick that contains the cached directory from block devices,
+// and return the path of cache dir.
+// the cache dir should locate at the root of USB stick and be named as "Images"
+// +-- USB root
+// | +-- Images (<--- the cache directory)
+// | +-- subdirectories or iso files
+// ...
+func getCachedDirectory() (string, error) {
+ blockDevs, err := block.GetBlockDevices()
+ if err != nil {
+ return "", fmt.Errorf("No available block devices to boot from")
+ }
+
+ mountPoints, err := ioutil.TempDir("", "temp-device-")
+ if err != nil {
+ return "", fmt.Errorf("Cannot create tmpdir: %v", err)
+ }
+
+ for _, device := range blockDevs {
+ mp, err := mount.TryMount(filepath.Join("/dev/", device.Name), filepath.Join(mountPoints, device.Name), "", 0)
+ if err != nil {
+ continue
+ }
+ cachePath := filepath.Join(mp.Path, "Images")
+ if _, err = os.Stat(cachePath); err == nil {
+ cacheDev = NewCacheDevice(device, mp.Path)
+ return cachePath, nil
+ }
+ }
+ return "", fmt.Errorf("Do not find the cache directory: Expected a /Images under at the root of a block device(USB)")
+}
+
+type LogOption struct {
+}
+
+func (d *LogOption) Label() string {
+ return "Show last log"
+}
+
+func getMainMenu(cacheDir string, menus chan<- string) menu.Entry {
+ entries := []menu.Entry{}
+ if cacheDir != "" {
+ // UseCacheOption is a special DirOption represents the root of cache dir
+ entries = append(entries, &DirOption{label: "Use Cached ISO", path: cacheDir})
+ }
+ entries = append(entries, &DownloadOption{})
+ entries = append(entries, &LogOption{})
+
+ for {
+ // Display the main menu until user makes a valid choice or
+ // they encounter an error that's not menu.BackRequest
+ entry, err := menu.PromptMenuEntry("Webboot", "Choose an option:", entries, ui.PollEvents(), menus)
+ if err != nil && err != menu.BackRequest {
+ log.Fatal(err)
+ } else if entry != nil {
+ return entry
+ }
+ }
+}
+
+func handleError(err error, menus chan<- string) {
+ if err == menu.ExitRequest {
+ menu.Close()
+ os.Exit(0)
+ } else if err == menu.BackRequest {
+ return
+ }
+
+ errorText := err.Error() + "\n" + tmpBuffer.String() + wifiStdout.String() + wifiStderr.String()
+ fmt.Fprintln(&logBuffer, errorText)
+ menu.DisplayResult(strings.Split(errorText, "\n"), ui.PollEvents(), menus)
+
+ tmpBuffer.Reset()
+ wifiStdout.Reset()
+ wifiStderr.Reset()
+}
+
+func showLog(menus chan<- string) {
+ s := logBuffer.String()
+ if len(s) > 1024 {
+ s = s[len(s)-1024:]
+ }
+ menu.DisplayResult(strings.Split(s, "\n"), ui.PollEvents(), menus)
+}
+
+func main() {
+
+ flag.Parse()
+ if *v {
+ verbose = log.Printf
+ }
+
+ cacheDir := *dir
+ if cacheDir != "" {
+ // call filepath.Clean to make sure the format of path is consistent
+ // we should check the cacheDir != "" before call filepath.Clean, because filepath.Clean("") = "."
+ cacheDir = filepath.Clean(cacheDir)
+ } else {
+ if cachePath, err := getCachedDirectory(); err != nil {
+ verbose("Fail to find the USB stick: %+v", err)
+ } else {
+ cacheDir = cachePath
+ }
+ }
+ verbose("Using cache dir: %v", cacheDir)
+ if err := menu.Init(); err != nil {
+ log.Fatalf(err.Error())
+ }
+
+ menus := make(chan string)
+ // Continuously throw away values from menus channel so that the channel doesn't block.
+ go func() {
+ for {
+ <-menus
+ }
+ }()
+ entry := getMainMenu(cacheDir, menus)
+
+ // Buffer the log output, else it might overlap with the menu
+ log.SetOutput(&tmpBuffer)
+
+ // check the chosen entry of each level
+ // and call it's exec() to get the next level's chosen entry.
+ // repeat this process until there is no next level
+ var err error
+
+ for entry != nil {
+ switch entry.(type) {
+ case *LogOption:
+ showLog(menus)
+ entry = getMainMenu(cacheDir, menus)
+ case *DownloadOption:
+ // set up network
+ progress := menu.NewProgress("Testing network connection", true)
+ activeConnection := connected()
+ progress.Close()
+
+ if *network && !activeConnection {
+ if err := setupNetwork(ui.PollEvents(), menus); err != nil {
+ verbose("error on setupNetwork: %+v", err)
+ }
+ }
+
+ // get distro data
+ supportedDistros, err = distroData(ui.PollEvents(), menus, cacheDir)
+ if err != nil {
+ log.Fatalf("Error on supportedDistros(): %v", err.Error())
+ }
+
+ if entry, err = entry.(*DownloadOption).exec(ui.PollEvents(), menus, *network, cacheDir); err != nil {
+ handleError(err, menus)
+ entry = getMainMenu(cacheDir, menus)
+ }
+ case *ISO:
+ if err = entry.(*ISO).exec(ui.PollEvents(), menus, !*dryRun); err != nil {
+ handleError(err, menus)
+ entry = getMainMenu(cacheDir, menus)
+ }
+ case *DirOption:
+ dirOption := entry.(*DirOption)
+ if entry, err = dirOption.exec(ui.PollEvents(), menus); err != nil {
+ // Check if user requested to go back from a cache subdirectory,
+ // so we can send them to a DirOption for the parent directory
+ if err == menu.BackRequest && dirOption.path != cacheDir {
+ entry = &DirOption{path: filepath.Dir(dirOption.path)}
+ } else {
+ // Otherwise they either requested to go back from the
+ // cache root, so we can send them to main menu,
+ // or they encountered an error
+ handleError(err, menus)
+ entry = getMainMenu(cacheDir, menus)
+ }
+ }
+ default:
+ handleError(fmt.Errorf("Unknown menu type %T!\n", entry), menus)
+ entry = getMainMenu(cacheDir, menus)
+ }
+ }
+}
diff --git a/webboot/cmds/webboot/webboot_test.go b/webboot/cmds/webboot/webboot_test.go
new file mode 100644
index 000000000..c3e2c0bed
--- /dev/null
+++ b/webboot/cmds/webboot/webboot_test.go
@@ -0,0 +1,662 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "log"
+ "math/rand"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "testing"
+ "time"
+
+ ui "github.com/gizak/termui/v3"
+ "github.com/u-root/webboot/pkg/menu"
+)
+
+func pressKey(ch chan ui.Event, input []string) {
+ var key ui.Event
+ for _, id := range input {
+ key = ui.Event{
+ Type: ui.KeyboardEvent,
+ ID: id,
+ }
+ ch <- key
+ }
+}
+
+func nextMenuReady(menus <-chan string) string {
+ return <-menus
+}
+
+// The following files can be downloaded:
+const (
+ // randomISO is a file containing 1 mebibytes of random data.
+ randomISO = "random1MiB.iso"
+ // inititeISO is a file which is infinite bytes and takes forever to
+ // download.
+ infiniteISO = "infinite.iso"
+)
+
+// MiB is 1 mebibyte.
+const MiB = 1024 * 1024
+
+// TestMain is run once before all tests.
+func TestMain(m *testing.M) {
+ // Launch the fake ISO server.
+ server, err := startFakeISOServer()
+ if err != nil {
+ log.Fatalf("error starting fake ISO server: %v", err)
+ }
+ defer server.stop()
+
+ // Replace the supportedDistros list with a fake list for testing.
+ supportedDistros = map[string]Distro{
+ "FakeArch": {
+ // This checksum corresponds to the random data for random1MiB.iso.
+ Checksum: "d6e467cd833bfabaefd652cdea1c7bd8318392f703ddf73160c324f515b965a3",
+ ChecksumType: "sha256",
+ Mirrors: []Mirror{
+ {
+ Name: "Default",
+ Url: server.url(randomISO),
+ },
+ {
+ Name: "Arizona",
+ Url: server.url(randomISO),
+ },
+ },
+ },
+ "FakeTinycore": {
+ // This checksum corresponds to the random data for random1MiB.iso.
+ Checksum: "d6e467cd833bfabaefd652cdea1c7bd8318392f703ddf73160c324f515b965a3",
+ ChecksumType: "sha256",
+ Mirrors: []Mirror{
+ {
+ Name: "Default",
+ Url: server.url(randomISO),
+ },
+ },
+ },
+ "InfiniteOS": {
+ Mirrors: []Mirror{
+ {Url: server.url(infiniteISO)},
+ },
+ },
+ }
+
+ // Run tests.
+ os.Exit(m.Run())
+}
+
+// fakeISOServer serves fake ISO images for testing.
+type fakeISOServer struct {
+ server *http.Server
+ port int
+}
+
+// startFakeISOServers starts serving ISOs on 127.0.0.1. The port is in the
+// returned struct.
+func startFakeISOServer() (*fakeISOServer, error) {
+ f := &fakeISOServer{}
+ f.server = &http.Server{
+ Handler: f,
+ }
+
+ // Find an unused port.
+ l, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ return nil, fmt.Errorf("error creating free port: %v", err)
+ }
+ f.port = l.Addr().(*net.TCPAddr).Port
+
+ go func() {
+ if err := f.server.Serve(l); err != http.ErrServerClosed {
+ log.Fatal(err)
+ }
+ }()
+ return f, nil
+}
+
+// stop stops serving ISOs.
+func (f fakeISOServer) stop() {
+ f.server.Close()
+}
+
+// url returns the download url for the given filename.
+func (f fakeISOServer) url(filename string) string {
+ u := &url.URL{
+ Scheme: "http",
+ Host: fmt.Sprintf("127.0.0.1:%d", f.port),
+ Path: filename,
+ }
+ return u.String()
+}
+
+// ServeHTTP handles HTTP requests for the fakeISOServer.
+func (f fakeISOServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // Random number generator.
+ rr := rand.New(rand.NewSource(99))
+
+ switch r.URL.Path {
+ case "/" + randomISO:
+ w.WriteHeader(200)
+ io.CopyN(w, rr, MiB)
+
+ case "/" + infiniteISO:
+ w.WriteHeader(200)
+
+ ctx := r.Context()
+ for {
+ // Write 1 mebibyte every 1 second until the connection
+ // is closed.
+ io.CopyN(w, rr, MiB)
+ select {
+ case <-ctx.Done():
+ break
+ case <-time.After(time.Second):
+ }
+ }
+
+ default:
+ w.WriteHeader(404)
+ }
+}
+
+func TestDownload(t *testing.T) {
+ uiEvents := make(chan ui.Event)
+
+ t.Run("error_link", func(t *testing.T) {
+ errorLink := "errorlink"
+ expected := fmt.Errorf("Get %q: unsupported protocol scheme \"\"", errorLink)
+ if err := download(errorLink, "/tmp/test.iso", "/testdata", uiEvents); err.Error() != expected.Error() {
+ t.Errorf("Expected %+v, received %+v", expected, err)
+ }
+ })
+
+ t.Run("download_tinycore", func(t *testing.T) {
+ // Create a temporary directory for the download.
+ tmpDir, err := filepath.Abs(t.TempDir())
+ if err != nil {
+ t.Fatal(err)
+ }
+ fPath := filepath.Join(tmpDir, "test_download.iso")
+
+ // Download the ISO from the fake server.
+ u := supportedDistros["FakeTinycore"].Mirrors[0].Url
+ if err := download(u, fPath, tmpDir, uiEvents); err != nil {
+ t.Fatalf("Fail to download: %+v", err)
+ }
+ s, err := os.Stat(fPath)
+ if err != nil {
+ t.Fatalf("Fail to find downloaded file: %+v", err)
+ }
+ if s.Size() != MiB {
+ t.Fatalf("Expected download size of %d; got %d", MiB, s.Size())
+ }
+
+ })
+}
+
+func TestGetJsonLink(t *testing.T) {
+ for _, tt := range []struct {
+ name string
+ human func(chan ui.Event, <-chan string)
+ want string
+ }{
+ {
+ name: "test_downloaded",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ },
+ want: "https://raw.githubusercontent.com/u-root/webboot/main/cmds/webboot/distros.json",
+ },
+ {
+ name: "test_local",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"1", ""})
+ },
+ want: "./distros.json",
+ },
+ {
+ name: "test_custom",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"2", ""})
+ nextMenuReady(menus)
+ pressKey(uiEvents, stringToKeypress("https://raw.githubusercontent.com/u-root/webboot/main/cmds/webboot/distros.json"))
+ pressKey(uiEvents, []string{""})
+ },
+ want: "https://raw.githubusercontent.com/u-root/webboot/main/cmds/webboot/distros.json",
+ },
+ } {
+ t.Run(tt.name, func(t *testing.T) {
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+ go tt.human(uiEvents, menus)
+ got, _, err := getJsonLink(uiEvents, menus)
+
+ if err != nil {
+ t.Errorf("Error in getJsonLink(): %v", err)
+ } else if got != tt.want {
+ t.Errorf("%s: Got %s but want %s", tt.name, got, tt.want)
+ }
+ })
+ }
+
+}
+
+func TestDistroData(t *testing.T) {
+ for _, tt := range []struct {
+ name string
+ human func(chan ui.Event, <-chan string)
+ }{
+ {
+ name: "test_good_link",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ },
+ },
+ {
+ name: "test_bad_link",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ // User chooses to enter a custom link.
+ pressKey(uiEvents, []string{"2", ""})
+ nextMenuReady(menus)
+ // The link is valid but can't be downloaded.
+ pressKey(uiEvents, stringToKeypress("https://raw.githubusercontent.com/u-root/webboot/main/cmds/webboot/fake_link.json"))
+ pressKey(uiEvents, []string{""})
+ nextMenuReady(menus)
+ // User presses 0 to continue with local json file.
+ pressKey(uiEvents, []string{"0", ""})
+ },
+ },
+ } {
+ t.Run(tt.name, func(t *testing.T) {
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+ go tt.human(uiEvents, menus)
+ supportedDistros, err := distroData(uiEvents, menus, "./testdata")
+ if err != nil {
+ t.Fatalf("Error on distroData: %v", err)
+ }
+
+ if len(supportedDistros) == 0 {
+ t.Fatalf("Got empty distro list, want provided JSON file to be unmarshaled into supportedDistros.")
+ }
+
+ for distroName := range supportedDistros {
+ if len(supportedDistros[distroName].Mirrors) == 0 {
+ t.Fatalf("Got empty mirror list in %s, want provided JSON file to be unmarshaled into supportedDistros.", distroName)
+ }
+ }
+ })
+ }
+}
+
+func TestDownloadOption(t *testing.T) {
+ tinycoreIso := &ISO{
+ label: randomISO,
+ path: filepath.Join("testdata/Downloaded", randomISO),
+ }
+
+ // Select custom distro, then type Tinycore URL manually
+ customIndex := len(supportedDistros)
+ tinycoreURL := supportedDistros["FakeTinycore"].Mirrors[0].Url
+ tinycoreIndex, err := distroIndex("FakeTinycore")
+ if err != nil {
+ t.Fatalf("Error on distroIndex: %v", err)
+ }
+ for _, tt := range []struct {
+ name string
+ want *ISO
+ human func(chan ui.Event, <-chan string)
+ }{
+ {
+ name: "test_bookmark",
+ want: tinycoreIso,
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ // Distros selection menu
+ pressKey(uiEvents, []string{strconv.Itoa(tinycoreIndex), ""})
+ nextMenuReady(menus)
+ // Mirrors selection menu
+ pressKey(uiEvents, []string{"0", ""})
+ },
+ },
+ {
+ name: "test_custom_url",
+ want: tinycoreIso,
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{strconv.Itoa(customIndex), ""})
+ nextMenuReady(menus)
+ pressKey(uiEvents, stringToKeypress(tinycoreURL))
+ pressKey(uiEvents, []string{""})
+ },
+ },
+ } {
+ t.Run(tt.name, func(t *testing.T) {
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+ go tt.human(uiEvents, menus)
+ downloadOption := DownloadOption{}
+ entry, err := downloadOption.exec(uiEvents, menus, false, "./testdata")
+
+ if err != nil {
+ t.Fatalf("Fail to execute downloadOption.exec(): %+v", err)
+ }
+ iso, ok := entry.(*ISO)
+ if !ok {
+ t.Fatalf("Expected type *ISO, but get %T", entry)
+ }
+ if tt.want.label != iso.label || tt.want.path != iso.path {
+ t.Fatalf("Incorrect return. get %+v, want %+v", entry, tt.want)
+ }
+ if _, err := os.Stat(iso.path); err != nil {
+ t.Fatalf("Fail to find downloaded file: %+v", err)
+ }
+ if err := os.RemoveAll("./testdata/Downloaded"); err != nil {
+ t.Fatalf("Fail to remove test file: %+v", err)
+ }
+ })
+ }
+}
+
+func TestCancelDownload(t *testing.T) {
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+ index, err := distroIndex("InfiniteOS")
+ if err != nil {
+ t.Fatalf("Error on distroIndex: %v", err)
+ }
+
+ // InfiniteOS will take forever to download and must be cancelled.
+ go func() {
+ nextMenuReady(menus)
+ // Distros selection menu
+ pressKey(uiEvents, []string{strconv.Itoa(index), ""})
+ nextMenuReady(menus)
+ // Mirrors selection menu
+ pressKey(uiEvents, []string{"0", "", ""})
+ }()
+
+ downloadOption := DownloadOption{}
+ _, err = downloadOption.exec(uiEvents, menus, false, "./testdata")
+
+ if err == nil {
+ t.Errorf("Got nil error; expected 'Download was canceled.'")
+ }
+
+ if err != nil && err.Error() != "Download was canceled." {
+ t.Errorf("Received error: %+v", err)
+ }
+
+ if err := os.RemoveAll("./testdata/Downloaded"); err != nil {
+ t.Errorf("Fail to remove test file: %+v", err)
+ }
+}
+
+func TestDirOption(t *testing.T) {
+ wanted := &ISO{
+ label: "TinyCorePure64.iso",
+ path: "testdata/dirlevel1/dirlevel2/TinyCorePure64.iso",
+ }
+
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+
+ var entry menu.Entry = &DirOption{label: "root dir", path: "./testdata"}
+ var err error = nil
+ for {
+ if dirOption, ok := entry.(*DirOption); ok {
+ go func() {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ }()
+ entry, err = dirOption.exec(uiEvents, menus)
+ if err != nil {
+ t.Fatalf("Fail to execute option (%q)'s exec(): %+v", entry.Label(), err)
+ }
+ } else if iso, ok := entry.(*ISO); ok {
+ if iso.label != wanted.label || iso.path != wanted.path {
+ t.Fatalf("Get wrong chosen iso. get %+v, want %+v", iso, wanted)
+ }
+ break
+ } else {
+ t.Fatalf("Unknown type. got entry %+v of type %T, wanted DirOption or ISO", entry, entry)
+ }
+ }
+}
+
+// TestBackOption tests behavior when the escape key is pressed on a menu.
+func TestBackOption(t *testing.T) {
+
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+
+ var entry menu.Entry = &DirOption{path: "./testdata"}
+ var err error = nil
+
+ go func() {
+ for i := 0; i < 2; i++ {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{""})
+ }
+ }()
+ // The first loop tests ./testdata - a back request should not have any effect
+ // because we are already at the first possible menu.
+ // The second loop tests testdata/dirlevel1 - a back request should return the previous menu.
+ for i := 0; i < 2; i++ {
+ if dirOption, ok := entry.(*DirOption); ok {
+ currentPath := dirOption.path
+ entry, err = dirOption.exec(uiEvents, menus)
+ if err != nil && err != menu.BackRequest {
+ t.Fatalf("Fail to execute option (%q)'s exec(): %+v", entry.Label(), err)
+ } else if err == menu.BackRequest {
+ backTo := filepath.Dir(currentPath)
+ entry = &DirOption{path: backTo}
+ }
+ } else {
+ t.Fatalf("Unknown type. got entry %+v of type %T, wanted DirOption", entry, entry)
+ }
+
+ }
+ if dirOption, ok := entry.(*DirOption); !ok {
+ t.Fatalf("Incorrect result, want a DirOption, get %T", entry)
+ } else {
+ if dirOption.path != "testdata" {
+ t.Fatalf("Get incorrect dir option, want \"testdata\", get %s", dirOption.path)
+ }
+ }
+}
+
+func TestDisplayChecksumPrompt(t *testing.T) {
+ // test data
+ var testDistros = map[string]Distro{
+ "FakeDistro": {
+ Checksum: "1234567",
+ ChecksumType: "sha256",
+ },
+ "FakeDistroNoChecksum": {},
+ "FakeDistroGoodChecksum": {
+ Checksum: "407dc87b95afbe268e760313971041860f36e953a2116db03418a98ce46d61bc",
+ ChecksumType: "sha256",
+ },
+ }
+
+ type test struct {
+ name string
+ distroName string
+ want string
+ human func(chan ui.Event, <-chan string)
+ }
+
+ tests := []test{
+ {
+ name: "Incorrect checksum, don't proceed",
+ distroName: "FakeDistro",
+ want: "*main.DownloadOption",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"1", ""})
+ },
+ },
+ {
+ name: "Incorrect checksum, proceed",
+ distroName: "FakeDistro",
+ want: "",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ },
+ },
+ {
+ name: "No checksum, don't proceed",
+ distroName: "FakeDistroNoChecksum",
+ want: "*main.DownloadOption",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"1", ""})
+ },
+ },
+ {
+ name: "No checksum, proceed",
+ distroName: "FakeDistroNoChecksum",
+ want: "",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ },
+ },
+ {
+ name: "Correct checksum",
+ distroName: "FakeDistroGoodChecksum",
+ want: "",
+ human: func(uiEvents chan ui.Event, menus <-chan string) {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{})
+ },
+ },
+ }
+
+ for _, tc := range tests {
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+
+ t.Run(tc.name, func(t *testing.T) {
+ go tc.human(uiEvents, menus)
+ menu, err := displayChecksumPrompt(uiEvents, menus, testDistros, tc.distroName, "testdata/dirlevel1/fakeDistro.iso")
+ if err != nil {
+ t.Errorf("Error on displayChecksumPrompt: %v", err)
+ } else if got := fmt.Sprintf("%T", menu); got != tc.want {
+ t.Errorf("%s: Got %s but want %s", tc.name, got, tc.want)
+ }
+ })
+ }
+}
+
+func distroIndex(searchName string) (int, error) {
+ var downloadOptions []string
+ for distroName := range supportedDistros {
+ downloadOptions = append(downloadOptions, distroName)
+ }
+ sort.Strings(downloadOptions)
+
+ var distroList string
+
+ for index, distroName := range downloadOptions {
+ distroList += fmt.Sprintf("%s ", distroName)
+ if distroName == searchName {
+ return index, nil
+ }
+ }
+
+ return -1, fmt.Errorf("could not find distro %s. Here are the available distros: %s", searchName, distroList)
+}
+
+func stringToKeypress(str string) []string {
+ var keyPresses []string
+ for i := 0; i < len(str); i++ {
+ keyPresses = append(keyPresses, str[i:i+1])
+ }
+ return keyPresses
+}
+
+func TestDefaultMirrorNameAndLinkCheck(t *testing.T) {
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+
+ go func() {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"0", ""})
+ }()
+
+ entry := &Config{label: "FakeArch"}
+ u, m, err := mirrorMenu(entry, uiEvents, menus, "")
+ if err != nil {
+ t.Fatalf("%+v", err)
+ }
+ tl := supportedDistros["FakeArch"].Mirrors[0].Url
+ if u != tl {
+ t.Fatalf("Wrong mirror link. Got %q, want %q", u, tl)
+ }
+ if m != "Default" {
+ t.Fatalf("Wrong mirror name. Got %q, want %q", m, "Default")
+ }
+}
+
+func TestMirrorNameAndLinkCheck(t *testing.T) {
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+
+ go func() {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"1", ""})
+ }()
+
+ entry := &Config{label: "FakeArch"}
+ u, m, err := mirrorMenu(entry, uiEvents, menus, "")
+ if err != nil {
+ t.Fatalf("%+v", err)
+ }
+ tl := supportedDistros["FakeArch"].Mirrors[0].Url
+ if u != tl {
+ t.Fatalf("Wrong mirror link. Got %q, want %q", u, tl)
+ }
+ if m != "Arizona" {
+ t.Fatalf("Wrong mirror name. Got %q, want %q", m, "Arizona")
+ }
+}
+
+func TestMirrorNameAndLinkCheckBad(t *testing.T) {
+ t.Skip("TODO: This test is disabled until the menu package is fixed.")
+ uiEvents := make(chan ui.Event)
+ menus := make(chan string)
+
+ go func() {
+ nextMenuReady(menus)
+ pressKey(uiEvents, []string{"9", ""})
+ }()
+
+ entry := &Config{label: "FakeArch"}
+ _, _, err := mirrorMenu(entry, uiEvents, menus, "")
+ if err == nil {
+ t.Fatalf("Bad mirror selection: got nil, want error")
+ }
+}
diff --git a/webboot/cmds/wifiDebug/wifiDebug.go b/webboot/cmds/wifiDebug/wifiDebug.go
new file mode 100644
index 000000000..55dcb03e9
--- /dev/null
+++ b/webboot/cmds/wifiDebug/wifiDebug.go
@@ -0,0 +1,44 @@
+// Copyright 2021 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package main takes the connect function of iwl.go and reduces it
+// to as few lines as possible to make spotting errors in wifi bugs easier.
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+)
+
+// IWLWorker implements the WiFi interface using the Intel Wireless LAN commands
+type IWLWorker struct {
+ Interface string
+}
+
+func main() {
+ // There's no telling how long the supplicant will take, but on the other hand,
+ // it's been almost instantaneous. But, further, it needs to keep running.
+ go func() {
+ cmd := exec.Command("/usr/bin/strace", "-o", "/tmp/out", "wpa_supplicant", "-dd", "-i wlan0", "-c/tmp/wifi.conf")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ fmt.Println("wpa supplicant cmd.Stdout: ", cmd.Stdout)
+ fmt.Println("wpa supplicant cmd.Stderr: ", cmd.Stderr)
+ err := cmd.Run()
+ fmt.Println("wpa supplicant cmd.Run() error: ", err)
+ }()
+
+ // dhclient might never return on incorrect passwords or identity
+ go func() {
+ cmd := exec.Command("dhclient", "-ipv4=true", "-ipv6=false", "-v", "wlan0")
+ cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
+ fmt.Println("dhclient cmd.Stdout: ", cmd.Stdout)
+ fmt.Println("dhclient cmd.Stderr: ", cmd.Stderr)
+ err := cmd.Run()
+ fmt.Println("dhclient cmd.Run() error: ", err)
+ }()
+
+ for {
+ }
+}
diff --git a/webboot/config-5.6.14 b/webboot/config-5.6.14
new file mode 100644
index 000000000..6ac15bf05
--- /dev/null
+++ b/webboot/config-5.6.14
@@ -0,0 +1,4905 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86 5.6.14 Kernel Configuration
+#
+
+#
+# Compiler: gcc (Debian 10.2.1-6+build2) 10.2.1 20210110
+#
+CONFIG_CC_IS_GCC=y
+CONFIG_GCC_VERSION=100201
+CONFIG_CLANG_VERSION=0
+CONFIG_CC_CAN_LINK=y
+CONFIG_CC_HAS_ASM_GOTO=y
+CONFIG_CC_HAS_ASM_INLINE=y
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_TABLE_SORT=y
+CONFIG_THREAD_INFO_IN_TASK=y
+
+#
+# General setup
+#
+CONFIG_INIT_ENV_ARG_LIMIT=32
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_BUILD_SALT=""
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_GENERIC_IRQ_MIGRATION=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
+CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_GENERIC_IRQ_DEBUGFS is not set
+# end of IRQ subsystem
+
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
+CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+# CONFIG_NO_HZ_FULL is not set
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+# end of Timers subsystem
+
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_PREEMPTION=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_PSI is not set
+# end of CPU/Task time and stats accounting
+
+CONFIG_CPU_ISOLATION=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+CONFIG_PREEMPT_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_TASKS_RCU=y
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RCU_NEED_SEGCBLIST=y
+# end of RCU Subsystem
+
+CONFIG_BUILD_BIN2C=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_IKHEADERS is not set
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+
+#
+# Scheduler features
+#
+# end of Scheduler features
+
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
+CONFIG_CC_HAS_INT128=y
+CONFIG_ARCH_SUPPORTS_INT128=y
+CONFIG_CGROUPS=y
+CONFIG_PAGE_COUNTER=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_MEMCG_SWAP_ENABLED=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_WRITEBACK=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+# CONFIG_CGROUP_RDMA is not set
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+# CONFIG_CGROUP_BPF is not set
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_TIME_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_RD_LZ4=y
+# CONFIG_BOOT_CONFIG is not set
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_HAVE_UID16=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+CONFIG_SGETMASK_SYSCALL=y
+CONFIG_SYSFS_SYSCALL=y
+CONFIG_FHANDLE=y
+CONFIG_POSIX_TIMERS=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_FUTEX_PI=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_IO_URING=y
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_MEMBARRIER=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
+CONFIG_RSEQ=y
+# CONFIG_DEBUG_RSEQ is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+# CONFIG_PC104 is not set
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+# end of Kernel Performance Events And Counters
+
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLUB_MEMCG_SYSFS_ON is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_SLAB_MERGE_DEFAULT=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SLAB_FREELIST_HARDENED is not set
+# CONFIG_SHUFFLE_PAGE_ALLOCATOR is not set
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_SYSTEM_DATA_VERIFICATION=y
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# end of General setup
+
+CONFIG_64BIT=y
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=28
+CONFIG_ARCH_MMAP_RND_BITS_MAX=32
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_FILTER_PGPROT=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ZONE_DMA32=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_X86_64_SMP=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_PGTABLE_LEVELS=5
+CONFIG_CC_HAS_SANE_STACKPROTECTOR=y
+
+#
+# Processor type and features
+#
+CONFIG_ZONE_DMA=y
+CONFIG_SMP=y
+CONFIG_X86_FEATURE_NAMES=y
+CONFIG_X86_X2APIC=y
+# CONFIG_X86_MPPARSE is not set
+# CONFIG_GOLDFISH is not set
+CONFIG_RETPOLINE=y
+# CONFIG_X86_CPU_RESCTRL is not set
+# CONFIG_X86_EXTENDED_PLATFORM is not set
+CONFIG_X86_INTEL_LPSS=y
+# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
+CONFIG_IOSF_MBI=y
+CONFIG_IOSF_MBI_DEBUG=y
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_HYPERVISOR_GUEST=y
+CONFIG_PARAVIRT=y
+# CONFIG_PARAVIRT_DEBUG is not set
+CONFIG_PARAVIRT_SPINLOCKS=y
+# CONFIG_XEN is not set
+CONFIG_KVM_GUEST=y
+CONFIG_ARCH_CPUIDLE_HALTPOLL=y
+# CONFIG_PVH is not set
+CONFIG_KVM_DEBUG_FS=y
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+CONFIG_PARAVIRT_CLOCK=y
+# CONFIG_JAILHOUSE_GUEST is not set
+# CONFIG_ACRN_GUEST is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MATOM is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_IA32_FEAT_CTL=y
+CONFIG_X86_VMX_FEATURE_NAMES=y
+CONFIG_PROCESSOR_SELECT=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_HYGON=y
+# CONFIG_CPU_SUP_CENTAUR is not set
+CONFIG_CPU_SUP_ZHAOXIN=y
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+# CONFIG_GART_IOMMU is not set
+# CONFIG_MAXSMP is not set
+CONFIG_NR_CPUS_RANGE_BEGIN=2
+CONFIG_NR_CPUS_RANGE_END=512
+CONFIG_NR_CPUS_DEFAULT=64
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+# CONFIG_SCHED_MC is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCELOG_LEGACY is not set
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_AMD=y
+CONFIG_X86_MCE_THRESHOLD=y
+# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_THERMAL_VECTOR=y
+
+#
+# Performance monitoring
+#
+CONFIG_PERF_EVENTS_INTEL_UNCORE=y
+CONFIG_PERF_EVENTS_INTEL_RAPL=y
+CONFIG_PERF_EVENTS_INTEL_CSTATE=y
+# CONFIG_PERF_EVENTS_AMD_POWER is not set
+# end of Performance monitoring
+
+CONFIG_X86_16BIT=y
+CONFIG_X86_ESPFIX64=y
+# CONFIG_X86_VSYSCALL_EMULATION is not set
+CONFIG_X86_IOPL_IOPERM=y
+# CONFIG_I8K is not set
+CONFIG_MICROCODE=y
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_5LEVEL=y
+CONFIG_X86_DIRECT_GBPAGES=y
+# CONFIG_X86_CPA_STATISTICS is not set
+# CONFIG_AMD_MEM_ENCRYPT is not set
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_X86_PMEM_LEGACY_DEVICE=y
+CONFIG_X86_PMEM_LEGACY=y
+CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
+CONFIG_X86_RESERVE_LOW=64
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=1
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+CONFIG_ARCH_RANDOM=y
+CONFIG_X86_SMAP=y
+CONFIG_X86_UMIP=y
+CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y
+CONFIG_X86_INTEL_TSX_MODE_OFF=y
+# CONFIG_X86_INTEL_TSX_MODE_ON is not set
+# CONFIG_X86_INTEL_TSX_MODE_AUTO is not set
+# CONFIG_EFI is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
+CONFIG_ARCH_HAS_KEXEC_PURGATORY=y
+# CONFIG_KEXEC_SIG is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_KEXEC_JUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_RELOCATABLE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_X86_NEED_RELOCS=y
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_DYNAMIC_MEMORY_LAYOUT=y
+CONFIG_RANDOMIZE_MEMORY=y
+CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set
+# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_LEGACY_VSYSCALL_EMULATE=y
+# CONFIG_LEGACY_VSYSCALL_XONLY is not set
+# CONFIG_LEGACY_VSYSCALL_NONE is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_MODIFY_LDT_SYSCALL=y
+CONFIG_HAVE_LIVEPATCH=y
+# end of Processor type and features
+
+CONFIG_ARCH_HAS_ADD_PAGES=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_ARCH_HIBERNATION_HEADER=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_SUSPEND_SKIP_SYNC is not set
+CONFIG_HIBERNATE_CALLBACKS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_AUTOSLEEP is not set
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=100
+CONFIG_PM_WAKELOCKS_GC=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_PM_SLEEP_DEBUG=y
+# CONFIG_DPM_WATCHDOG is not set
+CONFIG_PM_TRACE=y
+CONFIG_PM_TRACE_RTC=y
+CONFIG_PM_CLK=y
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
+# CONFIG_ENERGY_MODEL is not set
+CONFIG_ARCH_SUPPORTS_ACPI=y
+CONFIG_ACPI=y
+CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
+CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
+CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
+# CONFIG_ACPI_DEBUGGER is not set
+CONFIG_ACPI_SPCR_TABLE=y
+CONFIG_ACPI_LPIT=y
+CONFIG_ACPI_SLEEP=y
+# CONFIG_ACPI_PROCFS_POWER is not set
+CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y
+CONFIG_ACPI_EC_DEBUGFS=y
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_TAD is not set
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_CPU_FREQ_PSS=y
+CONFIG_ACPI_PROCESSOR_CSTATE=y
+CONFIG_ACPI_PROCESSOR_IDLE=y
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_IPMI=y
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_PROCESSOR_AGGREGATOR=y
+CONFIG_ACPI_THERMAL=y
+CONFIG_ACPI_CUSTOM_DSDT_FILE=""
+CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
+CONFIG_ACPI_TABLE_UPGRADE=y
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=y
+CONFIG_ACPI_CONTAINER=y
+CONFIG_ACPI_HOTPLUG_IOAPIC=y
+CONFIG_ACPI_SBS=y
+CONFIG_ACPI_HED=y
+# CONFIG_ACPI_CUSTOM_METHOD is not set
+# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
+# CONFIG_ACPI_NFIT is not set
+CONFIG_HAVE_ACPI_APEI=y
+CONFIG_HAVE_ACPI_APEI_NMI=y
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_GHES=y
+CONFIG_ACPI_APEI_PCIEAER=y
+CONFIG_ACPI_APEI_MEMORY_FAILURE=y
+CONFIG_ACPI_APEI_EINJ=y
+# CONFIG_ACPI_APEI_ERST_DEBUG is not set
+# CONFIG_DPTF_POWER is not set
+# CONFIG_PMIC_OPREGION is not set
+# CONFIG_ACPI_CONFIGFS is not set
+CONFIG_X86_PM_TIMER=y
+CONFIG_SFI=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set
+
+#
+# CPU frequency scaling drivers
+#
+CONFIG_X86_INTEL_PSTATE=y
+CONFIG_X86_PCC_CPUFREQ=y
+CONFIG_X86_ACPI_CPUFREQ=y
+CONFIG_X86_ACPI_CPUFREQ_CPB=y
+# CONFIG_X86_POWERNOW_K8 is not set
+# CONFIG_X86_AMD_FREQ_SENSITIVITY is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_P4_CLOCKMOD is not set
+
+#
+# shared options
+#
+# end of CPU Frequency scaling
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_CPU_IDLE_GOV_TEO is not set
+# CONFIG_CPU_IDLE_GOV_HALTPOLL is not set
+CONFIG_HALTPOLL_CPUIDLE=y
+# end of CPU Idle
+
+CONFIG_INTEL_IDLE=y
+# end of Power management and ACPI options
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_MMCONF_FAM10H=y
+# CONFIG_PCI_CNB20LE_QUIRK is not set
+# CONFIG_ISA_BUS is not set
+CONFIG_ISA_DMA_API=y
+CONFIG_AMD_NB=y
+# CONFIG_X86_SYSFB is not set
+# end of Bus options (PCI etc.)
+
+#
+# Binary Emulations
+#
+CONFIG_IA32_EMULATION=y
+CONFIG_X86_X32=y
+CONFIG_COMPAT_32=y
+CONFIG_COMPAT=y
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_SYSVIPC_COMPAT=y
+# end of Binary Emulations
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DMIID=y
+CONFIG_DMI_SYSFS=y
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_GOOGLE_FIRMWARE=y
+# CONFIG_GOOGLE_SMI is not set
+CONFIG_GOOGLE_COREBOOT_TABLE=y
+CONFIG_GOOGLE_MEMCONSOLE=y
+# CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY is not set
+CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=y
+CONFIG_GOOGLE_VPD=y
+CONFIG_UEFI_CPER=y
+CONFIG_UEFI_CPER_X86=y
+CONFIG_EFI_EARLYCON=y
+
+#
+# Tegra firmware driver
+#
+# end of Tegra firmware driver
+# end of Firmware Drivers
+
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+CONFIG_KVM_WERROR=y
+# CONFIG_VHOST_NET is not set
+# CONFIG_VHOST_SCSI is not set
+# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
+
+#
+# General architecture-dependent options
+#
+CONFIG_CRASH_CORE=y
+CONFIG_KEXEC_CORE=y
+CONFIG_HOTPLUG_SMT=y
+CONFIG_OPROFILE=y
+# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+CONFIG_UPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_HAVE_ASM_MODVERSIONS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
+CONFIG_MMU_GATHER_TABLE_FREE=y
+CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_STACKLEAK=y
+CONFIG_HAVE_STACKPROTECTOR=y
+CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOVE_PMD=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_HAVE_ARCH_SOFT_DIRTY=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS=28
+CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
+CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
+CONFIG_HAVE_STACK_VALIDATION=y
+CONFIG_HAVE_RELIABLE_STACKTRACE=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_HAVE_ARCH_VMAP_STACK=y
+CONFIG_VMAP_STACK=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
+CONFIG_ARCH_USE_MEMREMAP_PROT=y
+# CONFIG_LOCK_EVENT_COUNTS is not set
+CONFIG_ARCH_HAS_MEM_ENCRYPT=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+# end of GCOV-based kernel profiling
+
+CONFIG_PLUGIN_HOSTCC=""
+CONFIG_HAVE_GCC_PLUGINS=y
+# end of General architecture-dependent options
+
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BLK_CGROUP_RWSTAT=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_INTEGRITY_T10=y
+# CONFIG_BLK_DEV_ZONED is not set
+CONFIG_BLK_DEV_THROTTLING=y
+# CONFIG_BLK_DEV_THROTTLING_LOW is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+# CONFIG_BLK_WBT is not set
+# CONFIG_BLK_CGROUP_IOLATENCY is not set
+# CONFIG_BLK_CGROUP_IOCOST is not set
+CONFIG_BLK_DEBUG_FS=y
+# CONFIG_BLK_SED_OPAL is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_CUMANA=y
+CONFIG_ACORN_PARTITION_EESOX=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_ADFS=y
+CONFIG_ACORN_PARTITION_POWERTEC=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_AIX_PARTITION=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_CMDLINE_PARTITION=y
+# end of Partition Types
+
+CONFIG_BLOCK_COMPAT=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_MQ_VIRTIO=y
+CONFIG_BLK_PM=y
+
+#
+# IO Schedulers
+#
+CONFIG_MQ_IOSCHED_DEADLINE=y
+CONFIG_MQ_IOSCHED_KYBER=y
+# CONFIG_IOSCHED_BFQ is not set
+# end of IO Schedulers
+
+CONFIG_PADATA=y
+CONFIG_ASN1=y
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_FREEZER=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+CONFIG_BINFMT_MISC=y
+CONFIG_COREDUMP=y
+# end of Executable file formats
+
+#
+# Memory Management options
+#
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_HAVE_FAST_GUP=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_CONTIG_ALLOC=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_MEMORY_FAILURE=y
+CONFIG_HWPOISON_INJECT=y
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_AREAS=7
+CONFIG_ZSWAP=y
+CONFIG_ZPOOL=y
+CONFIG_ZBUD=y
+# CONFIG_Z3FOLD is not set
+CONFIG_ZSMALLOC=y
+CONFIG_PGTABLE_MAPPING=y
+# CONFIG_ZSMALLOC_STAT is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_ARCH_HAS_PTE_DEVMAP=y
+CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
+CONFIG_ARCH_HAS_PKEYS=y
+# CONFIG_PERCPU_STATS is not set
+# CONFIG_GUP_BENCHMARK is not set
+CONFIG_ARCH_HAS_PTE_SPECIAL=y
+# end of Memory Management options
+
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+CONFIG_NET_INGRESS=y
+CONFIG_SKB_EXTENSIONS=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+CONFIG_UNIX_SCM=y
+# CONFIG_UNIX_DIAG is not set
+# CONFIG_TLS is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
+# CONFIG_NET_KEY is not set
+# CONFIG_XDP_SOCKETS is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_FIB_TRIE_STATS=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IP_TUNNEL=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE_COMMON=y
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=y
+CONFIG_NET_UDP_TUNNEL=y
+CONFIG_NET_FOU=y
+CONFIG_NET_FOU_IP_TUNNELS=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_ESP_OFFLOAD is not set
+# CONFIG_INET_ESPINTCP is not set
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_UDP_DIAG=y
+# CONFIG_INET_RAW_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_TCP_CONG_HTCP=y
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_MPTCP is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NET_PTP_CLASSIFY=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_INGRESS=y
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NETFILTER_NETLINK_OSF is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NF_LOG_NETDEV is not set
+# CONFIG_NF_TABLES is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# end of Core Netfilter Configuration
+
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_SOCKET_IPV4 is not set
+# CONFIG_NF_TPROXY_IPV4 is not set
+# CONFIG_NF_DUP_IPV4 is not set
+# CONFIG_NF_LOG_ARP is not set
+# CONFIG_NF_LOG_IPV4 is not set
+# CONFIG_NF_REJECT_IPV4 is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# end of IP: Netfilter Configuration
+
+# CONFIG_BPFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_DNS_RESOLVER is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_NET_NSH is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+CONFIG_NET_FLOW_LIMIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# end of Network testing
+# end of Networking options
+
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
+CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_CFG80211_WEXT_EXPORT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_MAC80211_MESSAGE_TRACING=y
+CONFIG_MAC80211_DEBUG_MENU=y
+# CONFIG_MAC80211_NOINLINE is not set
+CONFIG_MAC80211_VERBOSE_DEBUG=y
+# CONFIG_MAC80211_MLME_DEBUG is not set
+CONFIG_MAC80211_STA_DEBUG=y
+CONFIG_MAC80211_HT_DEBUG=y
+CONFIG_MAC80211_OCB_DEBUG=y
+CONFIG_MAC80211_IBSS_DEBUG=y
+CONFIG_MAC80211_PS_DEBUG=y
+CONFIG_MAC80211_TDLS_DEBUG=y
+# CONFIG_MAC80211_DEBUG_COUNTERS is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+CONFIG_WIMAX=y
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=y
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_PSAMPLE is not set
+# CONFIG_NET_IFE is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+CONFIG_GRO_CELLS=y
+# CONFIG_FAILOVER is not set
+CONFIG_ETHTOOL_NETLINK=y
+CONFIG_HAVE_EBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_HAVE_EISA=y
+# CONFIG_EISA is not set
+CONFIG_HAVE_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_HOTPLUG_PCI_PCIE is not set
+CONFIG_PCIEAER=y
+# CONFIG_PCIEAER_INJECT is not set
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
+CONFIG_PCIE_PME=y
+# CONFIG_PCIE_DPC is not set
+# CONFIG_PCIE_PTM is not set
+# CONFIG_PCIE_BW is not set
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_PCI_REALLOC_ENABLE_AUTO=y
+CONFIG_PCI_STUB=y
+# CONFIG_PCI_PF_STUB is not set
+CONFIG_PCI_ATS=y
+CONFIG_PCI_LOCKLESS_CONFIG=y
+CONFIG_PCI_IOV=y
+CONFIG_PCI_PRI=y
+CONFIG_PCI_PASID=y
+CONFIG_PCI_LABEL=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_ACPI=y
+CONFIG_HOTPLUG_PCI_ACPI_IBM=y
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=y
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=y
+CONFIG_HOTPLUG_PCI_SHPC=y
+
+#
+# PCI controller drivers
+#
+# CONFIG_VMD is not set
+
+#
+# DesignWare PCI Core Support
+#
+# CONFIG_PCIE_DW_PLAT_HOST is not set
+# CONFIG_PCI_MESON is not set
+# end of DesignWare PCI Core Support
+
+#
+# Cadence PCIe controllers support
+#
+# end of Cadence PCIe controllers support
+# end of PCI controller drivers
+
+#
+# PCI Endpoint
+#
+# CONFIG_PCI_ENDPOINT is not set
+# end of PCI Endpoint
+
+#
+# PCI switch controller drivers
+#
+# CONFIG_PCI_SW_SWITCHTEC is not set
+# end of PCI switch controller drivers
+
+CONFIG_PCCARD=y
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=y
+CONFIG_I82092=y
+CONFIG_PCCARD_NONSTATIC=y
+CONFIG_RAPIDIO=y
+CONFIG_RAPIDIO_TSI721=y
+CONFIG_RAPIDIO_DISC_TIMEOUT=30
+# CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS is not set
+CONFIG_RAPIDIO_DMA_ENGINE=y
+# CONFIG_RAPIDIO_DEBUG is not set
+CONFIG_RAPIDIO_ENUM_BASIC=y
+# CONFIG_RAPIDIO_CHMAN is not set
+# CONFIG_RAPIDIO_MPORT_CDEV is not set
+
+#
+# RapidIO Switch drivers
+#
+CONFIG_RAPIDIO_TSI57X=y
+CONFIG_RAPIDIO_CPS_XX=y
+CONFIG_RAPIDIO_TSI568=y
+CONFIG_RAPIDIO_CPS_GEN2=y
+# CONFIG_RAPIDIO_RXS_GEN3 is not set
+# end of RapidIO Switch drivers
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Firmware loader
+#
+CONFIG_FW_LOADER=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_EXTRA_FIRMWARE="iwlwifi-7265D-29.ucode iwlwifi-7260-17.ucode iwlwifi-7265-17.ucode iwlwifi-8265-27.ucode iwlwifi-6000-4.ucode iwlwifi-6000g2a-5.ucode iwlwifi-6000g2a-6.ucode iwlwifi-6000g2b-5.ucode iwlwifi-6000g2b-6.ucode"
+CONFIG_EXTRA_FIRMWARE_DIR="../linux-firmware"
+CONFIG_FW_LOADER_USER_HELPER=y
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+# CONFIG_FW_LOADER_COMPRESS is not set
+CONFIG_FW_CACHE=y
+# end of Firmware loader
+
+CONFIG_WANT_DEV_COREDUMP=y
+CONFIG_ALLOW_DEV_COREDUMP=y
+CONFIG_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_CPU_VULNERABILITIES=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_DMA_FENCE_TRACE is not set
+# end of Generic Driver Options
+
+#
+# Bus devices
+#
+# end of Bus devices
+
+# CONFIG_CONNECTOR is not set
+# CONFIG_GNSS is not set
+# CONFIG_MTD is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_NULL_BLK=y
+# CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION is not set
+CONFIG_BLK_DEV_FD=y
+CONFIG_CDROM=y
+CONFIG_BLK_DEV_PCIESSD_MTIP32XX=y
+CONFIG_ZRAM=y
+# CONFIG_ZRAM_WRITEBACK is not set
+# CONFIG_ZRAM_MEMORY_TRACKING is not set
+CONFIG_BLK_DEV_UMEM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_SKD=y
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_CDROM_PKTCDVD=y
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_VIRTIO_BLK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_BLK_DEV_RSXX is not set
+
+#
+# NVME Support
+#
+CONFIG_NVME_CORE=y
+CONFIG_BLK_DEV_NVME=y
+# CONFIG_NVME_MULTIPATH is not set
+# CONFIG_NVME_HWMON is not set
+# CONFIG_NVME_FC is not set
+# CONFIG_NVME_TCP is not set
+# CONFIG_NVME_TARGET is not set
+# end of NVME Support
+
+#
+# Misc devices
+#
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+CONFIG_TIFM_CORE=y
+# CONFIG_TIFM_7XX1 is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+CONFIG_SRAM=y
+# CONFIG_PCI_ENDPOINT_TEST is not set
+# CONFIG_XILINX_SDFEC is not set
+# CONFIG_PVPANIC is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=y
+# CONFIG_EEPROM_93XX46 is not set
+# CONFIG_EEPROM_IDT_89HPESX is not set
+# CONFIG_EEPROM_EE1004 is not set
+# end of EEPROM support
+
+CONFIG_CB710_CORE=y
+# CONFIG_CB710_DEBUG is not set
+CONFIG_CB710_DEBUG_ASSUMPTIONS=y
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# end of Texas Instruments shared transport line discipline
+
+# CONFIG_SENSORS_LIS3_I2C is not set
+# CONFIG_ALTERA_STAPL is not set
+# CONFIG_INTEL_MEI is not set
+# CONFIG_INTEL_MEI_ME is not set
+# CONFIG_INTEL_MEI_TXE is not set
+# CONFIG_VMWARE_VMCI is not set
+
+#
+# Intel MIC & related support
+#
+# CONFIG_INTEL_MIC_BUS is not set
+# CONFIG_SCIF_BUS is not set
+# CONFIG_VOP_BUS is not set
+# end of Intel MIC & related support
+
+# CONFIG_GENWQE is not set
+# CONFIG_ECHO is not set
+# CONFIG_MISC_ALCOR_PCI is not set
+# CONFIG_MISC_RTSX_PCI is not set
+# CONFIG_MISC_RTSX_USB is not set
+# CONFIG_HABANA_AI is not set
+# end of Misc devices
+
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
+CONFIG_SCSI_SAS_LIBSAS=y
+# CONFIG_SCSI_SAS_ATA is not set
+CONFIG_SCSI_SAS_HOST_SMP=y
+CONFIG_SCSI_SRP_ATTRS=y
+# end of SCSI Transports
+
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# end of SCSI device support
+
+CONFIG_ATA=y
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATA_ACPI=y
+# CONFIG_SATA_ZPODD is not set
+CONFIG_SATA_PMP=y
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_MOBILE_LPM_POLICY=0
+CONFIG_SATA_AHCI_PLATFORM=y
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_SATA_ACARD_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_DWC is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+
+#
+# PATA SFF controllers with BMDMA
+#
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+
+#
+# PIO-only SFF controllers
+#
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_PCMCIA is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_RZ1000 is not set
+
+#
+# Generic fallback / legacy drivers
+#
+# CONFIG_PATA_ACPI is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_LEGACY is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+# CONFIG_MD_AUTODETECT is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BCACHE=y
+# CONFIG_BCACHE_DEBUG is not set
+# CONFIG_BCACHE_CLOSURES_DEBUG is not set
+CONFIG_BLK_DEV_DM_BUILTIN=y
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_BUFIO=y
+# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set
+CONFIG_DM_BIO_PRISON=y
+CONFIG_DM_PERSISTENT_DATA=y
+# CONFIG_DM_UNSTRIPED is not set
+CONFIG_DM_CRYPT=y
+CONFIG_DM_SNAPSHOT=y
+CONFIG_DM_THIN_PROVISIONING=y
+CONFIG_DM_CACHE=y
+CONFIG_DM_CACHE_SMQ=y
+# CONFIG_DM_WRITECACHE is not set
+CONFIG_DM_ERA=y
+# CONFIG_DM_CLONE is not set
+CONFIG_DM_MIRROR=y
+# CONFIG_DM_LOG_USERSPACE is not set
+# CONFIG_DM_RAID is not set
+CONFIG_DM_ZERO=y
+CONFIG_DM_MULTIPATH=y
+CONFIG_DM_MULTIPATH_QL=y
+CONFIG_DM_MULTIPATH_ST=y
+CONFIG_DM_DELAY=y
+# CONFIG_DM_DUST is not set
+# CONFIG_DM_INIT is not set
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=y
+CONFIG_DM_VERITY=y
+# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG is not set
+# CONFIG_DM_VERITY_FEC is not set
+CONFIG_DM_SWITCH=y
+# CONFIG_DM_LOG_WRITES is not set
+# CONFIG_DM_INTEGRITY is not set
+CONFIG_TARGET_CORE=y
+CONFIG_TCM_IBLOCK=y
+CONFIG_TCM_FILEIO=y
+CONFIG_TCM_PSCSI=y
+CONFIG_LOOPBACK_TARGET=y
+# CONFIG_ISCSI_TARGET is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# end of IEEE 1394 (FireWire) support
+
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_WIREGUARD is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_IPVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_GENEVE is not set
+# CONFIG_GTP is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_RIONET is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_VIRTIO_NET is not set
+# CONFIG_NLMON is not set
+# CONFIG_ARCNET is not set
+
+#
+# Distributed Switch Architecture drivers
+#
+# end of Distributed Switch Architecture drivers
+
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_VORTEX is not set
+# CONFIG_TYPHOON is not set
+CONFIG_NET_VENDOR_ADAPTEC=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_NET_VENDOR_AGERE=y
+# CONFIG_ET131X is not set
+CONFIG_NET_VENDOR_ALACRITECH=y
+# CONFIG_SLICOSS is not set
+CONFIG_NET_VENDOR_ALTEON=y
+# CONFIG_ACENIC is not set
+# CONFIG_ALTERA_TSE is not set
+CONFIG_NET_VENDOR_AMAZON=y
+# CONFIG_ENA_ETHERNET is not set
+CONFIG_NET_VENDOR_AMD=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_PCNET32 is not set
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_AMD_XGBE is not set
+CONFIG_NET_VENDOR_AQUANTIA=y
+# CONFIG_AQTION is not set
+CONFIG_NET_VENDOR_ARC=y
+CONFIG_NET_VENDOR_ATHEROS=y
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ALX is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BCMGENET is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+CONFIG_TIGON3=y
+# CONFIG_TIGON3_HWMON is not set
+# CONFIG_BNX2X is not set
+# CONFIG_SYSTEMPORT is not set
+# CONFIG_BNXT is not set
+CONFIG_NET_VENDOR_BROCADE=y
+# CONFIG_BNA is not set
+CONFIG_NET_VENDOR_CADENCE=y
+# CONFIG_MACB is not set
+CONFIG_NET_VENDOR_CAVIUM=y
+# CONFIG_THUNDER_NIC_PF is not set
+# CONFIG_THUNDER_NIC_VF is not set
+# CONFIG_THUNDER_NIC_BGX is not set
+# CONFIG_THUNDER_NIC_RGX is not set
+# CONFIG_CAVIUM_PTP is not set
+# CONFIG_LIQUIDIO is not set
+# CONFIG_LIQUIDIO_VF is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_CHELSIO_T4VF is not set
+CONFIG_NET_VENDOR_CISCO=y
+# CONFIG_ENIC is not set
+CONFIG_NET_VENDOR_CORTINA=y
+# CONFIG_CX_ECAT is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_DEC=y
+# CONFIG_NET_TULIP is not set
+CONFIG_NET_VENDOR_DLINK=y
+# CONFIG_DL2K is not set
+# CONFIG_SUNDANCE is not set
+CONFIG_NET_VENDOR_EMULEX=y
+# CONFIG_BE2NET is not set
+CONFIG_NET_VENDOR_EZCHIP=y
+CONFIG_NET_VENDOR_FUJITSU=y
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_NET_VENDOR_GOOGLE=y
+# CONFIG_GVE is not set
+CONFIG_NET_VENDOR_HUAWEI=y
+# CONFIG_HINIC is not set
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+CONFIG_IGB=y
+CONFIG_IGB_HWMON=y
+CONFIG_IGB_DCA=y
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
+# CONFIG_I40E is not set
+# CONFIG_I40EVF is not set
+# CONFIG_ICE is not set
+# CONFIG_FM10K is not set
+# CONFIG_IGC is not set
+# CONFIG_JME is not set
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+CONFIG_NET_VENDOR_MELLANOX=y
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX5_CORE is not set
+# CONFIG_MLXSW_CORE is not set
+# CONFIG_MLXFW is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSZ884X_PCI is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_LAN743X is not set
+CONFIG_NET_VENDOR_MICROSEMI=y
+CONFIG_NET_VENDOR_MYRI=y
+# CONFIG_MYRI10GE is not set
+# CONFIG_FEALNX is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+# CONFIG_NATSEMI is not set
+# CONFIG_NS83820 is not set
+CONFIG_NET_VENDOR_NETERION=y
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+CONFIG_NET_VENDOR_NETRONOME=y
+# CONFIG_NFP is not set
+CONFIG_NET_VENDOR_NI=y
+# CONFIG_NI_XGE_MANAGEMENT_ENET is not set
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_PCMCIA_PCNET is not set
+CONFIG_NET_VENDOR_NVIDIA=y
+# CONFIG_FORCEDETH is not set
+CONFIG_NET_VENDOR_OKI=y
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_PACKET_ENGINES=y
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_NET_VENDOR_PENSANDO=y
+# CONFIG_IONIC is not set
+CONFIG_NET_VENDOR_QLOGIC=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_QED is not set
+CONFIG_NET_VENDOR_QUALCOMM=y
+# CONFIG_QCOM_EMAC is not set
+# CONFIG_RMNET is not set
+CONFIG_NET_VENDOR_RDC=y
+# CONFIG_R6040 is not set
+CONFIG_NET_VENDOR_REALTEK=y
+CONFIG_8139CP=y
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+CONFIG_8139TOO_TUNE_TWISTER=y
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R8169=y
+CONFIG_NET_VENDOR_RENESAS=y
+CONFIG_NET_VENDOR_ROCKER=y
+CONFIG_NET_VENDOR_SAMSUNG=y
+# CONFIG_SXGBE_ETH is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SOLARFLARE=y
+# CONFIG_SFC is not set
+# CONFIG_SFC_FALCON is not set
+CONFIG_NET_VENDOR_SILAN=y
+# CONFIG_SC92031 is not set
+CONFIG_NET_VENDOR_SIS=y
+# CONFIG_SIS900 is not set
+# CONFIG_SIS190 is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_SMSC9420 is not set
+CONFIG_NET_VENDOR_SOCIONEXT=y
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_SUN=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NIU is not set
+CONFIG_NET_VENDOR_SYNOPSYS=y
+# CONFIG_DWC_XLGMAC is not set
+CONFIG_NET_VENDOR_TEHUTI=y
+# CONFIG_TEHUTI is not set
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TI_CPSW_PHY_SEL is not set
+# CONFIG_TLAN is not set
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+CONFIG_NET_VENDOR_XILINX=y
+# CONFIG_XILINX_AXI_EMAC is not set
+# CONFIG_XILINX_LL_TEMAC is not set
+CONFIG_NET_VENDOR_XIRCOM=y
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_NET_SB1000 is not set
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_BUS=y
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_MSCC_MIIM is not set
+# CONFIG_MDIO_THUNDER is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+CONFIG_LED_TRIGGER_PHY=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_ADIN_PHY is not set
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AX88796B_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM84881_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_CORTINA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83822_PHY is not set
+# CONFIG_DP83TC811_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+# CONFIG_DP83869_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MARVELL_10G_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROCHIP_T1_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_NXP_TJA11XX_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+CONFIG_REALTEK_PHY=y
+# CONFIG_RENESAS_PHY is not set
+# CONFIG_ROCKCHIP_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_RTL8152=y
+# CONFIG_USB_LAN78XX is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_AX88179_178A=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set
+# CONFIG_USB_NET_CDC_MBIM is not set
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SR9700 is not set
+# CONFIG_USB_NET_SR9800 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+# CONFIG_USB_NET_SMSC95XX is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET_ENABLE=y
+CONFIG_USB_NET_CDC_SUBSET=y
+# CONFIG_USB_ALI_M5632 is not set
+# CONFIG_USB_AN2720 is not set
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_QMI_WWAN is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+# CONFIG_USB_NET_CH9200 is not set
+# CONFIG_USB_NET_AQC111 is not set
+CONFIG_WLAN=y
+# CONFIG_WIRELESS_WDS is not set
+CONFIG_WLAN_VENDOR_ADMTEK=y
+# CONFIG_ADM8211 is not set
+CONFIG_ATH_COMMON=y
+CONFIG_WLAN_VENDOR_ATH=y
+CONFIG_ATH_DEBUG=y
+CONFIG_ATH_TRACEPOINTS=y
+# CONFIG_ATH5K is not set
+# CONFIG_ATH5K_PCI is not set
+CONFIG_ATH9K_HW=y
+CONFIG_ATH9K_COMMON=y
+CONFIG_ATH9K_COMMON_DEBUG=y
+CONFIG_ATH9K_BTCOEX_SUPPORT=y
+CONFIG_ATH9K=y
+CONFIG_ATH9K_PCI=y
+# CONFIG_ATH9K_AHB is not set
+CONFIG_ATH9K_DEBUGFS=y
+CONFIG_ATH9K_STATION_STATISTICS=y
+# CONFIG_ATH9K_DYNACK is not set
+# CONFIG_ATH9K_WOW is not set
+CONFIG_ATH9K_RFKILL=y
+# CONFIG_ATH9K_CHANNEL_CONTEXT is not set
+CONFIG_ATH9K_PCOEM=y
+# CONFIG_ATH9K_PCI_NO_EEPROM is not set
+CONFIG_ATH9K_HTC=y
+CONFIG_ATH9K_HTC_DEBUGFS=y
+# CONFIG_ATH9K_HWRNG is not set
+# CONFIG_ATH9K_COMMON_SPECTRAL is not set
+# CONFIG_CARL9170 is not set
+# CONFIG_ATH6KL is not set
+# CONFIG_AR5523 is not set
+# CONFIG_WIL6210 is not set
+# CONFIG_ATH10K is not set
+# CONFIG_WCN36XX is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+# CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMSMAC is not set
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+# CONFIG_AIRO is not set
+# CONFIG_AIRO_CS is not set
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_IPW2100=y
+# CONFIG_IPW2100_MONITOR is not set
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=y
+# CONFIG_IPW2200_MONITOR is not set
+# CONFIG_IPW2200_QOS is not set
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBIPW=y
+# CONFIG_LIBIPW_DEBUG is not set
+CONFIG_IWLEGACY=y
+CONFIG_IWL4965=y
+CONFIG_IWL3945=y
+
+#
+# iwl3945 / iwl4965 Debugging Options
+#
+# CONFIG_IWLEGACY_DEBUG is not set
+# CONFIG_IWLEGACY_DEBUGFS is not set
+# end of iwl3945 / iwl4965 Debugging Options
+
+CONFIG_IWLWIFI=y
+CONFIG_IWLWIFI_LEDS=y
+CONFIG_IWLDVM=y
+CONFIG_IWLMVM=y
+# CONFIG_IWLWIFI_BCAST_FILTERING is not set
+
+#
+# Debugging Options
+#
+# CONFIG_IWLWIFI_DEBUG is not set
+# CONFIG_IWLWIFI_DEBUGFS is not set
+CONFIG_IWLWIFI_DEVICE_TRACING=y
+# end of Debugging Options
+
+CONFIG_WLAN_VENDOR_INTERSIL=y
+# CONFIG_HOSTAP is not set
+# CONFIG_HERMES is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_PRISM54 is not set
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MWIFIEX is not set
+# CONFIG_MWL8K is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+# CONFIG_MT7601U is not set
+# CONFIG_MT76x0U is not set
+# CONFIG_MT76x0E is not set
+# CONFIG_MT76x2E is not set
+# CONFIG_MT76x2U is not set
+# CONFIG_MT7603E is not set
+# CONFIG_MT7615E is not set
+CONFIG_WLAN_VENDOR_RALINK=y
+# CONFIG_RT2X00 is not set
+CONFIG_WLAN_VENDOR_REALTEK=y
+# CONFIG_RTL8180 is not set
+# CONFIG_RTL8187 is not set
+CONFIG_RTL_CARDS=y
+# CONFIG_RTL8192CE is not set
+# CONFIG_RTL8192SE is not set
+# CONFIG_RTL8192DE is not set
+# CONFIG_RTL8723AE is not set
+# CONFIG_RTL8723BE is not set
+# CONFIG_RTL8188EE is not set
+# CONFIG_RTL8192EE is not set
+# CONFIG_RTL8821AE is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_RTL8XXXU is not set
+# CONFIG_RTW88 is not set
+CONFIG_WLAN_VENDOR_RSI=y
+# CONFIG_RSI_91X is not set
+CONFIG_WLAN_VENDOR_ST=y
+# CONFIG_CW1200 is not set
+CONFIG_WLAN_VENDOR_TI=y
+# CONFIG_WL1251 is not set
+# CONFIG_WL12XX is not set
+# CONFIG_WL18XX is not set
+# CONFIG_WLCORE is not set
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_ZD1211RW is not set
+CONFIG_WLAN_VENDOR_QUANTENNA=y
+# CONFIG_QTNFMAC_PCIE is not set
+# CONFIG_PCMCIA_RAYCS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_VIRT_WIFI is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# end of WiMAX Wireless Broadband devices
+
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_FUJITSU_ES is not set
+# CONFIG_NETDEVSIM is not set
+# CONFIG_NET_FAILOVER is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_LEDS=y
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_SPARSEKMAP is not set
+CONFIG_INPUT_MATRIXKMAP=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ADP5588=y
+CONFIG_KEYBOARD_ADP5589=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1050 is not set
+CONFIG_KEYBOARD_QT1070=y
+CONFIG_KEYBOARD_QT2160=y
+# CONFIG_KEYBOARD_DLINK_DIR685 is not set
+CONFIG_KEYBOARD_LKKBD=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+CONFIG_KEYBOARD_TCA6416=y
+CONFIG_KEYBOARD_TCA8418=y
+CONFIG_KEYBOARD_MATRIX=y
+CONFIG_KEYBOARD_LM8323=y
+CONFIG_KEYBOARD_LM8333=y
+CONFIG_KEYBOARD_MAX7359=y
+CONFIG_KEYBOARD_MCS=y
+CONFIG_KEYBOARD_MPR121=y
+CONFIG_KEYBOARD_NEWTON=y
+CONFIG_KEYBOARD_OPENCORES=y
+CONFIG_KEYBOARD_SAMSUNG=y
+CONFIG_KEYBOARD_STOWAWAY=y
+CONFIG_KEYBOARD_SUNKBD=y
+# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set
+CONFIG_KEYBOARD_XTKBD=y
+CONFIG_KEYBOARD_CROS_EC=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_PS2_ELANTECH_SMBUS=y
+CONFIG_MOUSE_PS2_SENTELIC=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_PS2_FOCALTECH=y
+CONFIG_MOUSE_PS2_VMMOUSE=y
+CONFIG_MOUSE_PS2_SMBUS=y
+CONFIG_MOUSE_SERIAL=y
+CONFIG_MOUSE_APPLETOUCH=y
+CONFIG_MOUSE_BCM5974=y
+CONFIG_MOUSE_CYAPA=y
+CONFIG_MOUSE_ELAN_I2C=y
+CONFIG_MOUSE_ELAN_I2C_I2C=y
+CONFIG_MOUSE_ELAN_I2C_SMBUS=y
+CONFIG_MOUSE_VSXXXAA=y
+CONFIG_MOUSE_GPIO=y
+CONFIG_MOUSE_SYNAPTICS_I2C=y
+CONFIG_MOUSE_SYNAPTICS_USB=y
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=y
+CONFIG_JOYSTICK_A3D=y
+CONFIG_JOYSTICK_ADI=y
+CONFIG_JOYSTICK_COBRA=y
+CONFIG_JOYSTICK_GF2K=y
+CONFIG_JOYSTICK_GRIP=y
+CONFIG_JOYSTICK_GRIP_MP=y
+CONFIG_JOYSTICK_GUILLEMOT=y
+CONFIG_JOYSTICK_INTERACT=y
+CONFIG_JOYSTICK_SIDEWINDER=y
+CONFIG_JOYSTICK_TMDC=y
+CONFIG_JOYSTICK_IFORCE=y
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=y
+CONFIG_JOYSTICK_MAGELLAN=y
+CONFIG_JOYSTICK_SPACEORB=y
+CONFIG_JOYSTICK_SPACEBALL=y
+CONFIG_JOYSTICK_STINGER=y
+CONFIG_JOYSTICK_TWIDJOY=y
+CONFIG_JOYSTICK_ZHENHUA=y
+CONFIG_JOYSTICK_AS5011=y
+CONFIG_JOYSTICK_JOYDUMP=y
+CONFIG_JOYSTICK_XPAD=y
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+# CONFIG_JOYSTICK_PSXPAD_SPI is not set
+# CONFIG_JOYSTICK_PXRC is not set
+# CONFIG_JOYSTICK_FSIA6B is not set
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=y
+CONFIG_TABLET_USB_AIPTEK=y
+CONFIG_TABLET_USB_GTCO=y
+CONFIG_TABLET_USB_HANWANG=y
+CONFIG_TABLET_USB_KBTAB=y
+# CONFIG_TABLET_USB_PEGASUS is not set
+CONFIG_TABLET_SERIAL_WACOM4=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_BU21029 is not set
+# CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
+# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set
+# CONFIG_TOUCHSCREEN_EXC3000 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GOODIX is not set
+# CONFIG_TOUCHSCREEN_HIDEEP is not set
+# CONFIG_TOUCHSCREEN_ILI210X is not set
+# CONFIG_TOUCHSCREEN_S6SY761 is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_EKTF2127 is not set
+CONFIG_TOUCHSCREEN_ELAN=y
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MMS114 is not set
+# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=y
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_USB_JASTEC=y
+CONFIG_TOUCHSCREEN_USB_ELO=y
+CONFIG_TOUCHSCREEN_USB_E2I=y
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y
+CONFIG_TOUCHSCREEN_USB_NEXIO=y
+CONFIG_TOUCHSCREEN_USB_EASYTOUCH=y
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+# CONFIG_TOUCHSCREEN_TSC2004 is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_RM_TS is not set
+# CONFIG_TOUCHSCREEN_SILEAD is not set
+# CONFIG_TOUCHSCREEN_SIS_I2C is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_STMFTS is not set
+# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set
+# CONFIG_TOUCHSCREEN_SX8654 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+# CONFIG_TOUCHSCREEN_ZET6223 is not set
+# CONFIG_TOUCHSCREEN_ZFORCE is not set
+# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set
+# CONFIG_TOUCHSCREEN_IQS5XX is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MSM_VIBRATOR is not set
+# CONFIG_INPUT_PCSPKR is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_APANEL is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_GPIO_VIBRA is not set
+# CONFIG_INPUT_ATLAS_BTNS is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_IMS_PCU is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set
+# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+CONFIG_RMI4_CORE=y
+# CONFIG_RMI4_I2C is not set
+# CONFIG_RMI4_SPI is not set
+# CONFIG_RMI4_SMB is not set
+CONFIG_RMI4_F03=y
+CONFIG_RMI4_F03_SERIO=y
+CONFIG_RMI4_2D_SENSOR=y
+CONFIG_RMI4_F11=y
+CONFIG_RMI4_F12=y
+CONFIG_RMI4_F30=y
+# CONFIG_RMI4_F34 is not set
+# CONFIG_RMI4_F55 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_GPIO_PS2 is not set
+# CONFIG_USERIO is not set
+CONFIG_GAMEPORT=y
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# end of Hardware I/O ports
+# end of Input device support
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=0
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+# CONFIG_NULL_TTY is not set
+CONFIG_LDISC_AUTOLOAD=y
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_PNP=y
+# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
+# CONFIG_SERIAL_8250_FINTEK is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DMA=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_EXAR=y
+CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=48
+CONFIG_SERIAL_8250_RUNTIME_UARTS=32
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+CONFIG_SERIAL_8250_DWLIB=y
+CONFIG_SERIAL_8250_DW=y
+# CONFIG_SERIAL_8250_RT288X is not set
+CONFIG_SERIAL_8250_LPSS=y
+# CONFIG_SERIAL_8250_MID is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_KGDB_NMI is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_CONSOLE_POLL=y
+CONFIG_SERIAL_JSM=y
+CONFIG_SERIAL_SCCNXP=y
+# CONFIG_SERIAL_SCCNXP_CONSOLE is not set
+CONFIG_SERIAL_SC16IS7XX_CORE=y
+CONFIG_SERIAL_SC16IS7XX=y
+CONFIG_SERIAL_SC16IS7XX_I2C=y
+# CONFIG_SERIAL_SC16IS7XX_SPI is not set
+CONFIG_SERIAL_ALTERA_JTAGUART=y
+# CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE is not set
+CONFIG_SERIAL_ALTERA_UART=y
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
+# CONFIG_SERIAL_ALTERA_UART_CONSOLE is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+CONFIG_SERIAL_ARC=y
+# CONFIG_SERIAL_ARC_CONSOLE is not set
+CONFIG_SERIAL_ARC_NR_PORTS=1
+CONFIG_SERIAL_RP2=y
+CONFIG_SERIAL_RP2_NR_UARTS=32
+CONFIG_SERIAL_FSL_LPUART=y
+# CONFIG_SERIAL_FSL_LPUART_CONSOLE is not set
+# CONFIG_SERIAL_FSL_LINFLEXUART is not set
+# end of Serial drivers
+
+CONFIG_SERIAL_MCTRL_GPIO=y
+# CONFIG_SERIAL_DEV_BUS is not set
+CONFIG_TTY_PRINTK=y
+CONFIG_TTY_PRINTK_LEVEL=6
+# CONFIG_VIRTIO_CONSOLE is not set
+CONFIG_IPMI_HANDLER=y
+CONFIG_IPMI_DMI_DECODE=y
+CONFIG_IPMI_PLAT_DATA=y
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=y
+CONFIG_IPMI_SI=y
+CONFIG_IPMI_SSIF=y
+CONFIG_IPMI_WATCHDOG=y
+CONFIG_IPMI_POWEROFF=y
+# CONFIG_IPMB_DEVICE_INTERFACE is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=y
+CONFIG_HW_RANDOM_INTEL=y
+CONFIG_HW_RANDOM_AMD=y
+CONFIG_HW_RANDOM_VIA=y
+# CONFIG_HW_RANDOM_VIRTIO is not set
+CONFIG_NVRAM=y
+CONFIG_APPLICOM=y
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=y
+CONFIG_CARDMAN_4000=y
+CONFIG_CARDMAN_4040=y
+# CONFIG_SCR24X is not set
+# CONFIG_IPWIRELESS is not set
+# end of PCMCIA character devices
+
+CONFIG_MWAVE=y
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HPET_MMAP_DEFAULT=y
+CONFIG_HANGCHECK_TIMER=y
+CONFIG_TCG_TPM=y
+CONFIG_HW_RANDOM_TPM=y
+CONFIG_TCG_TIS_CORE=y
+CONFIG_TCG_TIS=y
+# CONFIG_TCG_TIS_SPI is not set
+CONFIG_TCG_TIS_I2C_ATMEL=y
+CONFIG_TCG_TIS_I2C_INFINEON=y
+CONFIG_TCG_TIS_I2C_NUVOTON=y
+CONFIG_TCG_NSC=y
+CONFIG_TCG_ATMEL=y
+CONFIG_TCG_INFINEON=y
+# CONFIG_TCG_CRB is not set
+# CONFIG_TCG_VTPM_PROXY is not set
+# CONFIG_TCG_TIS_ST33ZP24_I2C is not set
+# CONFIG_TCG_TIS_ST33ZP24_SPI is not set
+CONFIG_TELCLOCK=y
+CONFIG_DEVPORT=y
+CONFIG_XILLYBUS=y
+CONFIG_XILLYBUS_PCIE=y
+# end of Character devices
+
+# CONFIG_RANDOM_TRUST_CPU is not set
+# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_ACPI_I2C_OPREGION=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+CONFIG_I2C_MUX_GPIO=y
+# CONFIG_I2C_MUX_LTC4306 is not set
+CONFIG_I2C_MUX_PCA9541=y
+CONFIG_I2C_MUX_PCA954x=y
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_MUX_MLXCPLD is not set
+# end of Multiplexer I2C Chip support
+
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_SMBUS=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_AMD_MP2 is not set
+CONFIG_I2C_I801=y
+CONFIG_I2C_ISCH=y
+CONFIG_I2C_ISMT=y
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_NVIDIA_GPU is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# ACPI drivers
+#
+CONFIG_I2C_SCMI=y
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+CONFIG_I2C_DESIGNWARE_CORE=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+# CONFIG_I2C_DESIGNWARE_SLAVE is not set
+CONFIG_I2C_DESIGNWARE_PCI=y
+CONFIG_I2C_DESIGNWARE_BAYTRAIL=y
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_MLXCPLD is not set
+CONFIG_I2C_CROS_EC_TUNNEL=y
+# end of I2C Hardware Bus support
+
+CONFIG_I2C_SLAVE=y
+CONFIG_I2C_SLAVE_EEPROM=y
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# end of I2C support
+
+# CONFIG_I3C is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+# CONFIG_SPI_MEM is not set
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+CONFIG_SPI_DESIGNWARE=y
+CONFIG_SPI_DW_PCI=y
+CONFIG_SPI_DW_MID_DMA=y
+CONFIG_SPI_DW_MMIO=y
+# CONFIG_SPI_NXP_FLEXSPI is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_SIFIVE is not set
+# CONFIG_SPI_MXIC is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPI_SLAVE is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+CONFIG_PPS=y
+# CONFIG_PPS_DEBUG is not set
+
+#
+# PPS clients support
+#
+# CONFIG_PPS_CLIENT_KTIMER is not set
+CONFIG_PPS_CLIENT_LDISC=y
+CONFIG_PPS_CLIENT_GPIO=y
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+# end of PTP clock support
+
+CONFIG_PINCTRL=y
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_MCP23S08 is not set
+CONFIG_PINCTRL_SX150X=y
+CONFIG_PINCTRL_BAYTRAIL=y
+CONFIG_PINCTRL_CHERRYVIEW=y
+# CONFIG_PINCTRL_LYNXPOINT is not set
+# CONFIG_PINCTRL_BROXTON is not set
+# CONFIG_PINCTRL_CANNONLAKE is not set
+# CONFIG_PINCTRL_CEDARFORK is not set
+# CONFIG_PINCTRL_DENVERTON is not set
+# CONFIG_PINCTRL_GEMINILAKE is not set
+# CONFIG_PINCTRL_ICELAKE is not set
+# CONFIG_PINCTRL_LEWISBURG is not set
+# CONFIG_PINCTRL_SUNRISEPOINT is not set
+# CONFIG_PINCTRL_TIGERLAKE is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_FASTPATH_LIMIT=512
+CONFIG_GPIO_ACPI=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GPIO_MAX730X=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_AMDPT is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EXAR is not set
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_ICH=y
+# CONFIG_GPIO_MB86S7X is not set
+CONFIG_GPIO_VX855=y
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_AMD_FCH is not set
+# end of Memory mapped GPIO drivers
+
+#
+# Port-mapped I/O GPIO drivers
+#
+CONFIG_GPIO_F7188X=y
+# CONFIG_GPIO_IT87 is not set
+CONFIG_GPIO_SCH=y
+CONFIG_GPIO_SCH311X=y
+# CONFIG_GPIO_WINBOND is not set
+# CONFIG_GPIO_WS16C48 is not set
+# end of Port-mapped I/O GPIO drivers
+
+#
+# I2C GPIO expanders
+#
+CONFIG_GPIO_ADP5588=y
+# CONFIG_GPIO_ADP5588_IRQ is not set
+CONFIG_GPIO_MAX7300=y
+CONFIG_GPIO_MAX732X=y
+# CONFIG_GPIO_MAX732X_IRQ is not set
+CONFIG_GPIO_PCA953X=y
+# CONFIG_GPIO_PCA953X_IRQ is not set
+CONFIG_GPIO_PCF857X=y
+# CONFIG_GPIO_TPIC2810 is not set
+# end of I2C GPIO expanders
+
+#
+# MFD GPIO expanders
+#
+# end of MFD GPIO expanders
+
+#
+# PCI GPIO expanders
+#
+CONFIG_GPIO_AMD8111=y
+# CONFIG_GPIO_BT8XX is not set
+CONFIG_GPIO_ML_IOH=y
+# CONFIG_GPIO_PCI_IDIO_16 is not set
+# CONFIG_GPIO_PCIE_IDIO_24 is not set
+CONFIG_GPIO_RDC321X=y
+# end of PCI GPIO expanders
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX3191X is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+# CONFIG_GPIO_XRA1403 is not set
+# end of SPI GPIO expanders
+
+#
+# USB GPIO expanders
+#
+# end of USB GPIO expanders
+
+# CONFIG_GPIO_MOCKUP is not set
+CONFIG_W1=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_MATROX is not set
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+# CONFIG_W1_MASTER_SGI is not set
+# end of 1-wire Bus Masters
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2405 is not set
+# CONFIG_W1_SLAVE_DS2408 is not set
+# CONFIG_W1_SLAVE_DS2413 is not set
+# CONFIG_W1_SLAVE_DS2406 is not set
+# CONFIG_W1_SLAVE_DS2423 is not set
+# CONFIG_W1_SLAVE_DS2805 is not set
+# CONFIG_W1_SLAVE_DS2430 is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2438 is not set
+# CONFIG_W1_SLAVE_DS250X is not set
+CONFIG_W1_SLAVE_DS2780=y
+CONFIG_W1_SLAVE_DS2781=y
+# CONFIG_W1_SLAVE_DS28E04 is not set
+# CONFIG_W1_SLAVE_DS28E17 is not set
+# end of 1-wire Slaves
+
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_RESTART is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_POWER_SUPPLY_HWMON=y
+CONFIG_PDA_POWER=y
+CONFIG_TEST_POWER=y
+# CONFIG_CHARGER_ADP5061 is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_DS2780=y
+CONFIG_BATTERY_DS2781=y
+CONFIG_BATTERY_DS2782=y
+CONFIG_BATTERY_SBS=y
+# CONFIG_CHARGER_SBS is not set
+# CONFIG_MANAGER_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+CONFIG_BATTERY_MAX17040=y
+CONFIG_BATTERY_MAX17042=y
+# CONFIG_BATTERY_MAX1721X is not set
+CONFIG_CHARGER_ISP1704=y
+CONFIG_CHARGER_MAX8903=y
+CONFIG_CHARGER_LP8727=y
+CONFIG_CHARGER_GPIO=y
+# CONFIG_CHARGER_LT3651 is not set
+CONFIG_CHARGER_BQ2415X=y
+CONFIG_CHARGER_BQ24190=y
+# CONFIG_CHARGER_BQ24257 is not set
+CONFIG_CHARGER_BQ24735=y
+# CONFIG_CHARGER_BQ25890 is not set
+CONFIG_CHARGER_SMB347=y
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_CHARGER_CROS_USBPD is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7314 is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM1177 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7310 is not set
+# CONFIG_SENSORS_ADT7410 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_AS370 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_K10TEMP is not set
+# CONFIG_SENSORS_FAM15H_POWER is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ASPEED is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DRIVETEMP is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+CONFIG_SENSORS_DELL_SMM=y
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_G762 is not set
+# CONFIG_SENSORS_HIH6130 is not set
+# CONFIG_SENSORS_IBMAEM is not set
+# CONFIG_SENSORS_IBMPEX is not set
+CONFIG_SENSORS_I5500=y
+CONFIG_SENSORS_CORETEMP=y
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_POWR1220 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LTC2945 is not set
+# CONFIG_SENSORS_LTC2947_I2C is not set
+# CONFIG_SENSORS_LTC2947_SPI is not set
+# CONFIG_SENSORS_LTC2990 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4222 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4260 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX31722 is not set
+# CONFIG_SENSORS_MAX31730 is not set
+# CONFIG_SENSORS_MAX6621 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MAX6697 is not set
+# CONFIG_SENSORS_MAX31790 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_TC654 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LM95234 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_NCT6683 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_NCT7802 is not set
+# CONFIG_SENSORS_NCT7904 is not set
+# CONFIG_SENSORS_NPCM7XX is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SHT3x is not set
+# CONFIG_SENSORS_SHTC1 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_STTS751 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_ADC128D818 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA209 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_INA3221 is not set
+# CONFIG_SENSORS_TC74 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP103 is not set
+# CONFIG_SENSORS_TMP108 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_TMP513 is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83773G is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+
+#
+# ACPI drivers
+#
+CONFIG_SENSORS_ACPI_POWER=y
+# CONFIG_SENSORS_ATK0110 is not set
+CONFIG_THERMAL=y
+# CONFIG_THERMAL_STATISTICS is not set
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+CONFIG_THERMAL_GOV_FAIR_SHARE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_BANG_BANG=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_EMULATION=y
+
+#
+# Intel thermal drivers
+#
+CONFIG_INTEL_POWERCLAMP=y
+CONFIG_X86_PKG_TEMP_THERMAL=y
+CONFIG_INTEL_SOC_DTS_IOSF_CORE=y
+CONFIG_INTEL_SOC_DTS_THERMAL=y
+
+#
+# ACPI INT340X thermal drivers
+#
+CONFIG_INT340X_THERMAL=y
+CONFIG_ACPI_THERMAL_REL=y
+# end of ACPI INT340X thermal drivers
+
+# CONFIG_INTEL_PCH_THERMAL is not set
+# end of Intel thermal drivers
+
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+CONFIG_SSB=y
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+# CONFIG_SSB_PCMCIAHOST is not set
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+# CONFIG_SSB_SDIOHOST is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+# CONFIG_SSB_DRIVER_GPIO is not set
+CONFIG_BCMA_POSSIBLE=y
+CONFIG_BCMA=y
+CONFIG_BCMA_HOST_PCI_POSSIBLE=y
+# CONFIG_BCMA_HOST_PCI is not set
+# CONFIG_BCMA_HOST_SOC is not set
+# CONFIG_BCMA_DRIVER_PCI is not set
+# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
+# CONFIG_BCMA_DRIVER_GPIO is not set
+# CONFIG_BCMA_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_BD9571MWV is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+CONFIG_MFD_CROS_EC_DEV=y
+# CONFIG_MFD_MADERA is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
+CONFIG_LPC_ICH=y
+CONFIG_LPC_SCH=y
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_INTEL_SOC_PMIC_CHTWC is not set
+# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set
+CONFIG_MFD_INTEL_LPSS=y
+CONFIG_MFD_INTEL_LPSS_ACPI=y
+CONFIG_MFD_INTEL_LPSS_PCI=y
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+CONFIG_MFD_RDC321X=y
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_TI_LMU is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS68470 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TQMX86 is not set
+CONFIG_MFD_VX855=y
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# end of Multifunction device drivers
+
+# CONFIG_REGULATOR is not set
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_VGA_ARB is not set
+# CONFIG_VGA_SWITCHEROO is not set
+# CONFIG_DRM is not set
+
+#
+# ARM devices
+#
+# end of ARM devices
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+# end of ACP (Audio CoProcessor) Configuration
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_BOOT_VESA_SUPPORT=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+CONFIG_FB_VESA=y
+# CONFIG_FB_N411 is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I740 is not set
+# CONFIG_FB_LE80578 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SM712 is not set
+# end of Frame buffer Devices
+
+#
+# Backlight & LCD device support
+#
+# CONFIG_LCD_CLASS_DEVICE is not set
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+# end of Backlight & LCD device support
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=80
+CONFIG_DUMMY_CONSOLE_ROWS=25
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
+# end of Console display driver support
+
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# end of Graphics support
+
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+CONFIG_UHID=y
+# CONFIG_HID_GENERIC is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_ASUS is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CORSAIR is not set
+# CONFIG_HID_COUGAR is not set
+# CONFIG_HID_MACALLY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_VIEWSONIC is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_ITE is not set
+# CONFIG_HID_JABRA is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LED is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MALTRON is not set
+# CONFIG_HID_MAYFLASH is not set
+# CONFIG_HID_REDRAGON is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTI is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEAM is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THINGM is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_UDRAW_PS3 is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+# end of Special HID drivers
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# end of USB HID Boot Protocol drivers
+# end of USB HID support
+
+#
+# I2C HID support
+#
+CONFIG_I2C_HID=y
+# end of I2C HID support
+
+#
+# Intel ISH HID support
+#
+# CONFIG_INTEL_ISH_HID is not set
+# end of Intel ISH HID support
+# end of HID support
+
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+# CONFIG_USB_LED_TRIG is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_USB_CONN_GPIO is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_PCI=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set
+CONFIG_USB_AUTOSUSPEND_DELAY=2
+CONFIG_USB_MON=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+# CONFIG_USB_XHCI_DBGCAP is not set
+CONFIG_USB_XHCI_PCI=y
+# CONFIG_USB_XHCI_PLATFORM is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_PCI=y
+# CONFIG_USB_EHCI_FSL is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PCI=y
+# CONFIG_USB_OHCI_HCD_SSB is not set
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_BCMA is not set
+# CONFIG_USB_HCD_SSB is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+CONFIG_USB_TMC=y
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_REALTEK=y
+CONFIG_REALTEK_AUTOPM=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_UAS=y
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=y
+CONFIG_USB_MICROTEK=y
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_CDNS3 is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_CONSOLE is not set
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=y
+CONFIG_USB_SERIAL_AIRCABLE=y
+CONFIG_USB_SERIAL_ARK3116=y
+CONFIG_USB_SERIAL_BELKIN=y
+CONFIG_USB_SERIAL_CH341=y
+CONFIG_USB_SERIAL_WHITEHEAT=y
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=y
+CONFIG_USB_SERIAL_CP210X=y
+CONFIG_USB_SERIAL_CYPRESS_M8=y
+CONFIG_USB_SERIAL_EMPEG=y
+CONFIG_USB_SERIAL_FTDI_SIO=y
+CONFIG_USB_SERIAL_VISOR=y
+CONFIG_USB_SERIAL_IPAQ=y
+CONFIG_USB_SERIAL_IR=y
+CONFIG_USB_SERIAL_EDGEPORT=y
+CONFIG_USB_SERIAL_EDGEPORT_TI=y
+CONFIG_USB_SERIAL_F81232=y
+# CONFIG_USB_SERIAL_F8153X is not set
+CONFIG_USB_SERIAL_GARMIN=y
+CONFIG_USB_SERIAL_IPW=y
+CONFIG_USB_SERIAL_IUU=y
+CONFIG_USB_SERIAL_KEYSPAN_PDA=y
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KLSI=y
+CONFIG_USB_SERIAL_KOBIL_SCT=y
+CONFIG_USB_SERIAL_MCT_U232=y
+CONFIG_USB_SERIAL_METRO=y
+CONFIG_USB_SERIAL_MOS7720=y
+CONFIG_USB_SERIAL_MOS7840=y
+CONFIG_USB_SERIAL_MXUPORT=y
+CONFIG_USB_SERIAL_NAVMAN=y
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_SERIAL_OTI6858=y
+CONFIG_USB_SERIAL_QCAUX=y
+CONFIG_USB_SERIAL_QUALCOMM=y
+CONFIG_USB_SERIAL_SPCP8X5=y
+CONFIG_USB_SERIAL_SAFE=y
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=y
+CONFIG_USB_SERIAL_SYMBOL=y
+CONFIG_USB_SERIAL_TI=y
+CONFIG_USB_SERIAL_CYBERJACK=y
+CONFIG_USB_SERIAL_XIRCOM=y
+CONFIG_USB_SERIAL_WWAN=y
+CONFIG_USB_SERIAL_OPTION=y
+CONFIG_USB_SERIAL_OMNINET=y
+CONFIG_USB_SERIAL_OPTICON=y
+CONFIG_USB_SERIAL_XSENS_MT=y
+CONFIG_USB_SERIAL_WISHBONE=y
+CONFIG_USB_SERIAL_SSU100=y
+CONFIG_USB_SERIAL_QT2=y
+# CONFIG_USB_SERIAL_UPD78F0730 is not set
+CONFIG_USB_SERIAL_DEBUG=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_EZUSB_FX2=y
+# CONFIG_USB_HUB_USB251XB is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+# CONFIG_USB_CHAOSKEY is not set
+
+#
+# USB Physical Layer drivers
+#
+CONFIG_USB_PHY=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_ISP1301=y
+# end of USB Physical Layer drivers
+
+# CONFIG_USB_GADGET is not set
+# CONFIG_TYPEC is not set
+# CONFIG_USB_ROLE_SWITCH is not set
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_IO_ACCESSORS=y
+CONFIG_MMC_SDHCI_PCI=y
+CONFIG_MMC_RICOH_MMC=y
+CONFIG_MMC_SDHCI_ACPI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+CONFIG_MMC_WBSD=y
+CONFIG_MMC_TIFM_SD=y
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_SDRICOH_CS=y
+CONFIG_MMC_CB710=y
+CONFIG_MMC_VIA_SDMMC=y
+CONFIG_MMC_VUB300=y
+CONFIG_MMC_USHC=y
+CONFIG_MMC_USDHI6ROL0=y
+CONFIG_MMC_CQHCI=y
+CONFIG_MMC_TOSHIBA_PCI=y
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_SDHCI_XENON is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_CLASS_FLASH is not set
+# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_APU is not set
+CONFIG_LEDS_LM3530=y
+# CONFIG_LEDS_LM3532 is not set
+CONFIG_LEDS_LM3642=y
+CONFIG_LEDS_PCA9532=y
+CONFIG_LEDS_PCA9532_GPIO=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_LP3944=y
+# CONFIG_LEDS_LP3952 is not set
+CONFIG_LEDS_LP55XX_COMMON=y
+CONFIG_LEDS_LP5521=y
+CONFIG_LEDS_LP5523=y
+CONFIG_LEDS_LP5562=y
+CONFIG_LEDS_LP8501=y
+CONFIG_LEDS_CLEVO_MAIL=y
+CONFIG_LEDS_PCA955X=y
+# CONFIG_LEDS_PCA955X_GPIO is not set
+CONFIG_LEDS_PCA963X=y
+# CONFIG_LEDS_DAC124S085 is not set
+CONFIG_LEDS_BD2802=y
+CONFIG_LEDS_INTEL_SS4200=y
+CONFIG_LEDS_TCA6507=y
+# CONFIG_LEDS_TLC591XX is not set
+CONFIG_LEDS_LM355x=y
+
+#
+# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
+#
+CONFIG_LEDS_BLINKM=y
+# CONFIG_LEDS_MLXCPLD is not set
+# CONFIG_LEDS_MLXREG is not set
+# CONFIG_LEDS_USER is not set
+# CONFIG_LEDS_NIC78BX is not set
+# CONFIG_LEDS_TI_LMU_COMMON is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+# CONFIG_LEDS_TRIGGER_DISK is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+# CONFIG_LEDS_TRIGGER_ACTIVITY is not set
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+# CONFIG_LEDS_TRIGGER_PANIC is not set
+# CONFIG_LEDS_TRIGGER_NETDEV is not set
+# CONFIG_LEDS_TRIGGER_PATTERN is not set
+# CONFIG_LEDS_TRIGGER_AUDIO is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_MC146818_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+CONFIG_RTC_NVMEM=y
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABEOZ9 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1307_CENTURY is not set
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS1374_WDT=y
+CONFIG_RTC_DRV_DS1672=y
+CONFIG_RTC_DRV_MAX6900=y
+CONFIG_RTC_DRV_RS5C372=y
+CONFIG_RTC_DRV_ISL1208=y
+CONFIG_RTC_DRV_ISL12022=y
+CONFIG_RTC_DRV_X1205=y
+CONFIG_RTC_DRV_PCF8523=y
+CONFIG_RTC_DRV_PCF85063=y
+# CONFIG_RTC_DRV_PCF85363 is not set
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_PCF8583=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_FM3130=y
+# CONFIG_RTC_DRV_RX8010 is not set
+CONFIG_RTC_DRV_RX8581=y
+CONFIG_RTC_DRV_RX8025=y
+CONFIG_RTC_DRV_EM3027=y
+# CONFIG_RTC_DRV_RV3028 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+# CONFIG_RTC_DRV_SD3078 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS3232=y
+CONFIG_RTC_DRV_DS3232_HWMON=y
+CONFIG_RTC_DRV_PCF2127=y
+CONFIG_RTC_DRV_RV3029C2=y
+CONFIG_RTC_DRV_RV3029_HWMON=y
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1286=y
+CONFIG_RTC_DRV_DS1511=y
+CONFIG_RTC_DRV_DS1553=y
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+CONFIG_RTC_DRV_DS1742=y
+CONFIG_RTC_DRV_DS2404=y
+CONFIG_RTC_DRV_STK17TA8=y
+CONFIG_RTC_DRV_M48T86=y
+CONFIG_RTC_DRV_M48T35=y
+CONFIG_RTC_DRV_M48T59=y
+CONFIG_RTC_DRV_MSM6242=y
+CONFIG_RTC_DRV_BQ4802=y
+CONFIG_RTC_DRV_RP5C01=y
+CONFIG_RTC_DRV_V3020=y
+# CONFIG_RTC_DRV_CROS_EC is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_FTRTC010 is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_ACPI=y
+# CONFIG_ALTERA_MSGDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_INTEL_IDXD is not set
+CONFIG_INTEL_IOATDMA=y
+# CONFIG_PLX_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+CONFIG_DW_DMAC_CORE=y
+CONFIG_DW_DMAC=y
+CONFIG_DW_DMAC_PCI=y
+# CONFIG_DW_EDMA is not set
+# CONFIG_DW_EDMA_PCIE is not set
+# CONFIG_SF_PDMA is not set
+
+#
+# DMA Clients
+#
+CONFIG_ASYNC_TX_DMA=y
+# CONFIG_DMATEST is not set
+CONFIG_DMA_ENGINE_RAID=y
+
+#
+# DMABUF options
+#
+CONFIG_SYNC_FILE=y
+# CONFIG_SW_SYNC is not set
+# CONFIG_UDMABUF is not set
+# CONFIG_DMABUF_SELFTESTS is not set
+# CONFIG_DMABUF_HEAPS is not set
+# end of DMABUF options
+
+CONFIG_DCA=y
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_MENU=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_PCI_LEGACY=y
+# CONFIG_VIRTIO_PMEM is not set
+# CONFIG_VIRTIO_BALLOON is not set
+# CONFIG_VIRTIO_INPUT is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_HYPERV is not set
+# end of Microsoft Hyper-V guest support
+
+# CONFIG_GREYBUS is not set
+# CONFIG_STAGING is not set
+# CONFIG_X86_PLATFORM_DEVICES is not set
+CONFIG_PMC_ATOM=y
+CONFIG_MFD_CROS_EC=y
+CONFIG_CHROME_PLATFORMS=y
+CONFIG_CHROMEOS_LAPTOP=y
+CONFIG_CHROMEOS_PSTORE=y
+# CONFIG_CHROMEOS_TBMC is not set
+CONFIG_CROS_EC=y
+# CONFIG_CROS_EC_I2C is not set
+# CONFIG_CROS_EC_SPI is not set
+CONFIG_CROS_EC_LPC=y
+CONFIG_CROS_EC_PROTO=y
+CONFIG_CROS_KBD_LED_BACKLIGHT=y
+CONFIG_CROS_EC_CHARDEV=y
+CONFIG_CROS_EC_LIGHTBAR=y
+CONFIG_CROS_EC_DEBUGFS=y
+CONFIG_CROS_EC_SENSORHUB=y
+CONFIG_CROS_EC_SYSFS=y
+# CONFIG_WILCO_EC is not set
+# CONFIG_MELLANOX_PLATFORM is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_MAX9485 is not set
+# CONFIG_COMMON_CLK_SI5341 is not set
+CONFIG_COMMON_CLK_SI5351=y
+# CONFIG_COMMON_CLK_SI544 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# end of Common Clock Framework
+
+# CONFIG_HWSPINLOCK is not set
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKEVT_I8253=y
+CONFIG_I8253_LOCK=y
+CONFIG_CLKBLD_I8253=y
+# end of Clock Source drivers
+
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_REMOTEPROC is not set
+# end of Remoteproc drivers
+
+#
+# Rpmsg drivers
+#
+# CONFIG_RPMSG_VIRTIO is not set
+# end of Rpmsg drivers
+
+# CONFIG_SOUNDWIRE is not set
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Amlogic SoC drivers
+#
+# end of Amlogic SoC drivers
+
+#
+# Aspeed SoC drivers
+#
+# end of Aspeed SoC drivers
+
+#
+# Broadcom SoC drivers
+#
+# end of Broadcom SoC drivers
+
+#
+# NXP/Freescale QorIQ SoC drivers
+#
+# end of NXP/Freescale QorIQ SoC drivers
+
+#
+# i.MX SoC drivers
+#
+# end of i.MX SoC drivers
+
+#
+# Qualcomm SoC drivers
+#
+# end of Qualcomm SoC drivers
+
+# CONFIG_SOC_TI is not set
+
+#
+# Xilinx SoC drivers
+#
+# CONFIG_XILINX_VCU is not set
+# end of Xilinx SoC drivers
+# end of SOC (System On Chip) specific Drivers
+
+# CONFIG_PM_DEVFREQ is not set
+CONFIG_EXTCON=y
+
+#
+# Extcon Device Drivers
+#
+# CONFIG_EXTCON_FSA9480 is not set
+# CONFIG_EXTCON_GPIO is not set
+# CONFIG_EXTCON_INTEL_INT3496 is not set
+# CONFIG_EXTCON_MAX3355 is not set
+# CONFIG_EXTCON_PTN5150 is not set
+# CONFIG_EXTCON_RT8973A is not set
+# CONFIG_EXTCON_SM5502 is not set
+# CONFIG_EXTCON_USB_GPIO is not set
+# CONFIG_EXTCON_USBC_CROS_EC is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_NTB is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_PWM is not set
+
+#
+# IRQ chip support
+#
+# end of IRQ chip support
+
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_BRCMSTB_RESCAL is not set
+# CONFIG_RESET_TI_SYSCON is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+CONFIG_BCM_KONA_USB2_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_PHY_INTEL_EMMC is not set
+# end of PHY Subsystem
+
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# end of Performance monitor support
+
+CONFIG_RAS=y
+# CONFIG_RAS_CEC is not set
+# CONFIG_USB4 is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# end of Android
+
+CONFIG_LIBNVDIMM=y
+CONFIG_BLK_DEV_PMEM=y
+CONFIG_ND_BLK=y
+CONFIG_ND_CLAIM=y
+CONFIG_ND_BTT=y
+CONFIG_BTT=y
+CONFIG_DAX_DRIVER=y
+CONFIG_DAX=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SYSFS=y
+
+#
+# HW tracing support
+#
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+# end of HW tracing support
+
+# CONFIG_FPGA is not set
+# CONFIG_TEE is not set
+# CONFIG_UNISYS_VISORBUS is not set
+# CONFIG_SIOX is not set
+# CONFIG_SLIMBUS is not set
+# CONFIG_INTERCONNECT is not set
+# CONFIG_COUNTER is not set
+# end of Device Drivers
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_VALIDATE_FS_PARSER is not set
+CONFIG_FS_IOMAP=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_DAX=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS_BLOCK_OPS=y
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+CONFIG_FS_ENCRYPTION=y
+CONFIG_FS_ENCRYPTION_ALGS=y
+# CONFIG_FS_VERITY is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QUOTA_DEBUG is not set
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+CONFIG_QUOTACTL_COMPAT=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+# CONFIG_VIRTIO_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+# end of Caches
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+# end of CD-ROM/DVD Filesystems
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+# end of DOS/FAT/NT Filesystems
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_CHILDREN=y
+CONFIG_PROC_PID_ARCH_STATUS=y
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLBFS is not set
+CONFIG_MEMFD_CREATE=y
+CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
+CONFIG_CONFIGFS_FS=y
+# end of Pseudo filesystems
+
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_FILE_CACHE is not set
+CONFIG_SQUASHFS_FILE_DIRECT=y
+# CONFIG_SQUASHFS_DECOMP_SINGLE is not set
+# CONFIG_SQUASHFS_DECOMP_MULTI is not set
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_ZLIB=y
+# CONFIG_SQUASHFS_LZ4 is not set
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+# CONFIG_SQUASHFS_ZSTD is not set
+# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_PSTORE=y
+CONFIG_PSTORE_DEFLATE_COMPRESS=y
+# CONFIG_PSTORE_LZO_COMPRESS is not set
+# CONFIG_PSTORE_LZ4_COMPRESS is not set
+# CONFIG_PSTORE_LZ4HC_COMPRESS is not set
+# CONFIG_PSTORE_842_COMPRESS is not set
+# CONFIG_PSTORE_ZSTD_COMPRESS is not set
+CONFIG_PSTORE_COMPRESS=y
+CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y
+CONFIG_PSTORE_COMPRESS_DEFAULT="deflate"
+# CONFIG_PSTORE_CONSOLE is not set
+# CONFIG_PSTORE_PMSG is not set
+# CONFIG_PSTORE_FTRACE is not set
+CONFIG_PSTORE_RAM=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_EROFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=y
+# CONFIG_9P_FS_POSIX_ACL is not set
+# CONFIG_9P_FS_SECURITY is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+# CONFIG_UNICODE is not set
+CONFIG_IO_WQ=y
+# end of File systems
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_REQUEST_CACHE is not set
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_TRUSTED_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+CONFIG_SECURITYFS=y
+CONFIG_PAGE_TABLE_ISOLATION=y
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+# CONFIG_HARDENED_USERCOPY is not set
+# CONFIG_FORTIFY_SOURCE is not set
+# CONFIG_STATIC_USERMODEHELPER is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity"
+
+#
+# Kernel hardening options
+#
+
+#
+# Memory initialization
+#
+CONFIG_INIT_STACK_NONE=y
+# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
+# CONFIG_INIT_ON_FREE_DEFAULT_ON is not set
+# end of Memory initialization
+# end of Kernel hardening options
+# end of Security options
+
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SKCIPHER=y
+CONFIG_CRYPTO_SKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_AKCIPHER=y
+CONFIG_CRYPTO_KPP2=y
+CONFIG_CRYPTO_KPP=y
+CONFIG_CRYPTO_ACOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_PCRYPT=y
+CONFIG_CRYPTO_CRYPTD=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_SIMD=y
+CONFIG_CRYPTO_GLUE_HELPER_X86=y
+CONFIG_CRYPTO_ENGINE=y
+
+#
+# Public-key cryptography
+#
+CONFIG_CRYPTO_RSA=y
+CONFIG_CRYPTO_DH=y
+# CONFIG_CRYPTO_ECDH is not set
+# CONFIG_CRYPTO_ECRDSA is not set
+# CONFIG_CRYPTO_CURVE25519 is not set
+# CONFIG_CRYPTO_CURVE25519_X86 is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_AEGIS128 is not set
+# CONFIG_CRYPTO_AEGIS128_AESNI_SSE2 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=y
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CFB is not set
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_CTS=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+# CONFIG_CRYPTO_OFB is not set
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_XTS=y
+# CONFIG_CRYPTO_KEYWRAP is not set
+# CONFIG_CRYPTO_NHPOLY1305_SSE2 is not set
+# CONFIG_CRYPTO_NHPOLY1305_AVX2 is not set
+# CONFIG_CRYPTO_ADIANTUM is not set
+CONFIG_CRYPTO_ESSIV=y
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_VMAC=y
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_CRC32C_INTEL=y
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32_PCLMUL=y
+# CONFIG_CRYPTO_XXHASH is not set
+# CONFIG_CRYPTO_BLAKE2B is not set
+# CONFIG_CRYPTO_BLAKE2S is not set
+# CONFIG_CRYPTO_BLAKE2S_X86 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_CRCT10DIF_PCLMUL=y
+CONFIG_CRYPTO_GHASH=y
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_POLY1305_X86_64 is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=y
+CONFIG_CRYPTO_RMD160=y
+CONFIG_CRYPTO_RMD256=y
+CONFIG_CRYPTO_RMD320=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA1_SSSE3=y
+CONFIG_CRYPTO_SHA256_SSSE3=y
+CONFIG_CRYPTO_SHA512_SSSE3=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_SM3 is not set
+# CONFIG_CRYPTO_STREEBOG is not set
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=y
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_AES_TI is not set
+CONFIG_CRYPTO_AES_NI_INTEL=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_BLOWFISH_COMMON=y
+CONFIG_CRYPTO_BLOWFISH_X86_64=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_CAMELLIA_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=y
+CONFIG_CRYPTO_CAST_COMMON=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST5_AVX_X86_64=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_CAST6_AVX_X86_64=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_DES3_EDE_X86_64=y
+CONFIG_CRYPTO_FCRYPT=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_SALSA20=y
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_CHACHA20_X86_64 is not set
+CONFIG_CRYPTO_SEED=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_SERPENT_SSE2_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX2_X86_64=y
+# CONFIG_CRYPTO_SM4 is not set
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+CONFIG_CRYPTO_TWOFISH_X86_64=y
+CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=y
+CONFIG_CRYPTO_TWOFISH_AVX_X86_64=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+CONFIG_CRYPTO_LZ4=y
+CONFIG_CRYPTO_LZ4HC=y
+# CONFIG_CRYPTO_ZSTD is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_HASH=y
+CONFIG_CRYPTO_DRBG_CTR=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HASH_INFO=y
+
+#
+# Crypto library routines
+#
+CONFIG_CRYPTO_LIB_AES=y
+CONFIG_CRYPTO_LIB_ARC4=y
+# CONFIG_CRYPTO_LIB_BLAKE2S is not set
+# CONFIG_CRYPTO_LIB_CHACHA is not set
+# CONFIG_CRYPTO_LIB_CURVE25519 is not set
+CONFIG_CRYPTO_LIB_DES=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11
+# CONFIG_CRYPTO_LIB_POLY1305 is not set
+# CONFIG_CRYPTO_LIB_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_LIB_SHA256=y
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=y
+CONFIG_CRYPTO_DEV_PADLOCK_AES=y
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=y
+# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set
+# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set
+CONFIG_CRYPTO_DEV_CCP=y
+CONFIG_CRYPTO_DEV_CCP_DD=y
+CONFIG_CRYPTO_DEV_SP_CCP=y
+CONFIG_CRYPTO_DEV_CCP_CRYPTO=y
+CONFIG_CRYPTO_DEV_SP_PSP=y
+# CONFIG_CRYPTO_DEV_CCP_DEBUGFS is not set
+CONFIG_CRYPTO_DEV_QAT=y
+CONFIG_CRYPTO_DEV_QAT_DH895xCC=y
+# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set
+# CONFIG_CRYPTO_DEV_QAT_C62X is not set
+# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set
+# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set
+# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set
+# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set
+CONFIG_CRYPTO_DEV_VIRTIO=y
+# CONFIG_CRYPTO_DEV_SAFEXCEL is not set
+# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set
+CONFIG_ASYMMETRIC_KEY_TYPE=y
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_X509_CERTIFICATE_PARSER=y
+# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set
+CONFIG_PKCS7_MESSAGE_PARSER=y
+# CONFIG_PKCS7_TEST_KEY is not set
+# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set
+
+#
+# Certificates for signature checking
+#
+CONFIG_SYSTEM_TRUSTED_KEYRING=y
+CONFIG_SYSTEM_TRUSTED_KEYS=""
+# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
+# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
+# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
+# end of Certificates for signature checking
+
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+# CONFIG_PACKING is not set
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_CORDIC=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC64=y
+# CONFIG_CRC4 is not set
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_CRC8=y
+CONFIG_XXHASH=y
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4HC_COMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_XZ_DEC_TEST=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_ENC8=y
+CONFIG_REED_SOLOMON_DEC8=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_SWIOTLB=y
+# CONFIG_DMA_CMA is not set
+# CONFIG_DMA_API_DEBUG is not set
+CONFIG_SGL_ALLOC=y
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_GLOB=y
+# CONFIG_GLOB_SELFTEST is not set
+CONFIG_NLATTR=y
+CONFIG_CLZ_TAB=y
+# CONFIG_IRQ_POLL is not set
+CONFIG_MPILIB=y
+CONFIG_OID_REGISTRY=y
+CONFIG_HAVE_GENERIC_VDSO=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_VDSO_TIME_NS=y
+CONFIG_FONT_SUPPORT=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_PMEM_API=y
+CONFIG_MEMREGION=y
+CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
+CONFIG_ARCH_HAS_UACCESS_MCSAFE=y
+CONFIG_ARCH_STACKWALK=y
+CONFIG_SBITMAP=y
+# CONFIG_STRING_SELFTEST is not set
+# end of Library routines
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+# CONFIG_PRINTK_CALLER is not set
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
+CONFIG_CONSOLE_LOGLEVEL_QUIET=4
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_SYMBOLIC_ERRNAME=y
+CONFIG_DEBUG_BUGVERBOSE=y
+# end of printk and dmesg options
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_HEADERS_INSTALL is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+CONFIG_STACK_VALIDATION=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# end of Compile-time checks and compiler options
+
+#
+# Generic Kernel Debugging Instruments
+#
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+CONFIG_MAGIC_SYSRQ_SERIAL=y
+CONFIG_DEBUG_FS=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_KGDB=y
+CONFIG_KGDB_SERIAL_CONSOLE=y
+# CONFIG_KGDB_TESTS is not set
+CONFIG_KGDB_LOW_LEVEL_TRAP=y
+CONFIG_KGDB_KDB=y
+CONFIG_KDB_DEFAULT_ENABLE=0x1
+# CONFIG_KDB_KEYBOARD is not set
+CONFIG_KDB_CONTINUE_CATASTROPHIC=0
+CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
+# CONFIG_UBSAN is not set
+CONFIG_UBSAN_ALIGNMENT=y
+# end of Generic Kernel Debugging Instruments
+
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_MISC=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_PAGE_REF is not set
+# CONFIG_DEBUG_RODATA_TEST is not set
+CONFIG_GENERIC_PTDUMP=y
+# CONFIG_PTDUMP_DEBUGFS is not set
+CONFIG_DEBUG_OBJECTS=y
+# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
+# CONFIG_DEBUG_OBJECTS_FREE is not set
+# CONFIG_DEBUG_OBJECTS_TIMERS is not set
+# CONFIG_DEBUG_OBJECTS_WORK is not set
+# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set
+# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set
+CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+CONFIG_HAVE_ARCH_KASAN=y
+CONFIG_HAVE_ARCH_KASAN_VMALLOC=y
+CONFIG_CC_HAS_KASAN_GENERIC=y
+# CONFIG_KASAN is not set
+CONFIG_KASAN_STACK=1
+# end of Memory Debugging
+
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Oops, Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y
+CONFIG_HARDLOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_WQ_WATCHDOG is not set
+# end of Debug Oops, Lockups and Hangs
+
+#
+# Scheduler Debugging
+#
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHED_INFO=y
+CONFIG_SCHEDSTATS=y
+# end of Scheduler Debugging
+
+# CONFIG_DEBUG_TIMEKEEPING is not set
+CONFIG_DEBUG_PREEMPT=y
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_WW_MUTEX_SELFTEST is not set
+# end of Lock Debugging (spinlocks, mutexes, etc...)
+
+CONFIG_STACKTRACE=y
+# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
+# CONFIG_DEBUG_KOBJECT is not set
+
+#
+# Debug kernel data structures
+#
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PLIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BUG_ON_DATA_CORRUPTION is not set
+# end of Debug kernel data structures
+
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# end of RCU Debugging
+
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_FENTRY=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_BOOTTIME_TRACING is not set
+CONFIG_FUNCTION_TRACER=y
+CONFIG_FUNCTION_GRAPH_TRACER=y
+CONFIG_DYNAMIC_FTRACE=y
+CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
+# CONFIG_PREEMPTIRQ_EVENTS is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+CONFIG_SCHED_TRACER=y
+# CONFIG_HWLAT_TRACER is not set
+CONFIG_MMIOTRACE=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_TRACER_SNAPSHOT=y
+# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_UPROBE_EVENTS=y
+CONFIG_BPF_EVENTS=y
+CONFIG_DYNAMIC_EVENTS=y
+CONFIG_PROBE_EVENTS=y
+CONFIG_FTRACE_MCOUNT_RECORD=y
+# CONFIG_HIST_TRIGGERS is not set
+# CONFIG_TRACE_EVENT_INJECT is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_TRACE_EVAL_MAP_FILE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_STARTUP_TEST is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_SAMPLES is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+
+#
+# x86 Debugging
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_EARLY_PRINTK_USB=y
+# CONFIG_X86_VERBOSE_BOOTUP is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_EARLY_PRINTK_DBGP=y
+# CONFIG_EARLY_PRINTK_USB_XDBC is not set
+# CONFIG_DEBUG_WX is not set
+CONFIG_DOUBLEFAULT=y
+# CONFIG_DEBUG_TLBFLUSH is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+# CONFIG_X86_DECODER_SELFTEST is not set
+# CONFIG_IO_DELAY_0X80 is not set
+CONFIG_IO_DELAY_0XED=y
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+# CONFIG_DEBUG_BOOT_PARAMS is not set
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_DEBUG_ENTRY is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+CONFIG_X86_DEBUG_FPU=y
+# CONFIG_PUNIT_ATOM_DEBUG is not set
+# CONFIG_UNWINDER_ORC is not set
+CONFIG_UNWINDER_FRAME_POINTER=y
+# CONFIG_UNWINDER_GUESS is not set
+# end of x86 Debugging
+
+#
+# Kernel Testing and Coverage
+#
+# CONFIG_KUNIT is not set
+CONFIG_NOTIFIER_ERROR_INJECTION=y
+CONFIG_PM_NOTIFIER_ERROR_INJECT=y
+# CONFIG_NETDEV_NOTIFIER_ERROR_INJECT is not set
+CONFIG_FAULT_INJECTION=y
+# CONFIG_FAILSLAB is not set
+# CONFIG_FAIL_PAGE_ALLOC is not set
+# CONFIG_FAIL_MAKE_REQUEST is not set
+# CONFIG_FAIL_IO_TIMEOUT is not set
+# CONFIG_FAIL_FUTEX is not set
+# CONFIG_FAULT_INJECTION_DEBUG_FS is not set
+CONFIG_ARCH_HAS_KCOV=y
+CONFIG_CC_HAS_SANCOV_TRACE_PC=y
+# CONFIG_KCOV is not set
+CONFIG_RUNTIME_TESTING_MENU=y
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_TEST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_REED_SOLOMON_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_STRSCPY is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_BITFIELD is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_XARRAY is not set
+# CONFIG_TEST_OVERFLOW is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_TEST_IDA is not set
+# CONFIG_FIND_BIT_BENCHMARK is not set
+CONFIG_TEST_FIRMWARE=y
+# CONFIG_TEST_SYSCTL is not set
+CONFIG_TEST_UDELAY=y
+# CONFIG_TEST_MEMCAT_P is not set
+# CONFIG_TEST_STACKINIT is not set
+# CONFIG_TEST_MEMINIT is not set
+CONFIG_MEMTEST=y
+# end of Kernel Testing and Coverage
+# end of Kernel hacking
diff --git a/webboot/distros.md b/webboot/distros.md
new file mode 100644
index 000000000..8d1ab6282
--- /dev/null
+++ b/webboot/distros.md
@@ -0,0 +1,70 @@
+# Distributions of Linux-based systems
+
+Well... https://twitter.com/OrangeCMS/status/1220605490792751104
+
+This file lists details on how the respective distributions patch and configure
+their kernels, where to obtain the sources and config files, and the download
+URLs for current release ISO images. That helps maintaining and further
+developing webboot.
+
+## Arch Linux
+
+- [ISO](http://mirror.rackspace.com/archlinux/iso/2020.01.01/archlinux-2020.01.01-x86_64.iso)
+- [kernel sources](https://git.archlinux.org/linux.git?signed#tag=v5.4.14-arch1)
+- [kernel config](https://git.archlinux.org/svntogit/packages.git/tree/trunk?h=packages/linux)
+
+### SystemRescueCd
+
+Formerly based on Gentoo, SystemRescueCd now builds on top of Arch Linux. Hence,
+the directory structure in the ISO is similar to the Arch Linux ISO.
+
+It is meant to be a live distro for system rescue tasks, hence the name.
+
+- [download page](http://www.system-rescue-cd.org/Download/)
+- [ISO](https://osdn.net/projects/systemrescuecd/storage/releases/6.0.7/systemrescuecd-6.0.7.iso)
+
+## Fedora
+
+[Build instructions](https://fedoraproject.org/wiki/Building_a_custom_kernel)
+in the wiki are specific to Fedora and not suitable for other systems.
+Cloning from the repository and applying the config should just work though.
+
+- [ISO](https://download.fedoraproject.org/pub/fedora/linux/releases/31/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-31-1.9.iso)
+- [kernel sources](https://src.fedoraproject.org/rpms/kernel/tree/master)
+- [stable sources](https://koji.fedoraproject.org/koji/search?terms=kernel-5.5.0-0.rc6.git3.1.fc32&type=build&match=glob)
+- [kernel config](https://src.fedoraproject.org/rpms/kernel/raw/master/f/kernel-x86_64-fedora.config)
+
+### Release 30
+
+- [ISO](https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/30/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-30-1.2.iso)
+- [netinst](https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/30/Workstation/x86_64/iso/Fedora-Workstation-netinst-x86_64-30-1.2.iso)
+- [kernel sources](https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/30/Workstation/source/tree/Packages/k/kernel-5.0.9-301.fc30.src.rpm)
+
+## openSUSE
+
+Details on the kernel are [in the wiki](https://en.opensuse.org/Kernel), as well
+as [instructions](https://en.opensuse.org/openSUSE:Kernel_git).
+
+- [ISO](https://download.opensuse.org/distribution/leap/15.1/iso/openSUSE-Leap-15.1-DVD-x86_64.iso),
+ [netboot](https://download.opensuse.org/distribution/leap/15.1/iso/openSUSE-Leap-15.1-NET-x86_64.iso)
+- [kernel sources](https://kernel.opensuse.org/cgit/kernel-source/tree/config/x86_64/default?h=openSUSE-15.2)
+- kernel config: within sources, see `config/x86_64/default`
+
+## TinyCore
+
+Patched kernel sources, separate patches and config can be found among the
+[release sources](http://tinycorelinux.net/10.x/x86/release/src/kernel/).
+
+- [Core ISO](http://tinycorelinux.net/10.x/x86/release/Core-current.iso)
+- [CorePlus ISO](http://tinycorelinux.net/10.x/x86/release/CorePlus-current.iso)
+- [TinyCore ISO](http://tinycorelinux.net/10.x/x86/release/TinyCore-current.iso)
+- [kernel sources](http://tinycorelinux.net/10.x/x86/release/src/kernel/linux-4.19.10-patched.txz)
+- [kernel config](http://tinycorelinux.net/10.x/x86/release/src/kernel/config-4.19.10-tinycore)
+
+## Ubuntu
+
+- [kernel sources](http://security.ubuntu.com/ubuntu/pool/main/l/linux-hwe/linux-source-5.0.0_5.0.0-37.40~18.04.1_all.deb)
+- kernel config: included in sources, split into parts for common, arch-specific
+ and generic/low latency bits in `src/linux-source-5.0.0/debian.hwe/config/`:
+ `config.common.ubuntu`, `amd64/config.{common.amd64,flavour.generic}` are
+ the relevant files for webboot on x86
diff --git a/webboot/docs/remaster-arch-iso.md b/webboot/docs/remaster-arch-iso.md
new file mode 100644
index 000000000..c8ef9f356
--- /dev/null
+++ b/webboot/docs/remaster-arch-iso.md
@@ -0,0 +1,143 @@
+# Remaster Arch Linux Live ISO for webboot
+
+## Preparation
+
+In general, follow the steps as described in
+[the wiki](https://wiki.archlinux.org/index.php/Remastering_the_Install_ISO).
+
+For webboot, the following steps are necessary:
+
+- mount ISO
+- extract squashfs
+- copy over kernel
+- copy over [mkinitcpio.conf](https://git.archlinux.org/archiso.git/tree/configs/releng/mkinitcpio.conf) (overwrite `squashfs-root/etc/mkinitcpio.conf`)
+- chroot into rootfs
+- [build new initramfs](#building-the-new-initramfs-in-the-chroot)
+- copy mounted ISO
+- add the new initramfs to it (`iso/arch/boot/x86_64/archiso.img`)
+- build new ISO
+
+## Building the new initramfs in the chroot
+
+Arch has a tool to build a suitable initramfs that is used to create the ISO
+images in the first place. So instead of extracting the existing initramfs,
+hacking on it, and rebuilding it, `mkinitcpio` will do it. There are two
+possible strategies:
+
+1. add the pmem modules to the list of files to include (more generic)
+2. write a custom hook to do it (https://github.com/archlinux/mkinitcpio/pull/30)
+
+### Manual strategy
+
+#### Decompress the modules
+
+This is necessary because the initramfs cannot load compressed modules.
+
+```sh
+cd /lib/modules/5.6.8-arch1-1/kernel/drivers/nvdimm/
+unxz nd_btt.ko.xz
+unxz nd_e820.ko.xz
+unxz nd_pmem.ko.xz
+```
+
+#### Adjust the mkinitcpio config
+
+Add `FILES` to `/etc/mkinitcpio.conf`:
+
+```
+HOOKS=(base udev memdisk archiso_shutdown archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs archiso_kms block filesystems keyboard)
+COMPRESSION="xz"
+### the above is from the copied releng/mkinitcpio.conf
+FILES=(
+/lib/modules/5.6.8-arch1-1/kernel/drivers/nvdimm/nd_btt.ko
+/lib/modules/5.6.8-arch1-1/kernel/drivers/nvdimm/nd_e820.ko
+/lib/modules/5.6.8-arch1-1/kernel/drivers/nvdimm/nd_pmem.ko)
+```
+
+### Using a custom hook
+
+Create the file `/lib/initcpio/install/nvdimm`:
+
+```sh
+#!/bin/bash
+
+build() {
+ add_checked_modules '/drivers/nvdimm/'
+}
+```
+
+And add it to the `HOOKS` in `/etc/mkinitcpio.conf`:
+
+```
+HOOKS=(base udev memdisk archiso_shutdown archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs archiso_kms block filesystems keyboard nvdimm)
+COMPRESSION="xz"
+```
+
+### Create the new initramfs
+
+```sh
+_preset=`ls /etc/mkinitcpio.d/|sed 's#\..*##'`
+mkinitcpio -k $(ls /lib/modules/) -p $preset`
+```
+
+## Try it out
+
+Check that everything works before rebuilding the ISO and trying to boot it.
+
+The location where you extracted the squashfs root may differ. This assumes
+following the guide, using the `run-webboot.sh` script from the repo:
+
+```sh
+$ sh run-webboot.sh \
+ ~/customiso/arch/x86_64/squashfs-root/boot/vmlinuz-linux \
+ ~/customiso/arch/x86_64/squashfs-root/boot/initramfs.img
+```
+
+Check that the modules are present:
+
+```
+[rootfs ]# ls /lib/modules/5.6.8-arch1-1/kernel/drivers/nvdimm/
+nd_btt.ko nd_e820.ko nd_pmem.ko
+```
+
+The modules should be loaded because `memmap` was passed from our script:
+
+```
+[rootfs ]# lsmod
+Module Size Used by
+nd_pmem 24576 0
+nd_btt 28672 1 nd_pmem
+serio_raw 20480 0
+atkbd 36864 0
+libps2 20480 1 atkbd
+nd_e820 16384 1
+sr_mod 28672 0
+cdrom 77824 1 sr_mod
+i8042 32768 0
+serio 28672 5 serio_raw,atkbd,i8042
+```
+
+And you should get a pmem device:
+
+```
+[rootfs ]# dmesg|grep pmem
+[ 9.013750] nd_pmem namespace0.0: unable to guarantee persistence of writes
+[ 9.172887] pmem0: detected capacity change from 0 to 805306368
+```
+
+If you get a confusing error in dmesg, try smaller memmap sizes.
+Some people wrote that steps of 64M or 256M should work.
+I had success with 768M, barely enough for the Arch ISO, and 4G, enough for
+bigger live environments including full graphical UIs such as Gnome or KDE.
+
+See also https://github.com/pmem/ndctl/issues/76#issuecomment-440849415.
+
+## Rebuild the ISO
+
+Generally, follow the wiki. Mind the importance of the label of the ISO.
+We need to pass it when we kexec. The Arch ISO itself assumes booting
+through its own bootloader, and the hooks in its initramfs pick it up.
+In other words: Whatever label you choose, use it also in `webboot.go`.
+
+See the file `arch/boot/syslinux/archiso_sys.cfg` from the Arch ISO to see what
+the initramfs expects from the bootloader.
diff --git a/webboot/docs/remaster-debian-iso.md b/webboot/docs/remaster-debian-iso.md
new file mode 100644
index 000000000..7bb552dc0
--- /dev/null
+++ b/webboot/docs/remaster-debian-iso.md
@@ -0,0 +1,56 @@
+# Remastering Debian live ISO
+
+## Figure out kernel command line
+`less /mnt/iso/boot/grub/grub.cfg`
+
+```
+...
+ linux /live/vmlinuz-4.19.0-9-amd64 boot=live components splash quiet "${loopback}"
+ initrd /live/initrd.img-4.19.0-9-amd64
+...
+```
+
+## Tailor initrd for webboot
+
+### Extract initrd
+```sh
+zcat /mnt/iso/live/initrd.img-4.19.0-9-amd64 | sudo cpio -idmv
+```
+
+### Extract and copy nvdimm modules from squashfs
+```sh
+unsquashfs -f /mnt/iso/live/filesystem.squashfs \
+ -e usr/lib/modules/4.19.0-9-amd64/kernel/drivers/nvdimm
+mv squashfs-root/usr/lib/modules/4.19.0-9-amd64/kernel/drivers/nvdimm \
+ lib/modules/4.19.0-9-amd64/kernel/drivers
+rm -r squashfs-root
+```
+
+### Add insmod statements to /init - little hackaround :)
+```sh
+insmod /lib/modules/4.19.0-9-amd64/kernel/drivers/nvdimm/libnvdimm.ko
+insmod /lib/modules/4.19.0-9-amd64/kernel/drivers/nvdimm/nd_btt.ko
+insmod /lib/modules/4.19.0-9-amd64/kernel/drivers/nvdimm/nd_pmem.ko
+insmod /lib/modules/4.19.0-9-amd64/kernel/drivers/nvdimm/nd_e820.ko
+insmod /lib/modules/4.19.0-9-amd64/kernel/drivers/nvdimm/nd_blk.ko
+```
+
+### Rebuild initrd
+```sh
+find . | cpio --create --format='newc' | gzip > initrd
+```
+
+## Build new ISO
+
+```sh
+cp -a /mnt/iso/ debian-remastered/
+cp initrd.img-4.19.0-9-amd64 debian-remastered/live/initrd.img-4.19.0-9-amd64
+cd debian-remastered
+genisoimage \
+ -l -r -J -V "DEBIAN_WEBBOOT" \
+ -b isolinux/isolinux.bin \
+ -no-emul-boot -boot-load-size 4 -boot-info-table \
+ -c isolinux/boot.cat \
+ -o ../debian.iso \
+ ./
+```
diff --git a/webboot/docs/remaster-manjaro-iso.md b/webboot/docs/remaster-manjaro-iso.md
new file mode 100644
index 000000000..73c3e5454
--- /dev/null
+++ b/webboot/docs/remaster-manjaro-iso.md
@@ -0,0 +1,170 @@
+# Remastering a Manjaro ISO
+
+From the [Manjaro wiki](https://wiki.manjaro.org/index.php?title=Manjaro-tools#buildiso)
+it is unclear how the initramfs is compiled.
+
+## Inspecting the ISO
+
+The structure differs from the Arch ISO. There are multiple
+squashfs files.
+
+```sh
+$ ls -l /mnt/iso/manjaro/x86_64/
+total 2.6G
+-r--r--r-- 1 root root 48 May 11 08:56 desktopfs.md5
+-r--r--r-- 1 root root 1.3G May 11 08:56 desktopfs.sfs
+-r--r--r-- 1 root root 45 May 11 09:40 livefs.md5
+-r--r--r-- 1 root root 61M May 11 09:40 livefs.sfs
+-r--r--r-- 1 root root 45 May 11 08:54 mhwdfs.md5
+-r--r--r-- 1 root root 618M May 11 08:54 mhwdfs.sfs
+-r--r--r-- 1 root root 45 May 11 08:58 rootfs.md5
+-r--r--r-- 1 root root 585M May 11 08:58 rootfs.sfs
+```
+
+Extracting `rootfs.sfs` and following the approach for Arch errors:
+
+```sh
+$ mkinitcpio -k $(ls /lib/modules/) -p linux56
+==> Building image from preset: /etc/mkinitcpio.d/linux56.preset: 'default'
+ -> -k /boot/vmlinuz-5.6-x86_64 -c /etc/mkinitcpio.conf -g /boot/initramfs-5.6-x86_64.img
+==> Starting build: 5.6.11-1-MANJARO
+ -> Running build hook: [base]
+ -> Running build hook: [udev]
+ -> Running build hook: [memdisk]
+==> ERROR: file not found: `memdiskfind'
+==> ERROR: Hook 'archiso_shutdown' cannot be found
+==> ERROR: Hook 'archiso' cannot be found
+==> ERROR: Hook 'archiso_loop_mnt' cannot be found
+==> ERROR: Hook 'archiso_pxe_common' cannot be found
+==> ERROR: Hook 'archiso_pxe_nbd' cannot be found
+==> ERROR: Hook 'archiso_pxe_http' cannot be found
+==> ERROR: Hook 'archiso_pxe_nfs' cannot be found
+==> ERROR: Hook 'archiso_kms' cannot be found
+ -> Running build hook: [block]
+ -> Running build hook: [filesystems]
+ -> Running build hook: [keyboard]
+ -> Running build hook: [nvdimm]
+==> Generating module dependencies
+==> Creating xz-compressed initcpio image: /boot/initramfs-5.6-x86_64.img
+==> WARNING: errors were encountered during the build. The image may not be complete.
+```
+
+The hooks used for `archiso` are apparently not available.
+
+The `mkinitcpio.conf` from `desktopfs.sfs` has `systemd` and `ostree`:
+
+```
+HOOKS="base systemd ostree autodetect modconf block filesystems keyboard fsck"
+```
+
+Which leads to no success either:
+
+```sh
+$ mkinitcpio -k 5.6.11-1-MANJARO -g /boot/initramfs.img
+==> Starting build: 5.6.11-1-MANJARO
+ -> Running build hook: [base]
+ -> Running build hook: [systemd]
+==> ERROR: Hook 'ostree' cannot be found
+ -> Running build hook: [autodetect]
+==> ERROR: failed to detect root filesystem
+ -> Running build hook: [modconf]
+ -> Running build hook: [block]
+ -> Running build hook: [filesystems]
+ -> Running build hook: [keyboard]
+ -> Running build hook: [fsck]
+ -> Running build hook: [nvdimm]
+==> Generating module dependencies
+==> Creating xz-compressed initcpio image: /boot/initramfs.img
+==> WARNING: errors were encountered during the build. The image may not be complete.
+```
+
+## Booting the ISO for more insight
+
+```sh
+$ qemu-system-x86_64 -cdrom manjaro-gnome-20.0.1-200511-linux56.iso
+```
+
+### Kernel arguments
+
+A look at `cat /proc/cmdline` yields the crucial bits to pass to the
+kernel so that the initramfs can pick it up to find the ISO on devices.
+The naming is different from Arch / SystemRescueCd: `misolabel` and
+`misobasedir`.
+
+```
+misobasedir=manjaro misolabel=MANJARO_GNOME_2001
+```
+
+## Rebuilding the initramfs manually
+
+The steps are simple, just require some knowledge:
+
+- extract the initramfs
+- copy the modules into it, `unxz` them
+- recreate the initramfs
+
+Luckily, the [Red Hat docs](https://access.redhat.com/solutions/24029)
+explain how to recreate a `cpio` image, boiling down to the following:
+
+```sh
+$ find . | cpio --create --format='newc' > ../new.img
+```
+
+The compressed image needs a special alignment. We have that covered in
+the [u-root README](https://github.com/u-root/u-root#compression):
+
+```sh
+$ xz --check=crc32 -9 --lzma2=dict=1MiB \
+ --stdout /mnt/tmp/new.img \
+ | sudo dd conv=sync bs=512 \
+ of=initramfs-x86_64.img
+```
+
+Trying it out in QEMU though calls for trouble again:
+
+```
+$ qemu-system-x86_64 \
+ -machine q35,accel=kvm -m 1G -append 'memmap=512M!512M' \
+ -kernel manjaro-remastered/boot/vmlinuz-x86_64 \
+ -initrd manjaro-remastered/boot/initramfs-x86_64.img
+```
+
+There is no `/dev/pmem*` device. Uh-oh! And the modules were not loaded
+either - but why? An attempt to `modprobe nd_pmem` tells that the
+module cannot be found. But the file is present. A quick research says
+that the module lookup needs some help. The `depmod` utility will
+receate the `modules.dep` file in `/usr/lib/$KERNEL/`.
+Solution: simply add `depmod` to the top of `/init`.
+
+Recreating the initramfs now leads to an environment with the desired
+pmem device present.
+
+## Recreating the ISO
+
+First, copy the new initramfs to a copy is the ISO in some directory.
+
+Long story short: It's not `syslinux` like Arch does it, life is short.
+The resulting command is:
+
+```sh
+$ genisoimage \
+ -l -r -J -V "MANJARO_WEBBOOT" \
+ -b efi/boot/bootx64.efi \
+ -no-emul-boot -boot-load-size 4 -boot-info-table \
+ -c boot.catalog \
+ -o ../manjaro.iso \
+ ./
+```
+
+This loses the ability to boot via QEMU directly, which is a shortcut
+here for the proof of concept. For a full solution, the modules would
+just be added to the initramfs by the upstream distribution anyway.
+
+Now `webboot` successfully boots Manjaro with a full Gnome dekstop. :)
+
+## TODOs
+
+After some more search, here are the hooks used to create the Manjaro initramfs:
+https://gitlab.manjaro.org/tools/development-tools/manjaro-tools/-/tree/master/initcpio/hooks
+
+File a PR there to include another hook for adding the nvdimm/pmem modules.
diff --git a/webboot/firsttime.sh b/webboot/firsttime.sh
new file mode 100755
index 000000000..af2f0b431
--- /dev/null
+++ b/webboot/firsttime.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -e
+
+sudo apt-get install build-essential kexec-tools libelf-dev libnl-3-dev libnl-genl-3-dev libssl-dev qemu-system-x86 wireless-tools wpasupplicant
+
+go get -u github.com/u-root/u-root
+go get -u github.com/u-root/NiChrome/...
diff --git a/webboot/integration/basic_test.go b/webboot/integration/basic_test.go
new file mode 100644
index 000000000..3b47d9fa6
--- /dev/null
+++ b/webboot/integration/basic_test.go
@@ -0,0 +1,86 @@
+// Copyright 2018 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package integration
+
+import (
+ "fmt"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/u-root/u-root/pkg/qemu"
+ "github.com/u-root/u-root/pkg/uroot"
+ "github.com/u-root/u-root/pkg/vmtest"
+)
+
+var expectString = map[string]string{
+ "Arch": "TODO_PLEASE_SET_EXPECT_STRING",
+ "CentOS 7": "TODO_PLEASE_SET_EXPECT_STRING",
+ "CentOS 8": "TODO_PLEASE_SET_EXPECT_STRING",
+ "Debian": "TODO_PLEASE_SET_EXPECT_STRING",
+ "Fedora": "TODO_PLEASE_SET_EXPECT_STRING",
+ "Kali": "TODO_PLEASE_SET_EXPECT_STRING",
+ "Linux Mint": "TODO_PLEASE_SET_EXPECT_STRING",
+ "Manjaro": "TODO_PLEASE_SET_EXPECT_STRING",
+ "TinyCore": "5.4.3-tinycore64",
+ "Ubuntu": "TODO_PLEASE_SET_EXPECT_STRING",
+}
+
+func TestScript(t *testing.T) {
+ webbootDistro := os.Getenv("WEBBOOT_DISTRO")
+ if _, ok := expectString[webbootDistro]; !ok {
+ if webbootDistro == "" {
+ t.Fatal("WEBBOOT_DISTRO is not set")
+ }
+ t.Fatalf("Unknown distro: %q", webbootDistro)
+ }
+
+ q, cleanup := vmtest.QEMUTest(t, &vmtest.Options{
+ Name: "ShellScript",
+ BuildOpts: uroot.Opts{
+ Commands: uroot.BusyBoxCmds(
+ "github.com/u-root/u-root/cmds/core/init",
+ "github.com/u-root/u-root/cmds/core/ip",
+ "github.com/u-root/u-root/cmds/core/shutdown",
+ "github.com/u-root/u-root/cmds/core/sleep",
+ "github.com/u-root/u-root/cmds/boot/pxeboot",
+ "github.com/u-root/webboot/cmds/webboot",
+ "github.com/u-root/webboot/cmds/cli",
+ "github.com/u-root/u-root/cmds/core/dhclient",
+ "github.com/u-root/u-root/cmds/core/elvish",
+ ),
+ ExtraFiles: []string{
+ "../cmds/cli/ci.json:ci.json",
+ "/sbin/kexec",
+ "/etc/ssl/certs",
+ },
+ },
+ QEMUOpts: qemu.Options{
+ Timeout: 300 * time.Second,
+ Devices: []qemu.Device{
+ qemu.ArbitraryArgs{
+ "-machine", "q35",
+ "-device", "rtl8139,netdev=u1",
+ "-netdev", "user,id=u1",
+ "-m", "4G",
+ },
+ },
+ KernelArgs: "UROOT_NOHWRNG=1",
+ },
+ TestCmds: []string{
+ "dhclient -ipv6=f -v eth0",
+ // The webbootDistro may contain spaces.
+ fmt.Sprintf("cli -distroName=%q", webbootDistro),
+ "shutdown -h",
+ },
+ })
+ defer cleanup()
+
+ if err := q.Expect(expectString[webbootDistro]); err != nil {
+ t.Fatalf("expected %q, got error: %v", expectString[webbootDistro], err)
+ }
+}
diff --git a/webboot/makeusb.sh b/webboot/makeusb.sh
new file mode 100644
index 000000000..1ba30e18b
--- /dev/null
+++ b/webboot/makeusb.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -e
+go run .
+mkdir -p /mnt/usb
+sudo mount /dev/$1 /mnt/usb
+gzip -f /tmp/initramfs.linux_amd64.cpio
+sudo cp /tmp/initramfs.linux_amd64.cpio.gz /mnt/usb/boot/webboot.cpio.gz
+sudo umount /mnt/usb
+
diff --git a/webboot/nightly.sh b/webboot/nightly.sh
new file mode 100755
index 000000000..5ad07f354
--- /dev/null
+++ b/webboot/nightly.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+git clone --depth 1 -b v5.6.14 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git linux
+git clone git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/linux-firmware.git
+cp config-5.6.14 linux/.config
+(cd linux && make bzImage)
diff --git a/webboot/pkg/bootiso/bootiso.go b/webboot/pkg/bootiso/bootiso.go
new file mode 100644
index 000000000..70a48cbe1
--- /dev/null
+++ b/webboot/pkg/bootiso/bootiso.go
@@ -0,0 +1,421 @@
+package bootiso
+
+import (
+ "context"
+ "crypto/md5"
+ "crypto/sha1"
+ "crypto/sha256"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "hash"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path"
+ "runtime/debug"
+ "strings"
+
+ "github.com/u-root/u-root/pkg/boot"
+ "github.com/u-root/u-root/pkg/boot/grub"
+ "github.com/u-root/u-root/pkg/boot/kexec"
+ "github.com/u-root/u-root/pkg/boot/syslinux"
+ "github.com/u-root/u-root/pkg/boot/util"
+ "github.com/u-root/u-root/pkg/mount"
+ "github.com/u-root/u-root/pkg/mount/block"
+ "github.com/u-root/u-root/pkg/mount/loop"
+ "github.com/u-root/u-root/pkg/uio"
+ "golang.org/x/sys/unix"
+)
+
+type Config struct {
+ Label string
+ KernelPath string
+ InitrdPath string
+ Cmdline string
+}
+
+// ParseConfigFromISO mounts the iso file, attempts to parse the config file,
+// and returns a list of bootable boot.OSImage objects representing the parsed configs
+func ParseConfigFromISO(isoPath string, configType string) ([]boot.OSImage, error) {
+ tmp, err := ioutil.TempDir("", "mnt-")
+ if err != nil {
+ return nil, fmt.Errorf("Error creating mount dir: %v", err)
+ }
+ defer os.RemoveAll(tmp)
+
+ loopdev, err := loop.New(isoPath, "iso9660", "")
+ if err != nil {
+ return nil, fmt.Errorf("Error creating loop device: %v", err)
+ }
+
+ mp, err := loopdev.Mount(tmp, unix.MS_RDONLY|unix.MS_NOATIME)
+ if err != nil {
+ return nil, fmt.Errorf("Error mounting loop device: %v", err)
+ }
+ defer mp.Unmount(0)
+
+ images, err := parseConfigFile(tmp, configType)
+ if err != nil {
+ return nil, fmt.Errorf("Error parsing config: %v", err)
+ }
+
+ return images, nil
+}
+
+// LoadCustomConfigs is an alternative to ParseConfigFromISO that allows us
+// to define the boot parameters ourselves (in a list of Config objects)
+// instead of parsing them from a config file
+func LoadCustomConfigs(isoPath string, configs []Config) ([]boot.OSImage, error) {
+ tmpDir, err := ioutil.TempDir("", "mnt-")
+ if err != nil {
+ return nil, fmt.Errorf("Error on ioutil.TempDir; in %s, and got %v", debug.Stack(), err)
+ }
+
+ loopdev, err := loop.New(isoPath, "iso9660", "")
+ if err != nil {
+ return nil, fmt.Errorf("Error on loop.New; in %s, and got %v", debug.Stack(), err)
+ }
+
+ mp, err := loopdev.Mount(tmpDir, unix.MS_RDONLY|unix.MS_NOATIME)
+ if err != nil {
+ return nil, fmt.Errorf("Error on loopdev.Mount; in %s, and got %v", debug.Stack(), err)
+ }
+
+ var images []boot.OSImage
+ var files []*os.File
+ copied := make(map[string]*os.File)
+
+ defer func() {
+ for _, f := range files {
+ if err = f.Close(); err != nil {
+ log.Print(err)
+ }
+ }
+
+ if err = mp.Unmount(unix.MNT_FORCE); err != nil {
+ log.Fatal(err)
+ }
+
+ // Use Remove rather than RemoveAll to avoid
+ // removal if the directory is not empty
+ if err = os.Remove(tmpDir); err != nil {
+ log.Fatal(err)
+ }
+ }()
+
+ for _, c := range configs {
+ var tmpKernel, tmpInitrd *os.File
+
+ // Copy kernel to temp if we haven't already
+ if _, ok := copied[c.KernelPath]; !ok {
+ kernel, err := os.Open(path.Join(tmpDir, c.KernelPath))
+ if err != nil {
+ return nil, fmt.Errorf("Error on os.Open; in %s, and got %v", debug.Stack(), err)
+ }
+ files = append(files, kernel)
+
+ // Temp files are not added to the files list
+ // since they need to stay open for later reading
+ tmpKernel, err = ioutil.TempFile("", "kernel-")
+ if err != nil {
+ return nil, fmt.Errorf("Error on ioutil.TempFile; in %s, and got %v", debug.Stack(), err)
+ }
+
+ if _, err = io.Copy(tmpKernel, kernel); err != nil {
+ return nil, fmt.Errorf("Error on io.Copy; in %s, and got %v", debug.Stack(), err)
+ }
+
+ if _, err = tmpKernel.Seek(0, 0); err != nil {
+ return nil, fmt.Errorf("Error on tmpKernel.Seek; in %s, and got %v", debug.Stack(), err)
+ }
+
+ copied[c.KernelPath] = tmpKernel
+ } else {
+ tmpKernel = copied[c.KernelPath]
+ }
+
+ // Copy initrd to temp if we haven't already
+ if _, ok := copied[c.InitrdPath]; !ok {
+ initrd, err := os.Open(path.Join(tmpDir, c.InitrdPath))
+ if err != nil {
+ return nil, fmt.Errorf("Error on os.Open; in %s, and got %v", debug.Stack(), err)
+ }
+ files = append(files, initrd)
+
+ tmpInitrd, err = ioutil.TempFile("", "initrd-")
+ if err != nil {
+ return nil, fmt.Errorf("Error on ioutil.TempFile; in %s, and got %v", debug.Stack(), err)
+ }
+
+ if _, err = io.Copy(tmpInitrd, initrd); err != nil {
+ return nil, fmt.Errorf("Error on io.Copy; in %s, and got %v", debug.Stack(), err)
+ }
+
+ if _, err = tmpInitrd.Seek(0, 0); err != nil {
+ return nil, fmt.Errorf("Error on tmpInitrd.Seek; in %s, and got %v", debug.Stack(), err)
+ }
+
+ copied[c.InitrdPath] = tmpInitrd
+ } else {
+ tmpInitrd = copied[c.InitrdPath]
+ }
+
+ images = append(images, &boot.LinuxImage{
+ Name: c.Label,
+ Kernel: tmpKernel,
+ Initrd: tmpInitrd,
+ Cmdline: c.Cmdline,
+ })
+ }
+
+ return images, nil
+}
+
+// BootFromPmem copies the ISO to pmem0 and boots
+// given the syslinux configuration with the provided label
+func BootFromPmem(isoPath string, configLabel string, configType string) error {
+ pmem, err := os.OpenFile("/dev/pmem0", os.O_APPEND|os.O_WRONLY, 0600)
+ if err != nil {
+ return fmt.Errorf("Error opening persistent memory device: %v", err)
+ }
+
+ iso, err := os.Open(isoPath)
+ if err != nil {
+ return fmt.Errorf("Error opening ISO: %v", err)
+ }
+ defer iso.Close()
+
+ if _, err := io.Copy(pmem, iso); err != nil {
+ return fmt.Errorf("Error copying from ISO to pmem: %v", err)
+ }
+ if err = pmem.Close(); err != nil {
+ return fmt.Errorf("Error closing persistent memory device: %v", err)
+ }
+
+ tmp, err := ioutil.TempDir("", "mnt")
+ if err != nil {
+ return fmt.Errorf("Error creating temp directory: %v", err)
+ }
+ defer os.RemoveAll(tmp)
+
+ if _, err := mount.Mount("/dev/pmem0", tmp, "iso9660", "", unix.MS_RDONLY|unix.MS_NOATIME); err != nil {
+ return fmt.Errorf("Error mounting pmem0 to temp directory: %v", err)
+ }
+
+ configOpts, err := parseConfigFile(tmp, configType)
+ if err != nil {
+ return fmt.Errorf("Error retrieving syslinux config options: %v", err)
+ }
+
+ osImage := findConfigOptionByLabel(configOpts, configLabel)
+ if osImage == nil {
+ return fmt.Errorf("Config option with the requested label does not exist")
+ }
+
+ // Need to convert from boot.OSImage to boot.LinuxImage to edit the Cmdline
+ linuxImage, ok := osImage.(*boot.LinuxImage)
+ if !ok {
+ return fmt.Errorf("Error converting from boot.OSImage to boot.LinuxImage")
+ }
+
+ localCmd, err := ioutil.ReadFile("/proc/cmdline")
+ if err != nil {
+ return fmt.Errorf("Error accessing /proc/cmdline")
+ }
+ cmdline := strings.TrimSuffix(string(localCmd), "\n") + " " + linuxImage.Cmdline
+ linuxImage.Cmdline = cmdline
+
+ if err := linuxImage.Load(true); err != nil {
+ return err
+ }
+ if err := kexec.Reboot(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// next two functions hoisted from u-root kexec. We will remove
+// them when the u-root kexec becomes capable of using the 32-bit
+// entry point. 32-bit entry is essential to working on chromebooks.
+
+func copyToFile(r io.Reader) (*os.File, error) {
+ f, err := ioutil.TempFile("", "webboot")
+ if err != nil {
+ return nil, fmt.Errorf("Error on ioutil.TempFile; in %s, and got %v", debug.Stack(), err)
+ }
+ defer f.Close()
+ if _, err := io.Copy(f, r); err != nil {
+ return nil, fmt.Errorf("Error on io.Copy; in %s, and got %v", debug.Stack(), err)
+ }
+ if err := f.Sync(); err != nil {
+ return nil, fmt.Errorf("Error on f.Sync; in %s, and got %v", debug.Stack(), err)
+ }
+
+ readOnlyF, err := os.Open(f.Name())
+ if err != nil {
+ return nil, fmt.Errorf("Error on os.Open; in %s, and got %v", debug.Stack(), err)
+ }
+ return readOnlyF, nil
+}
+
+// kexecCmd boots via the classic kexec command, if it exists
+func cmdKexecLoad(li *boot.LinuxImage, verbose bool) error {
+ if li.Kernel == nil {
+ return errors.New("LinuxImage.Kernel must be non-nil")
+ }
+
+ kernel, initrd := uio.Reader(util.TryGzipFilter(li.Kernel)), uio.Reader(li.Initrd)
+ if verbose {
+ // In verbose mode, print a dot every 5MiB. It is not pretty,
+ // but it at least proves the files are still downloading.
+ progress := func(r io.Reader, dot string) io.Reader {
+ return &uio.ProgressReadCloser{
+ RC: ioutil.NopCloser(r),
+ Symbol: dot,
+ Interval: 5 * 1024 * 1024,
+ W: os.Stdout,
+ }
+ }
+ kernel = progress(kernel, "K")
+ initrd = progress(initrd, "I")
+ }
+
+ // It seams inefficient to always copy, in particular when the reader
+ // is an io.File but that's not sufficient, os.File could be a socket,
+ // a pipe or some other strange thing. Also kexec_file_load will fail
+ // (similar to execve) if anything as the file opened for writing.
+ // That's unfortunately something we can't guarantee here - unless we
+ // make a copy of the file and dump it somewhere.
+ k, err := copyToFile(kernel)
+ if err != nil {
+ return err
+ }
+ defer k.Close()
+ kargs := []string{"-d", "-l", "--entry-32bit", "--command-line=" + li.Cmdline}
+ var i *os.File
+ if li.Initrd != nil {
+ i, err = copyToFile(initrd)
+ if err != nil {
+ return err
+ }
+ defer i.Close()
+ kargs = append(kargs, "--initrd="+i.Name())
+ }
+
+ log.Printf("Kernel: %s", k.Name())
+ kargs = append(kargs, k.Name())
+ if i != nil {
+ log.Printf("Initrd: %s", i.Name())
+ }
+ log.Printf("Command line: %s", li.Cmdline)
+ log.Printf("Kexec args: %q", kargs)
+
+ out, err := exec.Command("/sbin/kexec", kargs...).CombinedOutput()
+ if err != nil {
+ err = fmt.Errorf("Load failed; output %q, err %v", out, err)
+ }
+ return err
+}
+
+func cmdKexecReboot(verbose bool) error {
+ o, err := exec.Command("/sbin/kexec", "-d", "-e").CombinedOutput()
+ if err != nil {
+ err = fmt.Errorf("Exec failed; output %q, err %v", o, err)
+ }
+ return err
+}
+
+func BootCachedISO(osImage boot.OSImage, kernelParams string) error {
+ // Need to convert from boot.OSImage to boot.LinuxImage to edit the Cmdline
+ linuxImage, ok := osImage.(*boot.LinuxImage)
+ if !ok {
+ return fmt.Errorf("Error converting from boot.OSImage to boot.LinuxImage")
+ }
+
+ linuxImage.Cmdline = linuxImage.Cmdline + " " + kernelParams
+
+ // We prefer to use the kexec command for now, if possible, as it can
+ // use the 32-bit entry point.
+ if _, err := os.Stat("/sbin/kexec"); err != nil {
+ if err := cmdKexecLoad(linuxImage, true); err != nil {
+ return err
+ }
+ if err := cmdKexecReboot(true); err != nil {
+ return err
+ }
+ }
+ if err := linuxImage.Load(true); err != nil {
+ return err
+ }
+
+ if err := kexec.Reboot(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// VerifyChecksum takes a path to the ISO and its checksum
+// and compares the calculated checksum on the ISO against the checksum.
+// It returns true if the checksum was correct, false if the checksum
+// was incorrect, the calculated checksum, and an error.
+func VerifyChecksum(isoPath, checksum, checksumType string) (bool, string, error) {
+ iso, err := os.Open(isoPath)
+ if err != nil {
+ return false, "", err
+ }
+ defer iso.Close()
+
+ var hash hash.Hash
+ switch checksumType {
+ case "md5":
+ hash = md5.New()
+ case "sha1":
+ hash = sha1.New()
+ case "sha256":
+ hash = sha256.New()
+ default:
+ return false, "", fmt.Errorf("Unknown checksum type.")
+ }
+
+ if _, err := io.Copy(hash, iso); err != nil {
+ return false, "", err
+ }
+ calcChecksum := hex.EncodeToString(hash.Sum(nil))
+
+ return calcChecksum == checksum, calcChecksum, nil
+}
+
+func findConfigOptionByLabel(configOptions []boot.OSImage, configLabel string) boot.OSImage {
+ for _, config := range configOptions {
+ if config.Label() == configLabel {
+ return config
+ }
+ }
+ return nil
+}
+
+func parseConfigFile(mountDir string, configType string) ([]boot.OSImage, error) {
+ devs, err := block.GetBlockDevices()
+ if err != nil {
+ return nil, fmt.Errorf("Error on block.GetBlockDevices; in %s, and got %v", debug.Stack(), err)
+ }
+ mp := &mount.Pool{}
+
+ if configType == "syslinux" {
+ return syslinux.ParseLocalConfig(context.Background(), mountDir)
+ } else if configType == "grub" {
+ return grub.ParseLocalConfig(context.Background(), mountDir, devs, mp)
+ }
+
+ // If no config type was specified, try both grub and syslinux
+ configOpts, err := syslinux.ParseLocalConfig(context.Background(), mountDir)
+ if err == nil && len(configOpts) != 0 {
+ return configOpts, err
+ }
+ return grub.ParseLocalConfig(context.Background(), mountDir, devs, mp)
+}
diff --git a/webboot/pkg/bootiso/bootiso_test.go b/webboot/pkg/bootiso/bootiso_test.go
new file mode 100644
index 000000000..93c48a326
--- /dev/null
+++ b/webboot/pkg/bootiso/bootiso_test.go
@@ -0,0 +1,122 @@
+package bootiso
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "testing"
+)
+
+var isoPath string = "testdata/TinyCorePure64.iso"
+
+func TestParseConfigFromISO(t *testing.T) {
+ configOpts, err := ParseConfigFromISO(isoPath, "syslinux")
+ if err != nil {
+ t.Error(err)
+ }
+
+ expectedLabels := [4]string{
+ "Boot TinyCorePure64",
+ "Boot TinyCorePure64 (on slow devices, waitusb=5)",
+ "Boot Core (command line only).",
+ "Boot Core (command line only on slow devices, waitusb=5)",
+ }
+
+ for i, config := range configOpts {
+ if config.Label() != expectedLabels[i] {
+ t.Error("Invalid configuration option found.")
+ }
+ }
+}
+
+func TestChecksum(t *testing.T) {
+ for _, test := range []struct {
+ name string
+ checksum string
+ checksumType string
+ valid bool
+ }{
+ {
+ name: "valid_md5",
+ checksum: "10a79ba7558598574cd396e7b1b057b7",
+ checksumType: "md5",
+ valid: true,
+ },
+ {
+ name: "valid_sha256",
+ checksum: "01ce6b5f4e4f7e98eddc343fc14f1436fb1b0452e6b9f7e07461b6a089a909c1",
+ checksumType: "sha256",
+ valid: true,
+ },
+ {
+ name: "invalid_md5",
+ checksum: "99979ba7558598574cd396e7b1b057b7",
+ checksumType: "md5",
+ valid: false,
+ },
+ } {
+ t.Run(test.name, func(t *testing.T) {
+ valid, calcChecksum, err := VerifyChecksum(isoPath, test.checksum, test.checksumType)
+ if err != nil {
+ t.Error(err)
+ } else if valid != test.valid {
+ t.Errorf("Checksum validation was expected to result in %t.\n", test.valid)
+ } else if len(calcChecksum) == 0 {
+ t.Errorf("Should have returned a checksum")
+ }
+ })
+ }
+}
+
+func TestCustomConfigs(t *testing.T) {
+ var configs []Config
+ for i := 0; i < 5; i++ {
+ configs = append(configs, Config{
+ Label: "Custom Config " + fmt.Sprint(i),
+ KernelPath: "/boot/vmlinuz64",
+ InitrdPath: "/boot/corepure64.gz",
+ Cmdline: "loglevel=3 vga=791",
+ })
+ }
+
+ for _, test := range []struct {
+ name string
+ configs []Config
+ }{
+ {
+ name: "empty_list",
+ configs: []Config{},
+ },
+ {
+ name: "single_config",
+ configs: configs[:1],
+ },
+ {
+ name: "multiple_configs",
+ configs: configs,
+ },
+ } {
+ t.Run(test.name, func(t *testing.T) {
+ images, err := LoadCustomConfigs(isoPath, test.configs)
+ if err != nil {
+ t.Error(err)
+ } else if len(test.configs) != len(images) {
+ t.Errorf("Test contained %d configs, but only received %d images.", len(test.configs), len(images))
+ }
+
+ for index, image := range images {
+ if test.configs[index].Label != image.Label() {
+ t.Errorf("Expected label %q but received %q.", test.configs[index].Label, image.Label())
+ }
+ }
+ })
+ }
+}
+
+func TestMain(m *testing.M) {
+ if _, err := os.Stat(isoPath); err != nil {
+ log.Fatal("ISO file was not found in the testdata directory.")
+ }
+
+ os.Exit(m.Run())
+}
diff --git a/webboot/pkg/bootiso/testdata/TinyCorePure64.md5.txt b/webboot/pkg/bootiso/testdata/TinyCorePure64.md5.txt
new file mode 100644
index 000000000..48f83b35e
--- /dev/null
+++ b/webboot/pkg/bootiso/testdata/TinyCorePure64.md5.txt
@@ -0,0 +1 @@
+10a79ba7558598574cd396e7b1b057b7 TinyCorePure64.iso
diff --git a/webboot/pkg/bootiso/testdata/TinyCorePure64.sha256.txt b/webboot/pkg/bootiso/testdata/TinyCorePure64.sha256.txt
new file mode 100644
index 000000000..8bc1c98c3
--- /dev/null
+++ b/webboot/pkg/bootiso/testdata/TinyCorePure64.sha256.txt
@@ -0,0 +1 @@
+01ce6b5f4e4f7e98eddc343fc14f1436fb1b0452e6b9f7e07461b6a089a909c1 TinyCorePure64.iso
diff --git a/webboot/pkg/dhclient/dhclient.go b/webboot/pkg/dhclient/dhclient.go
new file mode 100644
index 000000000..9efbfea72
--- /dev/null
+++ b/webboot/pkg/dhclient/dhclient.go
@@ -0,0 +1,83 @@
+// Copyright 2019 the u-root Authors. All rights reserved
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dhclient
+
+import (
+ "context"
+ "fmt"
+ "regexp"
+ "time"
+
+ "github.com/u-root/u-root/pkg/dhclient"
+ "github.com/vishvananda/netlink"
+)
+
+// Request sets up the dhcp configurations for all of the ifNames.
+func Request(ifName string, timeout int, retry int, verbose bool, ipv4 bool, ipv6 bool, cl chan string) {
+ ifRE := regexp.MustCompilePOSIX(ifName)
+
+ ifnames, err := netlink.LinkList()
+ if err != nil {
+ cl <- fmt.Sprintf("Can't get list of link names: %v", err)
+ close(cl)
+ return
+ }
+
+ var filteredIfs []netlink.Link
+ for _, iface := range ifnames {
+ if ifRE.MatchString(iface.Attrs().Name) {
+ filteredIfs = append(filteredIfs, iface)
+ }
+ }
+
+ if len(filteredIfs) == 0 {
+ cl <- fmt.Sprintf("No interfaces match %s", ifName)
+ close(cl)
+ return
+ }
+
+ go configureAll(filteredIfs, cl, timeout, retry, verbose, ipv4, ipv6)
+
+}
+
+func configureAll(ifs []netlink.Link, cl chan<- string, timeout int, retry int, verbose bool, ipv4 bool, ipv6 bool) {
+ packetTimeout := time.Duration(timeout) * time.Second
+
+ ctx, cancel := context.WithTimeout(context.Background(), packetTimeout*time.Duration(1< b {
+ return a
+ }
+ return b
+}
+
+func countNewlines(str string) int {
+ count := 0
+ for _, s := range str {
+ if s == '\n' {
+ count++
+ }
+ }
+ return count
+}
+
+func Init() error {
+ return ui.Init()
+}
+
+func Close() {
+ ui.Close()
+}
+
+var BackRequest = errors.New("User requested to return to a previous menu.")
+var ExitRequest = errors.New("User requested to exit the program.")
+
+// AlwaysValid is a special isValid function that check nothing
+func AlwaysValid(input string) (string, string, bool) {
+ return input, "", true
+}
+
+// newParagraph returns a widgets.Paragraph struct with given initial text.
+func newParagraph(initText string, border bool, location int, wid int, ht int) *widgets.Paragraph {
+ p := widgets.NewParagraph()
+ p.Text = initText
+ p.Border = border
+ p.SetRect(0, location, wid, location+ht)
+ p.TextStyle.Fg = ui.ColorWhite
+ return p
+}
+
+// readKey reads a key from input stream.
+func readKey(uiEvents <-chan ui.Event) string {
+ for {
+ e := <-uiEvents
+ if e.Type == ui.KeyboardEvent || e.Type == ui.MouseEvent {
+ return e.ID
+ }
+ }
+}
+
+// processInput presents an input box to user and returns the user's input.
+// processInput will check validation of input using isValid function.
+func processInput(introwords string, location int, wid int, ht int, isValid validCheck, uiEvents <-chan ui.Event) (string, string, error) {
+ intro := newParagraph(introwords, false, location, len(introwords)+4, 3)
+ location += 2
+ input := newParagraph("", true, location, wid, ht+2)
+ location += ht + 2
+ warning := newParagraph(" to go back, to exit", false, location, wid, 15)
+
+ ui.Render(intro)
+ ui.Render(input)
+ ui.Render(warning)
+
+ // The input box is wid characters wide
+ // - 2 chars are reserved for the left and right borders
+ // - 1 char is left empty at the end of input to visually
+ // signify that the text box is still accepting input
+ // The user might want to input a string longer than wid-3
+ // characters, so we store the full typed input in fullText
+ // and display a substring of the full text to the user
+ var fullText string
+
+ for {
+ k := readKey(uiEvents)
+ switch k {
+ case "":
+ return "", "", ExitRequest
+ case "":
+ return "", "", BackRequest
+ case "":
+ inputString, warningString, ok := isValid(fullText)
+ if ok {
+ return inputString, warning.Text, nil
+ }
+ fullText = ""
+ input.Text = ""
+ warning.Text = warningString
+ ui.Render(input)
+ ui.Render(warning)
+ case "":
+ if len(input.Text) > 0 {
+ fullText = fullText[:len(fullText)-1]
+ start := max(0, len(fullText)-wid+3)
+ input.Text = fullText[start:]
+ ui.Render(input)
+ }
+ case "":
+ fullText += " "
+ start := max(0, len(fullText)-wid+3)
+ input.Text = fullText[start:]
+ ui.Render(input)
+ default:
+ // the termui use a string begin at '<' to represent some special keys
+ // for example the 'F1' key will be parsed to "" string .
+ // we should do nothing when meet these special keys, we only care about alphabets and digits.
+ if k[0:1] != "<" {
+ fullText += k
+ start := max(0, len(fullText)-wid+3)
+ input.Text = fullText[start:]
+ ui.Render(input)
+ }
+ }
+ }
+}
+
+// PromptTextInput opens a new input window with fixed width=100, hight=1.
+func PromptTextInput(introwords string, isValid validCheck, uiEvents <-chan ui.Event, menus chan<- string) (string, error) {
+ menus <- introwords
+ defer ui.Clear()
+ input, _, err := processInput(introwords, 0, 80, 1, isValid, uiEvents)
+ return input, err
+}
+
+// DisplayResult opens a new window and displays a message.
+// each item in the message array will be displayed on a single line.
+func DisplayResult(message []string, uiEvents <-chan ui.Event, menus chan<- string) (string, error) {
+ menus <- message[0]
+
+ defer ui.Clear()
+
+ // if a message is longer then width of the window, split it to shorter lines
+ var wid int = resultWidth
+ text := []string{}
+ for _, m := range message {
+ for len(m) > wid {
+ text = append(text, m[0:wid])
+ m = m[wid:]
+ }
+ text = append(text, m)
+ }
+
+ p := widgets.NewParagraph()
+ p.Border = true
+ p.SetRect(0, 0, resultWidth+2, resultHeight+4)
+ p.TextStyle.Fg = ui.ColorWhite
+
+ msgLength := len(text)
+ first := 0
+ last := min(resultHeight, msgLength)
+
+ controlText := ", to scroll\n\nPress any other key to continue."
+ controls := newParagraph(controlText, false, resultHeight+4, wid+2, 5)
+ ui.Render(controls)
+
+ for {
+ p.Title = fmt.Sprintf("Message---%v/%v", first, msgLength)
+ displayText := strings.Join(text[first:last], "\n")
+
+ // Indicate whether user is at the
+ // end of text for long messages
+ if msgLength > resultHeight {
+ if last < msgLength {
+ displayText += "\n\n(More)"
+ } else if last == msgLength {
+ displayText += "\n\n(End of message)"
+ }
+ }
+
+ p.Text = displayText
+ ui.Render(p)
+
+ k := readKey(uiEvents)
+ switch k {
+ case "", "":
+ first = max(0, first-1)
+ last = min(first+resultHeight, len(text))
+ case "", "":
+ last = min(last+1, len(text))
+ first = max(0, last-resultHeight)
+ case "", "":
+ first = max(0, first-resultHeight)
+ last = min(first+resultHeight, len(text))
+ case "", "":
+ last = min(last+resultHeight, len(text))
+ first = max(0, last-resultHeight)
+ case "":
+ return p.Text, ExitRequest
+ case "":
+ return p.Text, BackRequest
+ default:
+ return p.Text, nil
+ }
+ }
+}
+
+// parsingMenuOption parses the user's operation in the menu page, such as page up, page down, selection. etc
+func parsingMenuOption(labels []string, menu *widgets.List, input *widgets.Paragraph, logBox *widgets.List, warning *widgets.Paragraph, uiEvents <-chan ui.Event, customWarning ...string) (int, error) {
+
+ if len(labels) == 0 {
+ return 0, fmt.Errorf("No Entry in the menu")
+ }
+
+ menuTitle := menu.Title + "---%v/%v"
+
+ // first, last always point to the first and last entry in current menu page
+ first := 0
+ last := min(10, len(labels))
+ listData := labels[first:last]
+ menu.Rows = listData
+ menu.Title = fmt.Sprintf(menuTitle, first, len(labels))
+ ui.Render(menu)
+
+ // keep tracking all input from user
+ for {
+ k := readKey(uiEvents)
+ switch k {
+ case "":
+ return -1, ExitRequest
+ case "":
+ return -1, BackRequest
+ case "":
+ choose := input.Text
+ input.Text = ""
+ ui.Render(input)
+ c, err := strconv.Atoi(choose)
+ // Input is valid if the selected index
+ // is between 0 <= input < len(labels)
+ if err == nil && c >= 0 && c < len(labels) {
+ // if there is not specific warning for this entry, return it
+ // elsewise show the warning and continue
+ if len(customWarning) > c && customWarning[c] != "" {
+ warning.Text = customWarning[c]
+ ui.Render(warning)
+ continue
+ }
+ return c, nil
+ }
+ warning.Text = "Please enter a valid entry number."
+ ui.Render(warning)
+ case "":
+ if len(input.Text) > 0 {
+ input.Text = input.Text[:len(input.Text)-1]
+ ui.Render(input)
+ }
+ case "":
+ first = max(0, first-10)
+ last = min(first+10, len(labels))
+ listData := labels[first:last]
+ menu.Rows = listData
+ menu.Title = fmt.Sprintf(menuTitle, first, len(labels))
+ ui.Render(menu)
+ case "":
+ if first+10 >= len(labels) {
+ continue
+ }
+ first = first + 10
+ last = min(first+10, len(labels))
+ listData := labels[first:last]
+ menu.Rows = listData
+ menu.Title = fmt.Sprintf(menuTitle, first, len(labels))
+ ui.Render(menu)
+ case "":
+ // scroll up in the log box
+ logBox.ScrollHalfPageUp()
+ ui.Render(logBox)
+ case "":
+ // scroll down in the log box
+ logBox.ScrollHalfPageDown()
+ ui.Render(logBox)
+ case "", "":
+ // move one line up
+ first = max(0, first-1)
+ last = min(first+10, len(labels))
+ listData := labels[first:last]
+ menu.Rows = listData
+ menu.Title = fmt.Sprintf(menuTitle, first, len(labels))
+ ui.Render(menu)
+ case "", "":
+ // move one line down
+ last = min(last+1, len(labels))
+ first = max(0, last-10)
+ listData := labels[first:last]
+ menu.Rows = listData
+ menu.Title = fmt.Sprintf(menuTitle, first, len(labels))
+ ui.Render(menu)
+ case "":
+ // first page
+ first = 0
+ last = min(first+10, len(labels))
+ listData := labels[first:last]
+ menu.Rows = listData
+ menu.Title = fmt.Sprintf(menuTitle, first, len(labels))
+ ui.Render(menu)
+ case "":
+ // last page
+ last = len(labels)
+ first = max(0, last-10)
+ listData := labels[first:last]
+ menu.Rows = listData
+ menu.Title = fmt.Sprintf(menuTitle, first, len(labels))
+ ui.Render(menu)
+ case "":
+ input.Text += " "
+ ui.Render(input)
+ default:
+ // the termui use a string begin at '<' to represent some special keys
+ // for example the 'F1' key will be parsed to "" string .
+ // we should do nothing when meet these special keys, we only care about alphabets and digits.
+ if k[0:1] != "<" {
+ input.Text += k
+ ui.Render(input)
+ }
+ }
+ }
+}
+
+// PromptMenuEntry presents all entries into a menu with numbers.
+// user inputs a number to choose from them.
+// customWarning allow self-defined warnings in the menu
+// for example the wifi menu want to show specific warning when user hit a specific entry,
+// because some wifi's type may not be supported.
+func PromptMenuEntry(menuTitle string, introwords string, entries []Entry, uiEvents <-chan ui.Event, menus chan<- string, customWarning ...string) (Entry, error) {
+ menus <- menuTitle
+
+ defer ui.Clear()
+
+ // listData contains all choice's labels
+ listData := []string{}
+ for i, e := range entries {
+ listData = append(listData, fmt.Sprintf("[%d] %s", i, e.Label()))
+ }
+ windowWidth, windowHeight := termbox.Size()
+
+ // location will serve as the y1 coordinate in this function.
+ location := 0
+ menu := widgets.NewList()
+ menu.Title = menuTitle
+ // windowHeight is divided by 5 to make room for the five boxes that will be on the screen.
+ height := windowHeight / 5
+ // menu is the box with the options. It will be at the top of the screen.
+ menu.SetRect(0, location, windowWidth, height)
+ menu.TextStyle.Fg = ui.ColorWhite
+
+ location += height
+ // A variable to help get rid of the gap between "Choose an option:" and its
+ // corresponding box.
+ alternateHeight := 2
+
+ intro := newParagraph(introwords, false, location, windowWidth, height)
+
+ location += alternateHeight
+ input := newParagraph("", true, location, windowWidth, height)
+
+ location += height
+ logBox := widgets.NewList()
+ logBox.Title = "Logs:"
+ logBox.WrapText = false
+ logBox.SetRect(0, location, windowWidth, location+height)
+
+ location += height
+ warning := newParagraph(" to go back, to exit", false, location, windowWidth, height)
+
+ // Write the contents of the log output text file to the log box.
+ var file, err = os.OpenFile("logOutput.txt", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+ scanner := bufio.NewScanner(file)
+ scanner.Split(bufio.ScanLines)
+ for scanner.Scan() {
+ logBox.Rows = append(logBox.Rows, scanner.Text())
+ }
+ if err := scanner.Err(); err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ ui.Render(intro)
+ ui.Render(input)
+ ui.Render(warning)
+ ui.Render(logBox)
+
+ chooseIndex, err := parsingMenuOption(listData, menu, input, logBox, warning, uiEvents, customWarning...)
+ if err != nil {
+ return nil, err
+ }
+
+ return entries[chooseIndex], nil
+}
+
+func PromptConfirmation(message string, uiEvents <-chan ui.Event, menus chan<- string) (bool, error) {
+ defer ui.Clear()
+ menus <- message
+
+ wid := resultWidth
+ text := ""
+ position := 1
+
+ for {
+ // Split message if longer than msg box
+ end := min(len(message), wid)
+ text += message[:end] + "\n"
+ if len(message) > wid {
+ message = message[wid:]
+ } else {
+ break
+ }
+ }
+
+ text += "\n[0] Yes\n[1] No\n"
+ position += countNewlines(text) + 2
+ wid += 2 // 2 borders
+
+ msg := newParagraph(text, true, 0, wid, position)
+ ui.Render(msg)
+
+ selectHint := newParagraph("Choose an option:", false, position+1, wid, 1)
+ ui.Render(selectHint)
+
+ entry := newParagraph("", true, position+2, wid, 3)
+ ui.Render(entry)
+
+ backHint := newParagraph(" to go back, to exit", false, position+6, wid, 1)
+ ui.Render(backHint)
+
+ for {
+ key := readKey(uiEvents)
+ switch key {
+ case "":
+ return false, BackRequest
+ case "":
+ return false, ExitRequest
+ case "