├── .gitignore
├── .rubocop.yml
├── Dockerfile
├── LICENSE
├── README.md
├── compress.rb
├── copy.rb
├── decompress.rb
├── dep.txt
├── fetch.rb
├── fstab.rb
├── image.rb
├── initrd.sh
├── main.rb
├── mount.rb
├── overlay.sh
├── resize.rb
├── size.rb
├── template.sh
└── vendor-resources
├── friendlyelec-r6s
├── mjr
├── r6s
├── r6s-img
├── r6s-mjr
└── root
│ ├── config.sh
│ ├── mjr.sh
│ └── rk-vendor.sh
├── intel-edison
├── etc
│ ├── apt
│ │ └── apt.conf
│ ├── fstab
│ ├── fw_env.config
│ └── hostname
├── root
│ └── config.sh
├── tmp
│ └── resize-helper_0.12_all.deb
└── usr
│ └── bin
│ └── configure_edison
├── mars-a1
├── etc
│ ├── hostname
│ └── resolv.conf
├── home
│ └── ubuntu
│ │ └── Desktop
│ │ └── marspc.desktop
└── usr
│ └── share
│ ├── backgrounds
│ └── mars
│ │ ├── block.jpg
│ │ ├── cosmo.jpg
│ │ ├── hexagon.jpg
│ │ ├── home.jpg
│ │ ├── planet.jpg
│ │ └── wave.jpg
│ └── icons
│ └── mars
│ └── marspc.png
└── visionfive-2
├── root
├── config.sh
└── suse.sh
├── vf2
├── vf2-deb
└── vf2-fd
/.gitignore:
--------------------------------------------------------------------------------
1 | cache/
2 | temp/
3 | rootfs/
4 |
5 | *.ext4
6 | *.ext4*
7 |
8 | *.img
9 | *.img*
10 |
11 | mars*/
12 | edison/
13 | licheerv/
14 | binary/
15 | rk-vendor/
16 | merged/
17 | diff/
18 | work/
19 |
20 | linux/
21 | boot-img/
22 | initrd/
23 | boot/
24 | firmware/
25 | modules/
26 | origin*/
27 |
28 | ub-*/
29 | fd-*/
30 | suse-*/
31 | suse/
32 | gentoo*/
33 | arch/
34 | alpine*/
35 |
36 | fstab
37 | *.scr
38 | *.scr.bak
39 | *.script
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | TargetRubyVersion: 2.6
3 | DefaultFormatter: simple
4 |
5 | Layout/IndentationWidth:
6 | Width: 4
7 |
8 | Layout/LineLength:
9 | Max: 120
10 |
11 | Style/Not:
12 | Enabled: false
13 |
14 | Style/AndOr:
15 | Enabled: false
16 |
17 | Style/IfUnlessModifier:
18 | Enabled: false
19 |
20 | Style/RedundantReturn:
21 | Enabled: false
22 |
23 | Style/StringLiterals:
24 | Enabled: true
25 | EnforcedStyle: double_quotes
26 |
27 | Style/StringLiteralsInInterpolation:
28 | Enabled: true
29 | EnforcedStyle: double_quotes
30 |
31 | Naming/FileName:
32 | Enabled: false
33 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:22.04
2 |
3 | ARG DEBIAN_FRONTEND=noninteractive
4 | ENV TZ=Asia/Shanghai
5 |
6 | RUN set -e \
7 | && sed -i "s/# deb-src/deb-src/g" /etc/apt/sources.list \
8 | && apt-get update
9 |
10 | RUN set -e \
11 | && apt-get install --no-install-recommends -y \
12 | sudo
13 |
14 | RUN useradd -c 'ubuntu' -m -d /home/ubuntu -s /bin/bash ubuntu
15 | RUN set -e \
16 | && sed -i '/\%sudo/ c \%sudo ALL=(ALL) NOPASSWD: ALL' /etc/sudoers \
17 | && usermod -aG sudo ubuntu
18 |
19 | RUN set -e \
20 | && apt-get install --no-install-recommends -y \
21 |
22 | # Project
23 | git-core \
24 | ruby \
25 | qemu-user-static \
26 | libvirt-daemon-system \
27 |
28 | # compress.rb
29 | xz-utils \
30 |
31 | # copy.rb
32 |
33 | # decompress.rb
34 | unzip \
35 | p7zip-full \
36 | zstd \
37 | cpio \
38 |
39 | # fetch.rb
40 | wget \
41 |
42 | # fstab.rb
43 | btrfs-progs \
44 | dosfstools \
45 | exfat-utils \
46 | ntfs-3g \
47 |
48 | #image.rb
49 | u-boot-tools \
50 |
51 | # main.rb
52 |
53 | # mount.rb
54 | fdisk
55 |
56 | # resize.rb
57 |
58 | # size.rb
59 |
60 | USER ubuntu
61 | WORKDIR /home/ubuntu/
62 |
63 | ENTRYPOINT ["/bin/bash"]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rootfs-tools
2 |
3 | > build workflow for rootfs images
4 |
5 | ## Prepare
6 |
7 | ```
8 | sudo apt update
9 | sudo apt install $(cat dep.txt)
10 |
11 | sudo systemctl enable --now libvirtd
12 | ```
13 |
14 | ref: https://wiki.gentoo.org/wiki/RISC-V_Qemu_setup
15 |
16 | ## Run
17 |
18 | ```
19 | sudo ruby main.rb
20 | ```
21 |
22 | But it may be not fit to you, just run `CMD` in the scripts.
23 |
24 | ## More
25 |
26 | ### why qemu?
27 |
28 | `qemu-user-static` for cross-arch chroot supporting,
29 |
30 | like you need `qemu-aarch64` runing an `aarch64` binary on x86_64 host.
31 |
32 | ### Guide
33 |
34 | - Image
35 |
36 | Build which kind of disk image (single partition or combined image) deps the devkit needs.
37 |
38 | You can just edit the origin disk image if disk space is ok.
39 |
40 | Otherwise you may need create a new blank image by `dd`.
41 |
42 | Combined image aslo can be created by `dd`, you just need load disk layout file by `fdisk`.
43 |
44 | - Porting
45 |
46 | Porting linux distro, you need the `kernel` `firmware` `fstab` etc, so backup them first of all.
47 |
48 | Then copy the prebuilt linux distro `root` files.
49 |
50 | After file operation, you may need some configuration, like user password, extra software.
51 |
52 | Then flash it, boot it, debug it, re-edit someting...
53 |
54 | ## Wishing
55 |
56 | It's pretty easy task after this tool handling some **dirty work**, so have fun!
57 |
58 | ## Sponsors
59 |
60 | [
](https://riscv.org/blog-chinese/2022/11/cnrv-devboard-hacks/)
62 | [
](#sponsors)
63 | [
](#sponsors)
64 |
65 | [
](#sponsors)
66 | [
](#sponsors)
67 | [
](#sponsors)
68 |
69 | ## License
70 |
71 | MPL-2.0
72 |
--------------------------------------------------------------------------------
/compress.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | def xz(src)
4 | `xz -kzvfT0 #{src}`
5 | end
6 |
--------------------------------------------------------------------------------
/copy.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "./decompress"
4 |
5 | class Copy
6 | @temp_dir = "temp"
7 | def initialize(src, dest)
8 | @src = src
9 | @dest = dest
10 |
11 | @pwd = Dir.pwd
12 | `mkdir -p #{@pwd}/#{@temp_dir}`
13 | end
14 |
15 | class << self
16 | # ls -d1 */
17 | def Fedora(src, dest)
18 | @pwd = Dir.pwd
19 |
20 | `mkdir -p #{@temp_dir}/Fedora`
21 | Decompress.untar "#{@temp_dir}/Fedora", src
22 | Dir.chdir "#{@temp_dir}/Fedora" do
23 | inner = `ls -d1 */`.delete "\/\n"
24 | puts "#{inner}/layer.tar"
25 | if File.exist? "#{inner}/layer.tar"
26 | Decompress.done "#{inner}/layer.tar" if Decompress.untar "#{@pwd}/#{dest}", "#{inner}/layer.tar"
27 | else
28 | puts "layer.tar not exist"
29 | end
30 | end
31 | end
32 |
33 | def Arch(src, dest)
34 | @pwd = Dir.pwd
35 |
36 | `mkdir -p #{@temp_dir}/Arch`
37 | Decompress.ungz "#{@temp_dir}/Arch", src
38 | Dir.chdir "#{@temp_dir}/Arch" do
39 | inner = `ls -d1 */`.delete "\/\n"
40 | return system("sudo cp -a #{inner}/* #{@pwd}/#{dest}")
41 | end
42 | end
43 | end
44 | end
45 |
46 | # https://launchpad.net/~canonical-kernel-team/+archive/ubuntu/ppa/+build/24173564
47 | def copy_kernel(src, dest, extra = [], no_default = false)
48 | file_paths = %w[
49 | /boot/
50 | /lib/firmware/
51 | /lib/modprobe.d/
52 | /lib/modules/
53 | /usr/lib/linux/
54 |
55 | /etc/fstab
56 | ]
57 | file_paths = [] if no_default
58 | file_paths += extra
59 |
60 | # exec_dir = Dir.pwd
61 |
62 | `mkdir -p #{dest}`
63 | Dir.chdir dest do
64 | file_paths.each do |file_path|
65 | cp_src = "#{src}#{file_path}"
66 | dest_path = file_path.delete_prefix("/")
67 |
68 | # is_file = if dest_path.end_with?('/')
69 | # false
70 | # else
71 | # true
72 | # end
73 |
74 | parent_arr = dest_path.split("/")
75 | parent_arr.pop
76 | # p parent_arr
77 |
78 | parent_dir = case parent_arr.size
79 | when 0
80 | ""
81 | when 1
82 | parent_arr[0]
83 | else
84 | parent_arr.join("/")
85 | end
86 |
87 | if parent_dir != ""
88 | `mkdir -p #{parent_dir}`
89 | Dir.chdir parent_dir do
90 | puts Dir.pwd
91 |
92 | cmd = "cp -a #{cp_src} ."
93 | puts cmd
94 | system cmd
95 | puts
96 | end
97 | else
98 | puts Dir.pwd
99 |
100 | cmd = "cp -a #{cp_src} ."
101 | puts cmd
102 | system cmd
103 | puts
104 | end
105 | end
106 | end
107 | end
108 |
109 | # copy_map = {
110 | # "0": "1",
111 | # "2": "2"
112 | # }
113 | def copy_par(src, dest, copy_map = nil)
114 | if copy_map.nil?
115 | print `ls -d1 #{src}p*`
116 | puts
117 |
118 | puts "which partition(s) you want copy:"
119 | puts "(eg: 1, 3,4)"
120 | pars = gets.delete_suffix("\n").delete(" ").split(",")
121 | pars.each do |par|
122 | dd_src = `ls -d1 #{src}*#{par}`.delete_suffix("\n")
123 | dd_dest = `ls -d1 #{dest}*#{par}`.delete_suffix("\n")
124 | cmd = "dd if=#{dd_src} of=#{dd_dest}"
125 | puts cmd
126 | system cmd
127 | end
128 | else
129 | copy_map.each do |par_s, par_d|
130 | dd_src = `ls -d1 #{src}*#{par_s}`.delete_suffix("\n")
131 | dd_dest = `ls -d1 #{dest}*#{par_d}`.delete_suffix("\n")
132 | cmd = "dd if=#{dd_src} of=#{dd_dest}"
133 | puts cmd
134 | system cmd
135 | end
136 | end
137 | end
138 |
139 | if __FILE__ == $0
140 | # Copy.Fedora "cache/Fedora-Container-Base-36-1.5.x86_64.tar.xz", "fd-36"
141 | # Copy.Arch "cache/archlinux-bootstrap-2022.09.03-x86_64.tar.gz", "arch"
142 |
143 | l_extra = %w[
144 | /usr/lib/linux-allwinner-5.17-tools-5.17.0-1003/
145 | /usr/lib/libcpupower.so.5.17.0-1003
146 | /usr/lib/linux-tools/
147 | ]
148 |
149 | v_extra = %w[
150 | /usr/lib/linux-image-5.15.0-starfive/
151 | ]
152 |
153 | extlinux_uEnv = %w[
154 | /boot/extlinux/
155 | /boot/uEnv.txt
156 | ]
157 |
158 | r_extra = %w[
159 | /lib/firmware/
160 | /lib/modules/
161 | ]
162 |
163 | r_map = {
164 | "2": "8",
165 | }
166 | # copy_kernel "/media/ubuntu/rootfs", "origin", r_extra, true
167 | # copy_kernel "/home/ubuntu/vscode/rootfs-tools/origin", "rootfs"
168 |
169 | copy_par "/dev/loop14", "/dev/loop15", r_map
170 | end
--------------------------------------------------------------------------------
/decompress.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Decompress
4 | def initialize(dir, file)
5 | @dir = dir
6 | @file = file
7 | end
8 |
9 | class << self
10 | def unzip(dir, file)
11 | return system("unzip -d #{dir} #{file}")
12 | end
13 |
14 | def untar(dir, file)
15 | return system("tar -C #{dir} -xvf #{file}")
16 | end
17 |
18 | def ungz(dir, file)
19 | return system("tar -C #{dir} -zxvf #{file}")
20 | end
21 |
22 | def un7z(dir, file)
23 | return system("7z x -o#{dir} #{file}")
24 | end
25 |
26 | # https://www.cnblogs.com/Andy-Lv/p/5304247.html
27 | def uncpio(dir, file)
28 | pwd_file = "#{Dir.pwd}/#{file}"
29 | # puts pwd_file
30 | Dir.chdir dir do
31 | return system("cpio -i < #{pwd_file}")
32 | end
33 | end
34 |
35 | def done(file)
36 | puts "decompress #{file} done"
37 | end
38 | end
39 |
40 | def matcher
41 | ext = File.extname(@file)
42 | # puts ext
43 | case ext
44 | when ".zip"
45 | Decompress.done @file if Decompress.unzip @dir, @file
46 | when ".tar", ".xz", ".zst"
47 | Decompress.done @file if Decompress.untar @dir, @file
48 | when ".tgz", ".gz"
49 | Decompress.done @file if Decompress.ungz @dir, @file
50 | when ".7z"
51 | Decompress.done @file if Decompress.un7z @dir, @file
52 | else
53 | if @file.end_with? "initrd"
54 | Decompress.done @file if Decompress.uncpio @dir, @file
55 | else
56 | puts "unknown compress format for: #{@file}"
57 | end
58 | end
59 | end
60 | end
61 |
62 | # list = ["cache/ubuntu-base-22.04-base-amd64.tar.gz", "1.a.tgz", "2.tar.xz", "3.c.zip", "4.d.tgz", "5.e.7z"]
63 |
64 | # for f in list
65 | # d = Decompress.new "testdir", f
66 | # d.matcher
67 | # end
68 |
69 | if __FILE__ == $0
70 | d = Decompress.new "temp/test", "cache/initrd"
71 | d.matcher
72 | end
73 |
--------------------------------------------------------------------------------
/dep.txt:
--------------------------------------------------------------------------------
1 | git-core
2 | ruby
3 | qemu-user-static
4 | libvirt-daemon-system
5 |
6 | xz-utils
7 |
8 | unzip
9 | p7zip-full
10 | zstd
11 | cpio
12 |
13 | wget
14 |
15 | btrfs-progs
16 | dosfstools
17 | exfat-utils
18 | ntfs-3g
19 |
20 | u-boot-tools
21 |
22 | fdisk
23 |
--------------------------------------------------------------------------------
/fetch.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | REL = "22.04"
4 | CODENAME = "jammy"
5 | ARCH = "amd64"
6 |
7 | def fetch_ubuntu_base(cache_dir)
8 | url = "https://cdimage.ubuntu.com/ubuntu-base/releases/#{REL}/release"
9 | file = "ubuntu-base-#{REL}-base-#{ARCH}.tar.gz"
10 | sha256 = "#{url}/SHA256SUMS"
11 |
12 | unless File.exist?("#{cache_dir}/#{file}")
13 | `wget #{url}/#{file} -P #{cache_dir}`
14 | end
15 |
16 | `curl -L #{sha256} >> #{cache_dir}/SHA256SUMS`
17 | end
18 |
19 | def fetch_ubuntu_minimal(cache_dir)
20 | url = "https://cloud-images.ubuntu.com/minimal/releases/#{CODENAME}/release/"
21 | file = "ubuntu-#{REL}-minimal-cloudimg-#{ARCH}-root.tar.xz"
22 | sha256 = "#{url}/SHA256SUMS"
23 |
24 | unless File.exist?("#{cache_dir}/#{file}")
25 | `wget #{url}/#{file} -P #{cache_dir}`
26 | end
27 |
28 | `curl -L #{sha256} >> #{cache_dir}/SHA256SUMS`
29 | end
30 |
--------------------------------------------------------------------------------
/fstab.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # https://wiki.gentoo.org/wiki//etc/fstab
4 | # https://wiki.archlinux.org/title/fstab
5 | # https://wiki.archlinux.org/title/persistent_block_device_naming
6 |
7 | def label_to(par, label)
8 | output = `mount | grep #{par}`.chomp
9 | type = output.split(" ")[4]
10 | case type
11 | when "swap"
12 | `swaplabel -L '#{label}' #{par}`
13 | when "ext2", "ext3", "ext4"
14 | `e2label #{par} '#{label}'`
15 | when "fat", "vfat"
16 | `fatlabel #{par} '#{label}'`
17 | when "btrfs"
18 | `btrfs filesystem label #{par} '#{label}'`
19 | when "exfat"
20 | `exfatlabel #{par} '#{label}'`
21 | when "ntfs"
22 | `ntfslabel #{par} '#{label}'`
23 | else
24 | puts "Not supported FS type"
25 | end
26 | end
27 |
28 | if __FILE__ == $0
29 | label_to("/dev/sdc8", "cloudimg-rootfs")
30 | end
31 |
--------------------------------------------------------------------------------
/image.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # https://wiki.ubuntu.com/ARM/EditBootscr
4 | def de_uboot_scr(scr, script = nil)
5 | if script.nil?
6 | script = if scr.end_with?(".scr")
7 | "#{scr}ipt"
8 | else
9 | "#{scr}.script"
10 | end
11 | end
12 |
13 | `dd if=#{scr} of=#{script} bs=72 skip=1`
14 | end
15 |
16 | # https://manpages.ubuntu.com/manpages/jammy/man1/mkimage.1.html
17 | def mk_uboot_scr(script, scr = nil, arch = "arm", comp = "none")
18 | if scr.nil?
19 | scr = if script.end_with?(".script")
20 | script.delete_suffix("ipt")
21 | else
22 | "#{script}.scr"
23 | end
24 | end
25 |
26 | # mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
27 | # mkimage -T list
28 | `mkimage -A #{arch} -T script -C #{comp} -d #{script} #{scr}`
29 | end
30 |
31 | # https://manpages.ubuntu.com/manpages/jammy/en/man1/dd.1posix.html
32 | # https://manpages.ubuntu.com/manpages/jammy/man8/mkfs.8.html
33 | # https://manpages.ubuntu.com/manpages/jammy/man8/mkfs.ext4.8.html
34 | # https://manpages.ubuntu.com/manpages/jammy/en/man8/sfdisk.8.html
35 | def mk_rootfs(img, block_count, *opt, **args)
36 | block_size = opt[0] || args[:block_size]
37 | layout = opt[1] || args[:layout]
38 | mkfs_cmd = opt[2] || args[:mkfs_cmd]
39 |
40 | dd_bs = if block_size.nil? or block_size.empty?
41 | ""
42 | else
43 | # cmd_opt in func
44 | # should end with ' '
45 | # so we get log with good formatting
46 | "bs=#{block_size} "
47 | end
48 |
49 | dd_cmd = "dd if=/dev/zero of=#{img} count=0 seek=#{block_count} #{dd_bs}"
50 | puts dd_cmd
51 | system dd_cmd
52 |
53 | if layout.nil? or layout.empty?
54 | if mkfs_cmd != nil
55 | cmd = "#{mkfs_cmd} #{img}"
56 | puts cmd
57 | system cmd
58 | end
59 | else
60 | cmd = "sfdisk #{img} < #{layout}"
61 | puts cmd
62 | system cmd
63 | end
64 | end
65 |
66 | if __FILE__ == $0
67 | # de_uboot_scr "boot.scr"
68 |
69 | # mk_uboot_scr "boot.script"
70 | # mk_uboot_scr "boot.script", "abc.scr"
71 |
72 | # mk_rootfs "test-MB.img", 2100, "1MB"
73 | # mk_rootfs "test-MiB.img", 2001, "1MiB"
74 | # mk_rootfs "test-MB.img", 2100, "1MB", "vf2"
75 | # mk_rootfs "test-MiB.img", 2001, "1MiB", "vf2"
76 | # mk_rootfs "test.img", 4096100, "" ,"vf2"
77 | # mk_rootfs "test.img", 4096100, nil, "vf2"
78 | # mk_rootfs "test.img", 4096100, nil, nil, "mkfs.ext4 -F"
79 | mk_rootfs "test.img", 4096100, layout: "vf2"
80 | end
81 |
--------------------------------------------------------------------------------
/initrd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # https://www.cnblogs.com/shineshqw/articles/2336842.html
4 | # https://linuxconfig.org/how-to-create-and-extract-cpio-archives-on-linux-examples
5 |
6 | find initrd/ -depth -print0 | cpio -ocv0 | gzip -9 > temp/initrd
7 |
--------------------------------------------------------------------------------
/main.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "./fetch"
4 | require "./decompress"
5 | require "./size"
6 | require "./mount"
7 |
8 | CACHE_DIR = "cache"
9 | ROOT_PKG = "ubuntu-22.04-minimal-cloudimg-amd64-root.tar.xz"
10 | TEMP_ROOTFS_DIR = "ub-22"
11 | ROOTFS_DIR = "rootfs"
12 | ROOTFS_IMG = "edison-image-edison.ext4"
13 |
14 | def main
15 | `mkdir -p #{CACHE_DIR} #{TEMP_ROOTFS_DIR} #{ROOTFS_DIR}`
16 | fetch_ubuntu_base CACHE_DIR
17 | fetch_ubuntu_minimal CACHE_DIR
18 | `sha256sum -c #{CACHE_DIR}/SHA256SUMS`
19 |
20 | d = Decompress.new TEMP_ROOTFS_DIR, "#{CACHE_DIR}/#{ROOT_PKG}"
21 | d.matcher
22 |
23 | `cp -a boot #{TEMP_ROOTFS_DIR}`
24 | `cp -a firmware #{TEMP_ROOTFS_DIR}/lib`
25 | `cp -a modules #{TEMP_ROOTFS_DIR}/lib`
26 |
27 | `cp -a vendor-resources/intel-edison/* #{TEMP_ROOTFS_DIR}`
28 |
29 | mountDev TEMP_ROOTFS_DIR
30 | `sudo chroot #{TEMP_ROOTFS_DIR} /bin/bash -c /root/config.sh`
31 | unmountDev TEMP_ROOTFS_DIR
32 |
33 | s = Size.new TEMP_ROOTFS_DIR, 100, 100, "/dev/sda1"
34 | size = s.GetSize
35 | `dd if=/dev/zero of=#{ROOTFS_IMG} bs=1MB count=0 seek=#{size}`
36 | `mkfs.ext4 -F #{ROOTFS_IMG}`
37 | `tune2fs -c0 -i0 #{ROOTFS_IMG}`
38 |
39 | mountImage ROOTFS_IMG, ROOTFS_DIR
40 | `sudo cp -a #{TEMP_ROOTFS_DIR}/* #{ROOTFS_DIR}`
41 | unmountImage ROOTFS_DIR
42 | end
43 |
44 | main
45 |
--------------------------------------------------------------------------------
/mount.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | def mountImage(img, path)
4 | puts "mounting image #{img} on #{path}"
5 | `mount -o loop #{img} #{path}`
6 | end
7 |
8 | def unmountImage(path)
9 | puts "unmounting image on #{path}"
10 | `umount #{path}`
11 | end
12 |
13 | # ref: https://wiki.alpinelinux.org/wiki/How_to_make_a_cross_architecture_chroot
14 | def mountDev(path)
15 | puts "mounting /dev on #{path}"
16 | `mount -t proc /proc #{path}/proc`
17 | `mount -t sysfs /sys #{path}/sys`
18 | `mount -o bind /dev #{path}/dev`
19 | `mount -o bind /dev/pts #{path}/dev/pts`
20 | `mount -o bind /run #{path}/run`
21 | end
22 |
23 | def unmountDev(path)
24 | puts "unmounting /dev on #{path}"
25 | `umount #{path}/proc`
26 | `umount #{path}/sys`
27 | `umount #{path}/dev/pts`
28 | `umount #{path}/dev`
29 | `umount #{path}/run`
30 | end
31 |
32 | # https://askubuntu.com/questions/69363/mount-single-partition-from-image-of-entire-disk-device
33 | def getImageLoops(img)
34 | cmd = "losetup | grep #{img}"
35 | IO.popen(cmd) do |r|
36 | lines = r.readlines
37 | return nil if lines.empty?
38 |
39 | loops = []
40 | lines.each do |line|
41 | lo = line.delete_suffix("\n").split(" ").first
42 | loops.push lo
43 | end
44 | return loops
45 | end
46 | end
47 |
48 | def mountLoop(img, *opt)
49 | loop_dev = opt[0]
50 | offset = opt[1]
51 |
52 | unless loop_dev.nil?
53 | if !offset.nil?
54 | `losetup -o #{offset} #{loop_dev} #{img}`
55 | else
56 | `losetup #{loop_dev} #{img}`
57 | end
58 | return loop_dev
59 | end
60 |
61 | output = `losetup -Pf --show #{img}`
62 | return output.delete_suffix("\n")
63 | end
64 |
65 | def mountCombinedImage(img, path = nil, *opt)
66 | par = opt[0]
67 | loop_dev = opt[1]
68 |
69 | if loop_dev.nil?
70 | loop_dev = mountLoop img
71 | else
72 | mountLoop img, loop_dev
73 | end
74 |
75 | if path != nil
76 | system "fdisk -l #{img}"
77 |
78 | if par.nil?
79 | print "which partition to mount: "
80 | par = gets.delete_suffix("\n")
81 | # p par
82 | end
83 |
84 | loop_par = "#{loop_dev}p#{par}"
85 |
86 | puts "mounting #{loop_par} on #{path}"
87 | `mount #{loop_par} #{path}`
88 | else
89 | puts "#{img} mounted on #{loop_dev}"
90 | end
91 | end
92 |
93 | def unmountCombinedImage(img)
94 | loops = getImageLoops img
95 | loops.each do |lo|
96 | puts "unmounting combined image on #{lo}"
97 | `losetup -d #{lo}`
98 | end
99 | end
100 |
101 | if __FILE__ == $0
102 | # img = "ubuntu-core-gnome.img"
103 | # path = "mars-A1-ub18-core"
104 |
105 | img = "vf2.img"
106 | path = "rootfs"
107 |
108 | # mountImage img, path
109 | # mountCombinedImage img, path
110 | # mountDev path
111 |
112 | # unmountDev path
113 | # puts "waiting for 3s"
114 | # sleep 3
115 | unmountImage path
116 | # unmountCombinedImage img
117 |
118 | img2 = 'starfive-jh7110-VF2-VF2_515_v2.3.0-55.img'
119 | # mountCombinedImage img2, "vf-de"
120 | unmountImage "vf-de"
121 |
122 | # mountCombinedImage img2
123 | # mountCombinedImage img
124 | unmountCombinedImage img2
125 | unmountCombinedImage img
126 | end
--------------------------------------------------------------------------------
/overlay.sh:
--------------------------------------------------------------------------------
1 | mount -t overlay -o lowerdir=ub-22:binary,upperdir=rk-vendor,workdir=work overlay rootfs
--------------------------------------------------------------------------------
/resize.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | def resizeImage(img, size)
4 | `e2fsck -f #{img}`
5 | `resize2fs #{img} #{size}`
6 | # re-format to update inodes
7 | `mkfs.ext4 -F #{img}`
8 | end
9 |
--------------------------------------------------------------------------------
/size.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class Size
4 | @ratio = 4
5 | @block_size = 4096
6 |
7 | def initialize(temp_rootfs_dir, extra_inode, extra_size_MB, *rootfs_dev)
8 | @rDir = temp_rootfs_dir.to_s || ""
9 | @eInode = extra_inode.to_i || 0
10 | @eSizeM = extra_size_MB.to_i || 0
11 | @rDev = rootfs_dev[0].to_s || ""
12 | end
13 |
14 | class << self
15 | def BtoK(size)
16 | return size / 1024
17 | end
18 |
19 | def KtoM(size)
20 | return size / 1024
21 | end
22 |
23 | def MtoG(size)
24 | return size / 1024
25 | end
26 |
27 | # sudo tune2fs -l /dev/nvme0n1p4
28 | #
29 | # Blocks per group: 32768
30 | # Inodes per group: 8192
31 | #
32 | # 4 = 32768 / 8192
33 | def InodeToBlock(inode)
34 | return inode * @ratio
35 | end
36 |
37 | # Block size: 4096
38 | def BlockToB(block)
39 | return block * @block_size
40 | end
41 |
42 | def BlockToK(block)
43 | return BtoK(BlockToB(block))
44 | end
45 |
46 | def InodeToK(inode)
47 | return BlockToK(InodeToBlock(inode))
48 | end
49 |
50 | def BlockToM(block)
51 | return KtoM(BlockToK(block))
52 | end
53 |
54 | def InodeToM(inode)
55 | return KtoM(InodeToK(inode))
56 | end
57 |
58 | # sudo find . -printf "%h\n" | cut -d / -f -2 | sort | uniq -c | sort -rn
59 | def DirInode(dir)
60 | output = `sudo find #{dir}/.. -printf "%h\n" | cut -d / -f -2 | sort | uniq -c | sort -rn | grep #{dir}`
61 | inode = output.split(" ").first
62 | # puts inode
63 | return inode.to_i
64 | end
65 |
66 | def DirSizeK(dir)
67 | output = `sudo du -d0 #{dir}`
68 | size = output.split(" ").first
69 | # puts size
70 | return size.to_i
71 | end
72 |
73 | def DirSizeM(dir)
74 | return KtoM(DirSizeK(dir))
75 | end
76 |
77 | def DirInodeK(dir)
78 | result = InodeToK(DirInode(dir))
79 | # puts result
80 | return result
81 | end
82 |
83 | def DirInodeM(dir)
84 | return KtoM(DirInodeK(dir))
85 | end
86 |
87 | def Bigger(num_a, num_b)
88 | return num_a if num_a >= num_b
89 |
90 | return num_b
91 | end
92 | end
93 |
94 | def GetRatio
95 | if @rDev.empty?
96 | puts "missing disk device ARG"
97 | return false
98 | end
99 |
100 | output1 = `sudo tune2fs -l #{@rDev} | grep 'Blocks per group'`
101 | output2 = `sudo tune2fs -l #{@rDev} | grep 'Inodes per group'`
102 |
103 | return false if output1.empty? or output2.empty?
104 |
105 | blocks = output1.split(" ").last
106 | inodes = output2.split(" ").last
107 | ratio = blocks.to_i.fdiv(inodes.to_i)
108 | # puts ratio
109 | return ratio
110 | end
111 |
112 | def GetBlockSize
113 | if @rDev.empty?
114 | puts "missing disk device ARG"
115 | return false
116 | end
117 |
118 | output = `sudo tune2fs -l #{@rDev} | grep 'Block size'`
119 | return false if output.empty?
120 |
121 | size = output.split(" ").last
122 | # puts size
123 | return size.to_i
124 | end
125 |
126 | def GetSize
127 | unless @rDev.empty?
128 | @ratio = self.GetRatio || @ratio
129 | @block_size = self.GetBlockSize || @block_size
130 | end
131 |
132 | if @rDir.empty?
133 | puts "missing directory ARG"
134 | return false
135 | end
136 |
137 | rInode = Size.DirInode @rDir
138 | rSizeM = Size.DirSizeM @rDir
139 |
140 | aInodeM = Size.InodeToM(rInode + @eInode)
141 | aSizeM = rSizeM + @eSizeM
142 |
143 | # puts aInodeM
144 | return Size.Bigger(aInodeM.ceil(-1), aSizeM.ceil(-1))
145 | end
146 | end
147 |
148 | # dir = "ub-22"
149 | # dev = ""
150 |
151 | # s = Size.new dir, 100, 100
152 |
153 | # puts s.GetRatio
154 | # puts s.GetBlockSize
155 | # puts s.GetSize
156 |
157 | # for n in 1..10
158 | # s = Size.new "", 0, 0, "/dev/mmcblk0p#{n}"
159 | # puts "/dev/mmcblk0p#{n} #{s.GetRatio}"
160 | # end
161 |
162 | # sudo ruby size.rb 2>/dev/null
163 |
--------------------------------------------------------------------------------
/template.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | main() {
6 | apt-get update
7 | apt-get install -y
8 | }
9 |
10 | main "$@"
11 |
--------------------------------------------------------------------------------
/vendor-resources/friendlyelec-r6s/mjr:
--------------------------------------------------------------------------------
1 | label: gpt
2 | label-id: 837CB2D9-B9E9-4232-9967-880913144D47
3 | device: cache/Manjaro-ARM-gnome-generic-22.12.img
4 | unit: sectors
5 | first-lba: 34
6 | last-lba: 14815198
7 | sector-size: 512
8 |
9 | cache/Manjaro-ARM-gnome-generic-22.12.img1 : start= 2048, size= 997376, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=069CB19B-E0B2-4CB8-A53F-37FCE9C6EAE7, name="primary"
10 | cache/Manjaro-ARM-gnome-generic-22.12.img2 : start= 999424, size= 13813760, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=1B17A334-53C8-4A52-A9A9-38542BA1A14B, name="primary"
11 |
--------------------------------------------------------------------------------
/vendor-resources/friendlyelec-r6s/r6s:
--------------------------------------------------------------------------------
1 | # rootfs 8G on 32G SD card
2 | label: gpt
3 | label-id: 73987B6B-4974-4C94-A3E8-58AB2EB7A946
4 | device: /dev/sdc
5 | unit: sectors
6 | first-lba: 34
7 | last-lba: 61067230
8 |
9 | /dev/sdc1 : start= 16384, size= 8192, type=F808D051-1602-4DCD-9452-F9637FEFC49A, uuid=B750E44E-833F-4A30-C38C-B117241D84D4, name="uboot"
10 | /dev/sdc2 : start= 24576, size= 8192, type=C6D08308-E418-4124-8890-F8411E3D8D87, uuid=A1C81622-7741-47AD-B846-C6972488D396, name="misc"
11 | /dev/sdc3 : start= 32768, size= 8192, type=2A583E58-486A-4BD4-ACE4-8D5454E97F5C, uuid=43784A32-A03D-4ADE-92C6-EDE64FF9B794, name="dtbo"
12 | /dev/sdc4 : start= 40960, size= 32768, type=6115F139-4F47-4BAF-8D23-B6957EAEE4B3, uuid=000B305F-484A-4582-9090-4AD0099D47BD, name="resource"
13 | /dev/sdc5 : start= 73728, size= 81920, type=A83FBA16-D354-45C5-8B44-3EC50832D363, uuid=24EEB649-277F-4C11-FFEB-D9F20027A83B, name="kernel"
14 | /dev/sdc6 : start= 155648, size= 65536, type=500E2214-B72D-4CC3-D7C1-8419260130F5, uuid=1CAC805F-726A-495A-FD35-821355A6E7E8, name="boot"
15 | /dev/sdc7 : start= 221184, size= 65536, type=E099DA71-5450-44EA-AA9F-1B771C582805, uuid=2BFEE623-D83C-426A-AB80-21732C9BB7D3, name="recovery"
16 | /dev/sdc8 : start= 286720, size= 15728640, type=AF12D156-5D5B-4EE3-B415-8D492CA12EA9, uuid=B2AF085D-A675-48C6-C437-F6D557FF4744, name="rootfs"
17 | /dev/sdc9 : start= 16015360, size= 45051870, type=8EB9EE49-E963-4BB6-FD75-F30618DF9DCD, uuid=2D9E7B61-1B31-47E7-EE0D-8CEC26D42EF6, name="userdata"
18 |
--------------------------------------------------------------------------------
/vendor-resources/friendlyelec-r6s/r6s-img:
--------------------------------------------------------------------------------
1 | label: gpt
2 | label-id: 73987B6B-4974-4C94-A3E8-58AB2EB7A946
3 | device: rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img
4 | unit: sectors
5 | first-lba: 34
6 | last-lba: 15234340
7 |
8 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img1 : start= 16384, size= 8192, type=F808D051-1602-4DCD-9452-F9637FEFC49A, uuid=B750E44E-833F-4A30-C38C-B117241D84D4, name="uboot"
9 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img2 : start= 24576, size= 8192, type=C6D08308-E418-4124-8890-F8411E3D8D87, uuid=A1C81622-7741-47AD-B846-C6972488D396, name="misc"
10 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img3 : start= 32768, size= 8192, type=2A583E58-486A-4BD4-ACE4-8D5454E97F5C, uuid=43784A32-A03D-4ADE-92C6-EDE64FF9B794, name="dtbo"
11 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img4 : start= 40960, size= 32768, type=6115F139-4F47-4BAF-8D23-B6957EAEE4B3, uuid=000B305F-484A-4582-9090-4AD0099D47BD, name="resource"
12 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img5 : start= 73728, size= 81920, type=A83FBA16-D354-45C5-8B44-3EC50832D363, uuid=24EEB649-277F-4C11-FFEB-D9F20027A83B, name="kernel"
13 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img6 : start= 155648, size= 65536, type=500E2214-B72D-4CC3-D7C1-8419260130F5, uuid=1CAC805F-726A-495A-FD35-821355A6E7E8, name="boot"
14 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img7 : start= 221184, size= 65536, type=E099DA71-5450-44EA-AA9F-1B771C582805, uuid=2BFEE623-D83C-426A-AB80-21732C9BB7D3, name="recovery"
15 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img8 : start= 286720, size= 7864320, type=AF12D156-5D5B-4EE3-B415-8D492CA12EA9, uuid=B2AF085D-A675-48C6-C437-F6D557FF4744, name="rootfs"
16 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img9 : start= 8151040, size= 7083301, type=8EB9EE49-E963-4BB6-FD75-F30618DF9DCD, uuid=2D9E7B61-1B31-47E7-EE0D-8CEC26D42EF6, name="userdata"
17 |
--------------------------------------------------------------------------------
/vendor-resources/friendlyelec-r6s/r6s-mjr:
--------------------------------------------------------------------------------
1 | # rootfs 7G
2 | label: gpt
3 | label-id: 73987B6B-4974-4C94-A3E8-58AB2EB7A946
4 | device: rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img
5 | unit: sectors
6 | first-lba: 34
7 | last-lba: 15234340
8 |
9 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img1 : start= 16384, size= 8192, type=F808D051-1602-4DCD-9452-F9637FEFC49A, uuid=B750E44E-833F-4A30-C38C-B117241D84D4, name="uboot"
10 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img2 : start= 24576, size= 8192, type=C6D08308-E418-4124-8890-F8411E3D8D87, uuid=A1C81622-7741-47AD-B846-C6972488D396, name="misc"
11 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img3 : start= 32768, size= 8192, type=2A583E58-486A-4BD4-ACE4-8D5454E97F5C, uuid=43784A32-A03D-4ADE-92C6-EDE64FF9B794, name="dtbo"
12 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img4 : start= 40960, size= 32768, type=6115F139-4F47-4BAF-8D23-B6957EAEE4B3, uuid=000B305F-484A-4582-9090-4AD0099D47BD, name="resource"
13 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img5 : start= 73728, size= 81920, type=A83FBA16-D354-45C5-8B44-3EC50832D363, uuid=24EEB649-277F-4C11-FFEB-D9F20027A83B, name="kernel"
14 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img6 : start= 155648, size= 65536, type=500E2214-B72D-4CC3-D7C1-8419260130F5, uuid=1CAC805F-726A-495A-FD35-821355A6E7E8, name="boot"
15 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img7 : start= 221184, size= 65536, type=E099DA71-5450-44EA-AA9F-1B771C582805, uuid=2BFEE623-D83C-426A-AB80-21732C9BB7D3, name="recovery"
16 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img8 : start= 286720, size= 13813760, type=AF12D156-5D5B-4EE3-B415-8D492CA12EA9, uuid=B2AF085D-A675-48C6-C437-F6D557FF4744, name="rootfs"
17 | rk3588-sd-ubuntu-jammy-desktop-5.10-arm64-20221213.img9 : start= 14100480, size= 1133860, type=8EB9EE49-E963-4BB6-FD75-F30618DF9DCD, uuid=2D9E7B61-1B31-47E7-EE0D-8CEC26D42EF6, name="userdata"
18 |
--------------------------------------------------------------------------------
/vendor-resources/friendlyelec-r6s/root/config.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | add_ubuntu() {
6 | useradd -G sudo -d /home/ubuntu -m -s /bin/bash ubuntu
7 | echo "ubuntu:ubuntu" | chpasswd
8 | echo "root:root" | chpasswd
9 | }
10 |
11 | add_lang_pack() {
12 | apt-get install -y language-pack-en-base
13 | apt-get install -y dialog apt-utils
14 | }
15 |
16 | install_software() {
17 | apt-get install -y dnsutils file htop ifupdown iputils-ping lshw lsof nano net-tools network-manager openssh-server rfkill tree u-boot-tools wget wireless-tools wpasupplicant
18 | }
19 |
20 | set_sshd_config() {
21 | cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
22 | sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
23 | sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
24 | }
25 |
26 | main() {
27 | export DEBIAN_FRONTEND="noninteractive"
28 |
29 | # apt-get update
30 |
31 | # add_lang_pack
32 | # install_software
33 | # set_sshd_config
34 | # rm -rf /var/lib/apt/*
35 |
36 | add_ubuntu
37 | # systemctl enable getty@ttyS2.service
38 |
39 | touch /etc/cloud/cloud-init.disabled
40 | apt autoremove --purge snapd
41 |
42 | unset DEBIAN_FRONTEND
43 | }
44 |
45 | main "$@"
46 |
--------------------------------------------------------------------------------
/vendor-resources/friendlyelec-r6s/root/mjr.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | add_user() {
6 | useradd -G sudo -d /home/manjaro -m -s /bin/bash manjaro
7 | echo "manjaro:manjaro" | chpasswd
8 | echo "root:root" | chpasswd
9 | }
10 |
11 | set_sshd_config() {
12 | cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
13 | sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
14 | sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
15 | }
16 |
17 | main() {
18 | add_user
19 | }
20 |
21 | main "$@"
22 |
--------------------------------------------------------------------------------
/vendor-resources/friendlyelec-r6s/root/rk-vendor.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | main() {
6 | # apt-get update
7 | # apt-get upgrade -y
8 |
9 | chmod o+x /usr/lib/dbus-1.0/dbus-daemon-launch-helper
10 | chmod +x /etc/rc.local
11 |
12 | export APT_INSTALL="apt-get install -fy --allow-downgrades"
13 |
14 | #---------------power management --------------
15 | ${APT_INSTALL} pm-utils triggerhappy
16 | cp /etc/Powermanager/triggerhappy.service /lib/systemd/system/triggerhappy.service
17 |
18 | #---------------Rga--------------
19 | ${APT_INSTALL} /packages/rga/*.deb
20 |
21 | echo -e "\033[36m Setup Video.................... \033[0m"
22 | ${APT_INSTALL} gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-tools gstreamer1.0-alsa \
23 | gstreamer1.0-plugins-base-apps qtmultimedia5-examples
24 |
25 | ${APT_INSTALL} /packages/mpp/*
26 | ${APT_INSTALL} /packages/gst-rkmpp/*.deb
27 | ${APT_INSTALL} /packages/gstreamer/*.deb
28 | ${APT_INSTALL} /packages/gst-plugins-base1.0/*.deb
29 | ${APT_INSTALL} /packages/gst-plugins-bad1.0/*.deb
30 | ${APT_INSTALL} /packages/gst-plugins-good1.0/*.deb
31 |
32 | #---------Camera---------
33 | echo -e "\033[36m Install camera.................... \033[0m"
34 | ${APT_INSTALL} cheese v4l-utils
35 | ${APT_INSTALL} /packages/rkisp/*.deb
36 | ${APT_INSTALL} /packages/rkaiq/*.deb
37 | ${APT_INSTALL} /packages/libv4l/*.deb
38 |
39 | #---------Xserver---------
40 | echo -e "\033[36m Install Xserver.................... \033[0m"
41 | ${APT_INSTALL} /packages/xserver/*.deb
42 |
43 | #---------------Openbox--------------
44 | echo -e "\033[36m Install openbox.................... \033[0m"
45 | ${APT_INSTALL} /packages/openbox/*.deb
46 |
47 | #---------update chromium-----
48 | ${APT_INSTALL} /packages/chromium/*.deb
49 |
50 | #------------------libdrm------------
51 | echo -e "\033[36m Install libdrm.................... \033[0m"
52 | ${APT_INSTALL} /packages/libdrm/*.deb
53 |
54 | #------------------libdrm-cursor------------
55 | echo -e "\033[36m Install libdrm-cursor.................... \033[0m"
56 | ${APT_INSTALL} /packages/libdrm-cursor/*.deb
57 |
58 | # Only preload libdrm-cursor for X
59 | sed -i "/libdrm-cursor.so/d" /etc/ld.so.preload
60 | sed -i "1aexport LD_PRELOAD=libdrm-cursor.so.1" /usr/bin/X
61 |
62 | #------------------pcmanfm------------
63 | echo -e "\033[36m Install pcmanfm.................... \033[0m"
64 | ${APT_INSTALL} /packages/pcmanfm/*.deb
65 |
66 | #------------------rkwifibt------------
67 | echo -e "\033[36m Install rkwifibt.................... \033[0m"
68 | ${APT_INSTALL} /packages/rkwifibt/*.deb
69 | ln -s /system/etc/firmware /vendor/etc/
70 |
71 | if [ "$VERSION" == "debug" ]; then
72 | #------------------glmark2------------
73 | echo -e "\033[36m Install glmark2.................... \033[0m"
74 | ${APT_INSTALL} /packages/glmark2/*.deb
75 | fi
76 |
77 | echo -e "\033[36m Install synaptic/onboard.................... \033[0m"
78 | ${APT_INSTALL} synaptic onboard
79 |
80 | echo -e "\033[36m Install network vpn.................... \033[0m"
81 | ${APT_INSTALL} network-manager-l2tp network-manager-openvpn network-manager-pptp network-manager-strongswan network-manager-vpnc
82 | apt install -fy network-manager-gnome --reinstall
83 |
84 | #------------------pulseaudio---------
85 | echo -e "\033[36m Install pulseaudio................. \033[0m"
86 | no|apt-get install -fy --allow-downgrades /packages/pulseaudio/*.deb
87 |
88 | # mark package to hold
89 | apt list --installed | grep -v oldstable | cut -d/ -f1 | xargs apt-mark hold
90 |
91 | #---------------Custom Script--------------
92 | systemctl mask systemd-networkd-wait-online.service
93 | systemctl mask NetworkManager-wait-online.service
94 | rm /lib/systemd/system/wpa_supplicant@.service
95 |
96 | #---------------Clean--------------
97 | # rm -rf /var/cache/apt/archives/*.deb
98 | # rm -rf /var/lib/apt/lists/*
99 | }
100 |
101 | main "$@"
102 |
--------------------------------------------------------------------------------
/vendor-resources/intel-edison/etc/apt/apt.conf:
--------------------------------------------------------------------------------
1 | APT::Get::Install-Recommends "false";
2 | APT::Get::Install-Suggests "false";
--------------------------------------------------------------------------------
/vendor-resources/intel-edison/etc/fstab:
--------------------------------------------------------------------------------
1 | rootfs / auto nodev,noatime,discard,barrier=1,data=ordered,noauto_da_alloc 1 1
2 | proc /proc proc defaults 0 0
3 | devpts /dev/pts devpts mode=0620,gid=5 0 0
4 | usbdevfs /proc/bus/usb usbdevfs auto 0 0
5 | tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0
6 | tmpfs /var/volatile tmpfs defaults 0 0
7 |
8 | /dev/disk/by-partlabel/boot /boot auto noauto,x-systemd.automount,nosuid,nodev,noatime,discard 1 1
9 | #/dev/disk/by-partlabel/home /home auto noauto,x-systemd.automount,nosuid,nodev,noatime,discard,barrier=1,data=ordered,noauto_da_alloc 1 1
10 |
--------------------------------------------------------------------------------
/vendor-resources/intel-edison/etc/fw_env.config:
--------------------------------------------------------------------------------
1 | # Configuration file for fw_(printenv/setenv) utility.
2 | # Up to two entries are valid, in this case the redundant
3 | # environment sector is assumed present.
4 | # Notice, that the "Number of sectors" is not required on NOR and SPI-dataflash.
5 | # Futhermore, if the Flash sector size is ommitted, this value is assumed to
6 | # be the same as the Environment size, which is valid for NOR and SPI-dataflash
7 |
8 | # MTD device name Device offset Env. size Flash sector size Number of sectors
9 | # On Edison, the u-boot environments are located on partitions 2 and 4 and both have a size of 64kB
10 | /dev/mmcblk0p2 0x0000 0x10000
11 | /dev/mmcblk0p4 0x0000 0x10000
12 |
--------------------------------------------------------------------------------
/vendor-resources/intel-edison/etc/hostname:
--------------------------------------------------------------------------------
1 | edison
--------------------------------------------------------------------------------
/vendor-resources/intel-edison/root/config.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | add_ubuntu() {
6 | useradd -G sudo -d /home/ubuntu -m -s /bin/bash ubuntu
7 | echo "ubuntu:ubuntu" | chpasswd
8 | echo "root:root" | chpasswd
9 | }
10 |
11 | add_lang_pack() {
12 | apt-get install -y language-pack-en-base
13 | apt-get install -y dialog apt-utils
14 | }
15 |
16 | install_software() {
17 | apt-get install -y dnsutils file htop ifupdown iputils-ping lshw lsof nano net-tools network-manager openssh-server rfkill tree u-boot-tools wget wireless-tools wpasupplicant
18 | apt-get install /tmp/resize-helper_0.12_all.deb
19 | }
20 |
21 | set_sshd_config() {
22 | cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
23 | sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
24 | sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
25 | }
26 |
27 | main() {
28 | export DEBIAN_FRONTEND="noninteractive"
29 |
30 | apt-get update
31 |
32 | # add_lang_pack
33 | install_software
34 | set_sshd_config
35 | rm -rf /var/lib/apt/*
36 |
37 | add_ubuntu
38 | systemctl enable getty@ttyS2.service
39 |
40 | unset DEBIAN_FRONTEND
41 | }
42 |
43 | main "$@"
44 |
--------------------------------------------------------------------------------
/vendor-resources/intel-edison/tmp/resize-helper_0.12_all.deb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/intel-edison/tmp/resize-helper_0.12_all.deb
--------------------------------------------------------------------------------
/vendor-resources/intel-edison/usr/bin/configure_edison:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # Copyright (c) 2014, Intel Corporation.
4 | # Copyright (c) 2020, Ferry Toth and Matthias Dieter Wallnöfer
5 | #
6 | # This program is free software; you can redistribute it and/or modify it
7 | # under the terms and conditions of the GNU Lesser General Public License,
8 | # version 2.1, as published by the Free Software Foundation.
9 | #
10 | # This program is distributed in the hope it will be useful, but WITHOUT ANY
11 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
13 | # more details.
14 | #
15 |
16 | import os
17 | import sys
18 | from sys import stdout
19 | import time
20 | import termios
21 | import fcntl
22 | import subprocess
23 | import argparse
24 | import re
25 | import socket
26 | import struct
27 | from array import *
28 | import configparser
29 | from bottle import route, run, debug, template, request, static_file, redirect
30 | import datetime
31 | from datetime import timedelta
32 |
33 | WSREGEX = re.compile(r"\s+")
34 | STATE_DIR = '/var/lib/edison_config_tools'
35 | HOST_AP_MODE_FILE = "/.start-in-host-ap-mode"
36 | CONNMAN_SETTINGS = "/var/lib/connman/settings"
37 | CONNMAN_SERVICES = "/var/lib/connman/wifi.config"
38 |
39 | # Types
40 | #######################################
41 | class classHostName:
42 | Old = ""
43 | New = ""
44 | Valid = False
45 | Changed = False
46 | Tooltip = ""
47 |
48 | class classWired:
49 | Type = ""
50 | Mode = ""
51 | NewMode = ""
52 | IP = ""
53 | Changed = False
54 |
55 | class classWifiAP:
56 | Name = ""
57 | Passphrase = ""
58 | NewMode = ""
59 | IP = ""
60 | Changed = False
61 | Enabled = False
62 |
63 | class classSettings:
64 | HostName = classHostName()
65 | Wired = classWired()
66 | BT = classWifiAP()
67 | Wifi = classWifiAP()
68 | AP = classWifiAP()
69 |
70 | class text_colors:
71 | CYAN = '\033[96m'
72 | MAGENTA = '\033[95m'
73 | BLUE = '\033[94m'
74 | YELLOW = '\033[93m'
75 | GREEN = '\033[92m'
76 | RED = '\033[91m'
77 | END = '\033[0m'
78 |
79 | # Helpers
80 | #######################################
81 | def _checkName(newName):
82 | length = len(newName)
83 | if length < 1 or length > 63:
84 | return -1
85 | if newName[0] == '-' or newName[length - 1] == '-':
86 | return -2
87 | for i in range(length):
88 | if not newName[i].isalnum() and newName[i] != '-':
89 | return -3
90 | return 0
91 |
92 | def _changeHostName(newName):
93 | hostname_file = open('/etc/hostname','w')
94 | hostname_file.write(newName + "\n")
95 | hostname_file.close()
96 | subprocess.call("hostname -F /etc/hostname", shell=True)
97 |
98 | def _getDefaultSSID():
99 | data = os.popen("cat /sys/class/net/wlan0/address | tr '[:lower:]' '[:upper:]'").read()
100 | APSSID = "EDISON-" + data[12:14] +"-" + data[15:17]
101 | return APSSID
102 |
103 | def _getAPSSID():
104 | ConnmanSettings = configparser.ConfigParser()
105 | ConnmanSettings.optionxform=str
106 | ConnmanSettings.read(CONNMAN_SETTINGS)
107 | APSSID = ConnmanSettings.get('WiFi', 'Tethering.Identifier', fallback='')
108 | APPassword = ConnmanSettings.get('WiFi', 'Tethering.Passphrase', fallback='')
109 |
110 | if APSSID == "":
111 | if APPassword == "":
112 | APPassword = os.popen("cat /factory/serial_number").read()
113 | subprocess.check_output("connmanctl tether wifi off '" + _getDefaultSSID() + "' '" + APPassword + "'", shell=True)
114 | return APSSID
115 |
116 | def _changeAPSSID(newName):
117 | ConnmanSettings = configparser.ConfigParser()
118 | ConnmanSettings.optionxform=str
119 | ConnmanSettings.read(CONNMAN_SETTINGS)
120 | APPassword = ConnmanSettings.get('WiFi', 'Tethering.Passphrase', fallback='')
121 | if APPassword == "":
122 | APPassword = os.popen("cat /factory/serial_number").read()
123 | subprocess.check_output("connmanctl tether wifi off '" + newName + "' '" + APPassword + "'", shell=True)
124 |
125 | def _changeAPPassword(newPass):
126 | subprocess.check_output("connmanctl tether wifi off '" + _getAPSSID() + "' '" + newPass + "'", shell=True)
127 |
128 | def _changeAPCredentials(newName, newPass):
129 | subprocess.check_output("connmanctl tether wifi off '" + newName + "' '" + newPass + "'", shell=True)
130 |
131 | def _getWiFiMode():
132 | modestr = ''
133 | try:
134 | modestr = subprocess.check_output('connmanctl technologies', shell=True)
135 | except subprocess.CalledProcessError:
136 | return "Err"
137 | except Exception as inst:
138 | return "Err"
139 |
140 | modestr = str(modestr, 'utf-8')
141 | modestr = "[Wifi]" + modestr.split('/net/connman/technology/wifi')[1].split('/net/connman/technology')[0].replace(' ','')
142 | Section = configparser.ConfigParser()
143 | Section.optionxform=str
144 | Section.read_string(modestr)
145 | if Section['Wifi']['Connected'] == 'True':
146 | return "Connected"
147 | if Section['Wifi']['Tethering'] == 'True':
148 | return "AP"
149 | if Section['Wifi']['Powered'] == 'True':
150 | return "Powered"
151 | return "Off"
152 |
153 | def _getWiredMode():
154 | modestr = ''
155 | try:
156 | modestr = subprocess.check_output('connmanctl technologies', shell=True)
157 | except subprocess.CalledProcessError:
158 | return "Err"
159 | except Exception as inst:
160 | return "Err"
161 |
162 | modestr = str(modestr, 'utf-8')
163 | if modestr.find("ethernet") == -1:
164 | return "None"
165 | modestr = "[Wired]" + modestr.split('/net/connman/technology/ethernet')[1].split('/net/connman/technology')[0].replace(' ','')
166 | Section = configparser.ConfigParser()
167 | Section.optionxform=str
168 | Section.read_string(modestr)
169 | if Section['Wired']['Connected'] == 'True':
170 | return "Connected"
171 | if Section['Wired']['Powered'] == 'True':
172 | return "Powered"
173 | return "Off"
174 |
175 | def _getBTMode():
176 | modestr = ''
177 | try:
178 | modestr = subprocess.check_output('connmanctl technologies', shell=True)
179 | except subprocess.CalledProcessError:
180 | return "Err"
181 | except Exception as inst:
182 | return "Err"
183 |
184 | modestr = str(modestr, 'utf-8')
185 | if modestr.find("bluetooth") == -1:
186 | return "None"
187 | modestr = "[Bluetooth]" + modestr.split('/net/connman/technology/bluetooth')[1].split('/net/connman/technology')[0].replace(' ','')
188 | Section = configparser.ConfigParser()
189 | Section.optionxform=str
190 | Section.read_string(modestr)
191 | if Section['Bluetooth']['Connected'] == 'True':
192 | return "Connected"
193 | if Section['Bluetooth']['Powered'] == 'True':
194 | return "Powered"
195 | return "Off"
196 |
197 | def _getGadgetMode():
198 | modestr = ''
199 | modestr = subprocess.run('lsusb', shell=False, stderr=subprocess.PIPE)
200 | modestr = str(modestr.stderr, 'utf-8')
201 | if modestr.find("root hub") >= 0:
202 | return "None"
203 |
204 | modestr = ''
205 | try:
206 | modestr = subprocess.check_output('connmanctl technologies', shell=True)
207 | except subprocess.CalledProcessError:
208 | return "Err"
209 | except Exception as inst:
210 | return "Err"
211 |
212 | modestr = str(modestr, 'utf-8')
213 | if modestr.find("gadget") == -1:
214 | return "None"
215 | modestr = "[Wired]" + modestr.split('/net/connman/technology/gadget')[1].split('/net/connman/technology')[0].replace(' ','')
216 | Section = configparser.ConfigParser()
217 | Section.optionxform=str
218 | Section.read_string(modestr)
219 | if Section['Wired']['Connected'] == 'True':
220 | return "Connected"
221 | if Section['Wired']['Powered'] == 'True':
222 | return "Powered"
223 | return "Off"
224 |
225 | def _setWiFiMode(Mode):
226 | CurrentMode = _getWiFiMode()
227 | if CurrentMode == 'Err':
228 | return
229 | if Mode == 'Off':
230 | if CurrentMode != 'Off':
231 | subprocess.check_output("connmanctl disable wifi", shell=True)
232 | elif Mode == 'Powered':
233 | if CurrentMode == 'Off':
234 | subprocess.check_output("connmanctl enable wifi", shell=True)
235 | elif CurrentMode == 'AP':
236 | subprocess.check_output("connmanctl tether wifi off", shell=True)
237 | elif Mode == 'AP':
238 | if CurrentMode == 'Off':
239 | subprocess.check_output("connmanctl enable wifi", shell=True)
240 | time.sleep(1)
241 | subprocess.check_output("connmanctl tether wifi on", shell=True)
242 | time.sleep(1)
243 | return
244 |
245 | def _setBTMode(Mode):
246 | CurrentMode = _getBTMode()
247 | if CurrentMode == 'Err':
248 | return
249 | if Mode == 'Off':
250 | if CurrentMode != 'Off':
251 | subprocess.check_output("connmanctl disable bluetooth", shell=True)
252 | elif Mode == 'Powered':
253 | if CurrentMode == 'Off':
254 | subprocess.check_output("connmanctl enable bluetooth", shell=True)
255 | time.sleep(1)
256 | return
257 |
258 | def _setGadgetMode(Mode):
259 | CurrentMode = _getGadgetMode()
260 | if CurrentMode == 'Err':
261 | return
262 | if Mode == 'Off':
263 | if CurrentMode != 'Off':
264 | subprocess.check_output("connmanctl disable gadget", shell=True)
265 | elif Mode == 'Powered':
266 | if CurrentMode == 'Off':
267 | subprocess.check_output("connmanctl enable gadget", shell=True)
268 | time.sleep(1)
269 | return
270 |
271 | def _changeRootPassword(newPass):
272 | echoSub = subprocess.Popen(["echo", "root:" + newPass], stdout=subprocess.PIPE)
273 | chpasswdSub = subprocess.Popen(["chpasswd"], stdin=echoSub.stdout, stdout=subprocess.PIPE)
274 | echoSub.stdout.close() # Allow echoSub to receive a SIGPIPE if chpasswdSub exits.
275 | chpasswdSub.communicate()[0]
276 |
277 | def _getHostName():
278 | return(str(subprocess.check_output('hostname', shell=True).strip(), 'utf-8'))
279 |
280 | def _getIFaceIP(iface):
281 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
282 | try:
283 | return socket.inet_ntoa(fcntl.ioctl(
284 | s.fileno(),
285 | 0x8915, # SIOCGIFADDR
286 | struct.pack('256s', iface[:15].encode('utf-8'))
287 | )[20:24])
288 | except OSError:
289 | return "None"
290 | finally:
291 | s.close()
292 |
293 | def _scanForNetworks():
294 | global lastScanned
295 | global _cachedServices
296 | connection = []
297 | now = datetime.datetime.now()
298 | if((now - lastScanned) > timedelta(seconds = 30)):
299 | lastScanned = now
300 | subprocess.check_output("connmanctl scan wifi", shell=True)
301 | connection.append(("", "Scanning, please wait 10 seconds", ""))
302 | else:
303 | connection = _getServices("wifi")
304 | _cachedServices = connection
305 | return connection
306 |
307 | def _getServices(type):
308 | data = subprocess.getoutput("connmanctl services | grep '" + type + "'")
309 | data = data.split("\n")
310 |
311 | connection = []
312 | for i in range(len(data)):
313 | (left, seperator, session) = data[i].rpartition(' ')
314 | ssid = left[4:].rstrip()
315 | flags = left[:4].rstrip()
316 | if ssid != "":
317 | connection.append((flags, ssid, session))
318 | return connection
319 |
320 | def _getPrivateService(type):
321 | data = subprocess.getoutput("connmanctl services | grep '" + type + "'")
322 | data = data.split("\n")
323 |
324 | for i in range(len(data)):
325 | (left, _, session) = data[i].rpartition(' ')
326 | ssid = left[4:].rstrip()
327 | if ssid == "":
328 | return session
329 |
330 | def _getCachedService(service):
331 | global _cachedServices
332 |
333 | for i in _cachedServices:
334 | if i[2] == service:
335 | return i[1]
336 |
337 | def _getIFace(service):
338 | data = subprocess.getoutput("connmanctl services '" + service[2] + "'| grep Ethernet")
339 | return re.compile(r"Interface=(\w+)").search(data)[1]
340 |
341 | def _selectNetwork(service):
342 | data = subprocess.getoutput("connmanctl connect '" + service + "'")
343 | if data.startswith("Error") and not data.endswith("In progress"):
344 | print(text_colors.RED + data + text_colors.END)
345 | return False
346 | else:
347 | print(text_colors.GREEN + data + text_colors.END)
348 | return True
349 |
350 | def _store(WiFi_Network, WiFi_Name, WiFi_Passphrase, WiFi_Identity=None):
351 | ConnmanServices = configparser.ConfigParser()
352 | ConnmanServices.optionxform=str
353 | ConnmanServices.read(CONNMAN_SERVICES)
354 | service = WiFi_Network
355 | service.replace(" ", "")
356 | print(service)
357 | if ConnmanServices.get("service_" + service, "Name", fallback="") == "":
358 | ConnmanServices["service_" + service] = {}
359 | if WiFi_Passphrase != "!@#$%^&*":
360 | ConnmanServices["service_" + service]["Type"] = "wifi"
361 | ConnmanServices["service_" + service]["Name"] = WiFi_Name
362 | ConnmanServices["service_" + service]["SSID"] = WiFi_Name.encode("utf-8").hex()
363 | if WiFi_Passphrase is not None:
364 | ConnmanServices["service_" + service]["Passphrase"] = WiFi_Passphrase
365 | if WiFi_Identity is not None:
366 | ConnmanServices["service_" + service]["Identity"] = WiFi_Identity
367 | with open(CONNMAN_SERVICES, 'w') as configfile:
368 | ConnmanServices.write(configfile)
369 |
370 | # Main Functions
371 | #######################################
372 | def _getch():
373 | fd = sys.stdin.fileno()
374 |
375 | oldterm = termios.tcgetattr(fd)
376 | newattr = termios.tcgetattr(fd)
377 | newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
378 | termios.tcsetattr(fd, termios.TCSANOW, newattr)
379 |
380 | try:
381 | while 1:
382 | try:
383 | c = sys.stdin.read(1)
384 | break
385 | except IOError: pass
386 | finally:
387 | termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
388 | return c
389 |
390 | def _getPassword(prompt):
391 | stdout.write(prompt)
392 | stdout.flush()
393 | pw = ""
394 |
395 | while 1:
396 | c = _getch()
397 | if c == '\r' or c == '\n':
398 | break
399 | if c == '\003':
400 | raise KeyboardInterrupt
401 | if c == '\x08' or c == '\x7f':
402 | if len(pw):
403 | pw = pw[:-1]
404 | stdout.write('\x08')
405 | stdout.write('\x20')
406 | stdout.write('\x08')
407 | else:
408 | pw = pw + c
409 | stdout.write("*")
410 | stdout.flush()
411 | stdout.write('\r')
412 | stdout.write('\n')
413 | return pw
414 |
415 | def _verified(selection):
416 | verify = input("Is " + text_colors.MAGENTA + selection + text_colors.END + " correct? " + text_colors.YELLOW + "[Y or N]" + text_colors.END + ": ")
417 | if verify == "Y" or verify == "y":
418 | return 1
419 | elif verify == "N" or verify == "n":
420 | return 0
421 | else:
422 | while 1:
423 | verify = input("Please enter either " + text_colors.YELLOW + "[Y or N]" + text_colors.END + ": ")
424 | if verify == "Y" or verify == "y":
425 | return 1
426 | elif verify == "N" or verify == "n":
427 | return 0
428 |
429 | def reset(stage):
430 | subprocess.call("clear", shell=True)
431 | print(text_colors.CYAN + "\nConfigure Edison: " + stage + "\n" + text_colors.END)
432 |
433 | def setEdisonHostname():
434 | while 1:
435 | name = input("Give this Edison a unique name.\nThis will be used for the access point SSID and mDNS address.\nMake it at least five characters long (leave empty to skip): ")
436 | if (WSREGEX.search(name)):
437 | print("")
438 | print('Hostname must not contain whitespaces. Please try again.')
439 | print("")
440 | elif (len(name) == 0):
441 | print("Skipping name change...")
442 | break
443 | elif (len(name) > 4):
444 | if _verified(name):
445 | print("")
446 | break
447 | else:
448 | print("")
449 | else:
450 | print("")
451 | print('\"' + name + '\" is too short. Please try again.')
452 | print("")
453 |
454 | if len(name) > 0:
455 | changeName(name)
456 |
457 | def setEdisonPassword():
458 | while 1:
459 | password = _getPassword("Enter a new password (leave empty to abort)\nThis will be used to connect to the access point and login to the device.\nPassword: \t")
460 | if (password == _getPassword("Please enter the password again: \t")):
461 | if (WSREGEX.search(password)):
462 | print("")
463 | print('The device password must not contain whitespaces. Please try again.')
464 | print("")
465 | elif len(password) == 0:
466 | print("Skipping password change.")
467 | return
468 | elif len(password) < 8 or len(password) > 63:
469 | print("")
470 | print("The device password must be between 8 and 63 characters long. Please try again.")
471 | print("")
472 | else:
473 | break
474 | else:
475 | print("")
476 | print("The passwords do not match. Please try again.")
477 | print("")
478 |
479 | changePassword(password)
480 | print("The device password has been changed.\n")
481 |
482 | def _selectWifiMenu(ssid_keys):
483 | i = 2
484 | print("0 :\tRescan for networks")
485 | print("1 :\tExit WiFi Setup")
486 | print("2 :\tManually input a hidden SSID")
487 | for ssid in ssid_keys:
488 | i = i + 1
489 | print(i, ":\t", ssid[1])
490 |
491 | print("")
492 | choice = -1
493 | while 1:
494 | try:
495 | if i == 2:
496 | choice = int(input("\nEnter 0 to rescan for networks.\nEnter 1 to exit.\nEnter 2 to input a hidden network SSID: "))
497 | elif i == 3:
498 | choice = int(input("\nEnter 0 to rescan for networks.\nEnter 1 to exit.\nEnter 2 to input a hidden network SSID.\nEnter 3 to choose %s: " % ssid_keys[0]))
499 | else:
500 | choice = int(input("\nEnter 0 to rescan for networks.\nEnter 1 to exit.\nEnter 2 to input a hidden network SSID.\nEnter a number between 3 to %s to choose one of the listed network SSIDs: " % i))
501 | except TypeError:
502 | choice = -1
503 | except ValueError:
504 | choice = -1
505 |
506 | if choice == 0:
507 | break
508 | elif choice == 1:
509 | sys.exit(0)
510 | elif choice == 2:
511 | break
512 | elif choice > 2 and choice <= i and _verified(ssid_keys[choice-3][1]):
513 | break
514 | return choice
515 |
516 | def _getNetworkIdentity():
517 | return input("Please enter the network username: ")
518 |
519 | def _getNetworkPassword():
520 | pw = ''
521 | while len(pw) == 0:
522 | pw = _getPassword("What is the network password?: ")
523 | return pw
524 |
525 | def _configureHiddenNetwork(ssid):
526 | service = _getPrivateService('wifi')
527 |
528 | print('''
529 | 0: OPEN
530 | 1: WEP
531 | 2: WPA-Personal (PSK)
532 | 3: WPA-Enterprise (EAP)
533 | ''')
534 | while 1:
535 | try:
536 | security = int(input("Select the type of security [0 to 3]: "))
537 | except TypeError:
538 | security = -1
539 | except ValueError:
540 | security = -1
541 |
542 | if security == 0:
543 | _store(service, ssid, None)
544 | break
545 | elif security == 1:
546 | password = ''
547 | while len(password) != 5 and len(password) != 13:
548 | print("Password must be either 5 or 13 characters.")
549 | password = _getNetworkPassword()
550 | _store(service, ssid, password)
551 | break
552 | elif security == 2:
553 | password = ''
554 | while len(password) < 8 or len(password) > 63:
555 | print("Password must be between 8 and 63 characters.")
556 | password = _getNetworkPassword()
557 | _store(service, ssid, password)
558 | break
559 | elif security == 3:
560 | identity = _getNetworkIdentity()
561 | password = _getNetworkPassword()
562 | _store(service, ssid, password, identity)
563 | break
564 | else:
565 | print("Invalid input.")
566 |
567 | return _selectNetwork(service)
568 |
569 | def _configureNetwork(choice,ssid_keys):
570 | service = ssid_keys[choice-3][2]
571 |
572 | if service.endswith("_none"):
573 | return _selectNetwork(service)
574 | elif service.endswith("_wep"):
575 | identity = None
576 | password = ''
577 | while len(password) != 5 and len(password) != 13:
578 | print("Password must be either 5 or 13 characters.")
579 | password = _getNetworkPassword()
580 | elif service.endswith("_psk") or service.endswith("_wpa") or service.endswith("_rsn"):
581 | identity = None
582 | password = ''
583 | while len(password) < 8 or len(password) > 63:
584 | print("Password must be between 8 and 63 characters.")
585 | password = _getNetworkPassword()
586 | elif service.endswith("_ieee8021x"):
587 | identity = _getNetworkIdentity()
588 | password = _getNetworkPassword()
589 |
590 | _store(service, ssid_keys[choice-3][1], password, identity)
591 | return _selectNetwork(service)
592 |
593 | def configureNetworkAP(changewifi):
594 | ssid = changewifi[0]
595 | password = changewifi[1]
596 |
597 | if WSREGEX.search(ssid) or WSREGEX.search(password):
598 | print("The SSID and the password must not contain whitespaces.")
599 | return False
600 | if len(ssid) == 0:
601 | print("SSID must not be empty.")
602 | return False
603 | if len(password) < 8 or len(password) > 63:
604 | print("Password must be between 8 and 63 characters.")
605 | return False
606 |
607 | _changeAPCredentials(ssid, password)
608 | return True
609 |
610 | def _checkNetwork():
611 | i = 60
612 | while 1:
613 | waiting = "Connecting: %s seconds left \r" % i
614 | stdout.write(waiting)
615 | stdout.flush()
616 | time.sleep(1)
617 | address = _getIFaceIP("wlan0")
618 | if address != 'None':
619 | print("Done. Please connect your laptop or PC to the same network as this device and go to " + \
620 | text_colors.CYAN + "http://" + address + text_colors.END + " or " + text_colors.CYAN + \
621 | "http://" + _getHostName() + ".local" + text_colors.END + \
622 | " in your browser.")
623 | break
624 | if i == 0:
625 | print("Not connected. Something went wrong.")
626 | break
627 | i = i-1
628 |
629 | def connectNetwork():
630 | ssid = ""
631 | _setWiFiMode("Powered")
632 |
633 | while 1:
634 | reset("WiFi Connection")
635 |
636 | while True:
637 | ssid_keys = _scanForNetworks()
638 | if len(ssid_keys) > 0 and ssid_keys[0][1] == "Scanning, please wait 10 seconds":
639 | print(ssid_keys[0][1])
640 | time.sleep(10)
641 | else:
642 | break
643 |
644 | choice = _selectWifiMenu(ssid_keys)
645 |
646 | #choice is validated within selectNetwork.
647 | if choice == 2:
648 | while 1:
649 | ssid = input("Please enter the hidden network SSID: ")
650 | if _verified(ssid):
651 | break
652 | if _configureHiddenNetwork(ssid):
653 | break
654 | elif choice > 2:
655 | if _configureNetwork(choice, ssid_keys):
656 | break
657 |
658 | # for error messages
659 | time.sleep(5)
660 |
661 | _checkNetwork()
662 | disableOneTimeSetup(True)
663 |
664 | def showWiFiIP():
665 | if _getWiFiMode() == 'AP':
666 | return _getIFaceIP("tether")
667 | ipstr = _getIFaceIP('wlan0')
668 | if ipstr == 'None':
669 | print("No IP address found. Device not connected?")
670 | return ipstr
671 |
672 | def showWiFiMode():
673 | Mode = _getWiFiMode()
674 | if Mode == 'Err':
675 | print("Connman error")
676 | return Mode
677 |
678 | def isRestartWithAPSet():
679 | try:
680 | ret_value = subprocess.call("mkdir -p /update", shell=True)
681 | if ret_value != 0:
682 | print("Could not create destination folder.")
683 | return False
684 | except Exception as inst:
685 | print("Could not create destination folder.")
686 | print(type(inst), file=sys.stderr)
687 | print(inst, file=sys.stderr)
688 | return False
689 |
690 | try:
691 | ret_value = subprocess.call("losetup -o 8192 /dev/loop0 /dev/disk/by-partlabel/update", shell=True)
692 | if ret_value != 0:
693 | print("Could not setup loop device")
694 | return False
695 | except Exception as inst:
696 | print("Could not setup loop device")
697 | print(type(inst), file=sys.stderr)
698 | print(inst, file=sys.stderr)
699 | return False
700 |
701 | try:
702 | ret_value = subprocess.call("mount /dev/loop0 /update", shell=True)
703 | if ret_value != 0:
704 | print("Could not perform mount operation.")
705 | return False
706 | except Exception as inst:
707 | print("Could not perform mount operation.")
708 | print(type(inst), file=sys.stderr)
709 | print(inst, file=sys.stderr)
710 | return False
711 |
712 | if os.path.isfile("/update" + HOST_AP_MODE_FILE):
713 | ap_mode = True
714 | else:
715 | ap_mode = False
716 | try:
717 | ret_value = subprocess.call("umount /update", shell=True)
718 | if ret_value != 0:
719 | print("Could not perform umount operation.")
720 | return False
721 | except Exception as inst:
722 | print("Could not perform umount operation.")
723 | print(type(inst), file=sys.stderr)
724 | print(inst, file=sys.stderr)
725 | return False
726 | try:
727 | ret_value = subprocess.call("rmdir /update", shell=True)
728 | if ret_value != 0:
729 | print("Could not delete destination folder.")
730 | return False
731 | except Exception as inst:
732 | print("Could not delete destination folder.")
733 | print(type(inst), file=sys.stderr)
734 | print(inst, file=sys.stderr)
735 | return False
736 |
737 | return ap_mode
738 |
739 | def _decideToConnect():
740 | while 1:
741 | verify = input("Do you want to set up wifi? " + text_colors.YELLOW + "[Y or N]" + text_colors.END + ": ")
742 | if verify == "y" or verify == "Y":
743 | return 1
744 | elif verify == "n" or verify == "N":
745 | return 0
746 | else:
747 | print("I need Y or N as a reply.")
748 |
749 | def full():
750 | reset("Device Password")
751 | setEdisonPassword()
752 | reset("Device Name")
753 | setEdisonHostname()
754 | if _decideToConnect():
755 | connectNetwork()
756 | else:
757 | print("Done.\n")
758 |
759 | def enableOneTimeSetup(persist):
760 | subprocess.call("systemctl restart blink-led", shell=True)
761 | _setWiFiMode("Off")
762 |
763 | print("Restarting WiFi access point. Please wait until the AP appears...\n")
764 |
765 | if persist:
766 | subprocess.call("systemctl enable blink-led &> /dev/null", shell=True)
767 |
768 | _setWiFiMode("AP")
769 | myssid = _getAPSSID()
770 |
771 | print("From your PC or laptop, connect to the", "'" + myssid + "' network ")
772 | print("and visit", "'" + _getHostName() + ".local' in the browser")
773 |
774 | def disableOneTimeSetup(persist):
775 | subprocess.call("systemctl stop blink-led &> /dev/null", shell=True)
776 | _setWiFiMode("Off")
777 |
778 | if persist:
779 | subprocess.call("systemctl disable blink-led &> /dev/null", shell=True)
780 |
781 | _setWiFiMode("Powered")
782 |
783 | def toggleOneTimeSetup(persist):
784 | if _getWiFiMode() == "AP":
785 | disableOneTimeSetup(persist)
786 | else:
787 | enableOneTimeSetup(persist)
788 |
789 | def changePassword(newPass):
790 | if WSREGEX.search(newPass):
791 | print("New password contains whitespaces. Ignoring")
792 | return
793 |
794 | _changeRootPassword(newPass)
795 | if len(newPass) > 0:
796 | _changeAPPassword(newPass)
797 |
798 | if (not os.path.isfile(STATE_DIR + "/password-setup.done")):
799 | pass_done = open(STATE_DIR + "/password-setup.done", "w")
800 | pass_done.write("Indicates that password has been changed via oobe.\n")
801 | pass_done.close()
802 | print("First-time root password setup complete. Enabling SSH on WiFi interface.")
803 | subprocess.call("sed -i 's/^BindToDevice=/# BindToDevice=/g' /lib/systemd/system/sshd.socket ; sync ; systemctl daemon-reload; systemctl restart sshd.socket", shell=True)
804 |
805 | def changeName(newName):
806 | if _checkName(newName) < 0:
807 | print("Invalid new name. Ignoring")
808 | return
809 | _changeHostName(newName)
810 | _changeAPSSID(newName)
811 |
812 | def showNames():
813 | hostname = _getHostName()
814 | ssid = _getAPSSID()
815 | default_ssid = _getDefaultSSID()
816 | print('{"hostname": "' + hostname + '", "ssid": "' + ssid + '", "default_ssid": "' + default_ssid + '"}')
817 |
818 | # Web Interface
819 | #######################################
820 | @route('/')
821 | def main_form():
822 | print(request['REMOTE_ADDR'])
823 | return template('index' )
824 |
825 | @route('/', method='POST')
826 | def do_main_form():
827 | control = request.forms.get('button')
828 | print(control)
829 | redirect('/')
830 |
831 | @route('/activate')
832 | def activate():
833 | global Settings
834 | if Settings.HostName.Changed and Settings.HostName.Valid:
835 | hostname = Settings.HostName.New
836 | else:
837 | hostname = _getHostName()
838 | return template('activate', hostname = hostname, \
839 | nameChange = Settings.HostName.Changed, wiredChange = Settings.Wired.Changed, \
840 | btChange = Settings.BT.Changed, wifiChange = Settings.Wifi.Changed, \
841 | apChange = Settings.AP.Changed)
842 |
843 | @route('/activate', method='POST')
844 | def do_activate_form():
845 | global Settings
846 | if Settings.HostName.Changed and Settings.HostName.Valid:
847 | _changeHostName(Settings.HostName.New)
848 | Settings.HostName.Changed = False
849 | if Settings.Wired.Changed:
850 | if Settings.Wired.NewMode == "checked":
851 | _setGadgetMode("Powered")
852 | else:
853 | _setGadgetMode("Off")
854 | Settings.Wired.Changed = False
855 | if Settings.BT.Changed:
856 | if Settings.BT.NewMode == "checked":
857 | new_BTMode = "Powered"
858 | else:
859 | new_BTMode = "Off"
860 | _setBTMode(new_BTMode)
861 | BTMode = _getBTMode()
862 | if Settings.BT.Name is not None and BTMode == "Powered" or BTMode == "Connected":
863 | _selectNetwork(Settings.BT.Name)
864 | Settings.BT.Changed = False
865 | if Settings.Wifi.Changed:
866 | if Settings.Wifi.NewMode == "checked":
867 | new_WiFiMode = "Powered"
868 | else:
869 | new_WiFiMode = "Off"
870 | _setWiFiMode(new_WiFiMode)
871 | WiFiMode = _getWiFiMode()
872 | if Settings.Wifi.Name is not None and WiFiMode == "Powered" or WiFiMode == "Connected":
873 | WiFi_ServiceName = _getCachedService(Settings.Wifi.Name)
874 | _store(Settings.Wifi.Name, WiFi_ServiceName, Settings.Wifi.Passphrase)
875 | Settings.Wifi.Passphrase = ""
876 | _selectNetwork(Settings.Wifi.Name)
877 | Settings.Wifi.Changed = False
878 | if Settings.AP.Changed:
879 | if Settings.AP.Name != "":
880 | _changeAPSSID(Settings.AP.Name)
881 | if Settings.AP.Passphrase != "":
882 | _changeAPPassword(Settings.AP.Passphrase)
883 | Settings.AP.Passphrase = ""
884 | if Settings.AP.Enabled:
885 | enableOneTimeSetup(False)
886 | else:
887 | disableOneTimeSetup(False)
888 | Settings.AP.Changed = False
889 |
890 | redirect('/name')
891 |
892 | @route('/name')
893 | def name_form():
894 | global Settings
895 | Settings.HostName.Old = _getHostName()
896 | if not Settings.HostName.Changed:
897 | hostname = Settings.HostName.Old
898 | tooltip = "Names consist of 'a-z', '0-9', '-'"
899 | checked = ""
900 | else:
901 | hostname = Settings.HostName.New
902 | tooltip = Settings.HostName.Tooltip
903 | if Settings.HostName.Valid:
904 | checked = "font-weight: bold; "
905 | else:
906 | checked = "border:3px; border-style:solid; border-color:red; padding: 1em; "
907 |
908 | return template('name', hostname_checked = checked, hostname_tooltip = tooltip, \
909 | hostname = hostname)
910 |
911 | @route('/name', method='POST')
912 | def do_name_form():
913 | global Settings
914 | Settings.HostName.New = request.forms.get('hostname')
915 | Settings.HostName.Changed = False
916 | if Settings.HostName.New != Settings.HostName.Old:
917 | Settings.HostName.Changed = True
918 | # update done in do_activate_form()
919 | Settings.HostName.Valid = False
920 | check = _checkName(Settings.HostName.New)
921 | if check == 0:
922 | Settings.HostName.Valid = True
923 | Settings.HostName.Tooltip = "Valid host name"
924 | elif check == -1:
925 | Settings.HostName.Tooltip = "Incorrect length"
926 | elif check == -2:
927 | Settings.HostName.Tooltip = "Can not start or end with '-'"
928 | elif check == -3:
929 | Settings.HostName.Tooltip = "Can not contain other then 'a-z', '0-9', '-'"
930 | redirect('/name')
931 |
932 | @route('/wired')
933 | def wired_form():
934 | global Settings
935 | Host_IP = request['REMOTE_ADDR']
936 | Net = _getGadgetMode()
937 | if Net == "None":
938 | Net = _getWiredMode()
939 | if Net == "None":
940 | Settings.Wired.Type = "No ethernet available"
941 | Settings.Wired.Mode = ""
942 | elif Net == "Powered":
943 | Settings.Wired.Type = "Ethernet dongle"
944 | Settings.Wired.Mode = "checked"
945 | elif Net == "Connected":
946 | Settings.Wired.Type = "Ethernet dongle"
947 | Settings.Wired.Mode = "checked"
948 | else:
949 | Settings.Wired.Type = "An error has occured"
950 | Settings.Wired.Mode = ""
951 | elif Net == "Powered":
952 | Settings.Wired.Type = "Ethernet over USB (OTG)"
953 | Settings.Wired.Mode = "checked"
954 | elif Net == "Connected":
955 | Settings.Wired.Type = "Ethernet over USB (OTG)"
956 | Settings.Wired.Mode = "checked"
957 | elif Net == "Off":
958 | Settings.Wired.Type = "Ethernet over USB (OTG)"
959 | Settings.Wired.Mode = ""
960 | else:
961 | Settings.Wired.Type = "An error has occured"
962 | Settings.Wired.Mode = ""
963 |
964 | connections = _getServices("Wired")
965 | if connections:
966 | ConnState = connections[0][0]
967 | else:
968 | ConnState = ""
969 | Wired_State = ""
970 |
971 | Settings.Wired.IP = "Unknown"
972 | if Net == "Connected":
973 | if "O" in ConnState:
974 | Wired_State = "Primary connection verified On Line"
975 | elif "R" in ConnState:
976 | Wired_State = "Fall back connection standby"
977 | Settings.Wired.IP = _getIFaceIP(_getIFace(connections[0]))
978 | elif Net == "Powered":
979 | if "*" in ConnState:
980 | Wired_State = "Connection available"
981 | else:
982 | Wired_State = "Not plugged"
983 | Settings.Wired.IP = "Unconnected"
984 |
985 | return template('wired', Wired_Type = Settings.Wired.Type, Wired_IP = Settings.Wired.IP, \
986 | Wired_Mode = Settings.Wired.NewMode if Settings.Wired.Changed else Settings.Wired.Mode, \
987 | Wired_State = Wired_State, Host_IP = Host_IP)
988 |
989 | @route('/wired', method='POST')
990 | def do_wired_form():
991 | global Settings
992 | Settings.Wired.NewMode = request.forms.get('Wired_Mode', '')
993 | Settings.Wired.Changed = False
994 | if Settings.Wired.NewMode != Settings.Wired.Mode:
995 | Settings.Wired.Changed = True
996 | # update done in do_activate_form()
997 | redirect('/wired')
998 |
999 | @route('/bt')
1000 | def bt_form():
1001 | global Settings
1002 | Host_IP = request['REMOTE_ADDR']
1003 | Net = _getBTMode()
1004 |
1005 | BT_Mode = ""
1006 | if Net == "Powered" or Net == "Connected":
1007 | BT_Mode = "checked"
1008 |
1009 | connections = _getServices("bluetooth")
1010 | if connections:
1011 | ConnState = connections[0][0]
1012 | else:
1013 | ConnState = ""
1014 | BT_State = ""
1015 |
1016 | Settings.BT.IP = "Unknown"
1017 | if Net == "Connected":
1018 | if "O" in ConnState:
1019 | BT_State = "Primary connection verified On Line"
1020 | elif "R" in ConnState:
1021 | BT_State = "Fall back connection standby"
1022 | Settings.BT.IP = _getIFaceIP(_getIFace(connections[0]))
1023 | elif Net == "Powered":
1024 | if "*" in ConnState:
1025 | BT_State = "Connection available"
1026 | else:
1027 | BT_State = "Not plugged"
1028 | Settings.BT.IP = "Unconnected"
1029 |
1030 | return template('bt', rows = connections, BT_IP = Settings.BT.IP, \
1031 | BT_Mode = Settings.BT.NewMode if Settings.BT.Changed else BT_Mode, \
1032 | BT_State = BT_State, Host_IP = Host_IP)
1033 |
1034 | @route('/bt', method='POST')
1035 | def do_bt_form():
1036 | global Settings
1037 | Settings.BT.NewMode = request.forms.get('BT_Mode', '')
1038 | Settings.BT.Name = request.forms.get('newbts')
1039 |
1040 | Settings.BT.Changed = True
1041 | # update done in do_activate_form()
1042 | redirect('/bt')
1043 |
1044 | @route('/wireless')
1045 | @route('/wirelessr')
1046 | def wireless_form():
1047 | global Settings
1048 | Host_IP = request['REMOTE_ADDR']
1049 | WiFi_mode = ""
1050 | Settings.Wifi.IP = "WiFi is currently not powered"
1051 | WiFiMode = _getWiFiMode()
1052 | WiFi_State = ""
1053 | ReloadMode = False
1054 |
1055 | if WiFiMode == "Connected":
1056 | WiFi_mode = "checked"
1057 | Settings.Wifi.IP = _getIFaceIP("wlan0")
1058 | elif WiFiMode == "Powered":
1059 | Settings.Wifi.IP = "WiFi is powered but inactive"
1060 |
1061 | connections = []
1062 | if WiFiMode == "Powered" or WiFiMode == "Connected":
1063 | connections = _scanForNetworks()
1064 | print(connections)
1065 | if len(connections) > 0 and connections[0][1] == "Scanning, please wait 10 seconds":
1066 | WiFi_State = "Scanning"
1067 | ReloadMode = True
1068 | else:
1069 | if WiFiMode == "Connected":
1070 | ConnState = connections[0][0]
1071 | if "O" in ConnState:
1072 | WiFi_State = "Primary connection verified On Line"
1073 | elif "R" in ConnState:
1074 | WiFi_State = "Fall back connection standby"
1075 |
1076 | if ReloadMode == True:
1077 | return template('wirelessr',
1078 | WiFi_mode = Settings.Wifi.NewMode if Settings.Wifi.Changed else WiFi_mode,
1079 | rows = connections, WiFi_IP = Settings.Wifi.IP, WiFi_Passphrase = "!@#$%^&*",
1080 | WiFi_State = WiFi_State, Host_IP = Host_IP)
1081 | else:
1082 | return template('wireless',
1083 | WiFi_mode = Settings.Wifi.NewMode if Settings.Wifi.Changed else WiFi_mode,
1084 | rows = connections, WiFi_IP = Settings.Wifi.IP, WiFi_Passphrase = "!@#$%^&*",
1085 | WiFi_State = WiFi_State, Host_IP = Host_IP)
1086 |
1087 | @route('/wireless', method='POST')
1088 | def do_wireless_form():
1089 | global Settings
1090 | Settings.Wifi.NewMode = request.forms.get('WiFi_mode', '')
1091 | Settings.Wifi.Name = request.forms.get('newwifis')
1092 | Settings.Wifi.Passphrase = request.forms.get('WiFipassphrase')
1093 |
1094 | Settings.Wifi.Changed = True
1095 | Settings.AP.Changed = False # AP and wifi activation are mutually exclusive
1096 | # update done in do_activate_form()
1097 | redirect('/wireless')
1098 |
1099 | @route('/ap')
1100 | def ap_form():
1101 | global Settings
1102 |
1103 | AP_name = _getAPSSID()
1104 | hostname = _getHostName()
1105 |
1106 | if _getWiFiMode() == "AP":
1107 | AP_mode = "checked"
1108 | AP_IP = "Access Point " + AP_name + " is currently on IP address: " + _getIFaceIP("tether")
1109 | else:
1110 | AP_mode = ""
1111 | AP_IP = "Access Point is currently OFF"
1112 |
1113 | return template('ap', hostname = hostname,
1114 | AP_mode = Settings.AP.NewMode if Settings.AP.Changed else AP_mode,
1115 | AP_name = Settings.AP.Name if Settings.AP.Changed else AP_name,
1116 | AP_passphrase = "", AP_IP = AP_IP)
1117 |
1118 | @route('/ap', method='POST')
1119 | def do_ap_form():
1120 | global Settings
1121 | Settings.AP.NewMode = request.forms.get('AP_mode', '')
1122 | AP_name = request.forms.get('AP_name')
1123 | AP_passphrase = request.forms.get('AP_passphrase')
1124 |
1125 | Settings.AP.Changed = False
1126 | if _getWiFiMode() != "AP" and Settings.AP.NewMode == "checked":
1127 | Settings.AP.Changed = True
1128 | Settings.AP.Enabled = True
1129 | # update done in do_activate_form()
1130 |
1131 | if AP_name != Settings.AP.Name:
1132 | if WSREGEX.search(AP_name):
1133 | return "The SSID must not contain whitespaces."
1134 | if len(AP_name) == 0:
1135 | return "The SSID must not be empty."
1136 | Settings.AP.Name = AP_name
1137 | if AP_passphrase != "":
1138 | if WSREGEX.search(AP_passphrase):
1139 | return "The passphrase must not contain whitespaces."
1140 | if len(AP_passphrase) < 8 or len(AP_passphrase) > 63:
1141 | return "The passphrase must be between 8 and 63 characters."
1142 | Settings.AP.Passphrase = AP_passphrase
1143 | AP_passphrase = None
1144 | elif _getWiFiMode() == "AP" and Settings.AP.NewMode == "":
1145 | Settings.AP.Changed = True
1146 | Settings.AP.Enabled = False
1147 | # update done in do_activate_form()
1148 | if Settings.AP.Changed:
1149 | Settings.Wifi.Changed = False # AP and wifi activation are mutually exclusive
1150 |
1151 | redirect('/ap')
1152 |
1153 | @route('/img/')
1154 | def send_image(filename):
1155 | return static_file(filename, root='img', mimetype='image/png')
1156 |
1157 | @route('/img/')
1158 | def send_image(filename):
1159 | return static_file(filename, root='img', mimetype='image/svg+xml')
1160 |
1161 | @route('/css/')
1162 | def send_static(filename):
1163 | return static_file(filename, root='css')
1164 |
1165 | @route('/script/')
1166 | def send_static(filename):
1167 | return static_file(filename, root='script')
1168 |
1169 | @route('/')
1170 | def send_image(filename):
1171 | return static_file(filename, root='img', mimetype='image/x-icon')
1172 |
1173 | # Main
1174 | #######################################
1175 | def main():
1176 | global lastScanned
1177 | global Settings
1178 | lastScanned = datetime.datetime.min
1179 | Settings = classSettings()
1180 |
1181 | parser = argparse.ArgumentParser(prog='configure_edison')
1182 |
1183 | parser.add_argument('--restartWithAP', dest='restartwithap', help=argparse.SUPPRESS, action='store_true', default=False)
1184 | parser.add_argument('--persist', dest='persist', help=argparse.SUPPRESS, action='store_true', default=False)
1185 |
1186 | root_group = parser.add_mutually_exclusive_group()
1187 |
1188 | group_interactive = root_group.add_mutually_exclusive_group()
1189 | group_interactive.add_argument('--setup', dest='setup', help='Goes through changing the device name, password, and wifi options', action='store_true', default=False)
1190 | group_interactive.add_argument('--name', dest='name', help='Changes the device name', action='store_true', default=False)
1191 | group_interactive.add_argument('--password', dest='password', help='Changes the device password', action='store_true', default=False)
1192 | group_interactive.add_argument('--wifi', dest='wifi', help='Changes the wifi options', action='store_true', default=False)
1193 |
1194 | group_non_interactive = root_group.add_mutually_exclusive_group()
1195 | group_non_interactive.add_argument('--isRestartWithAPSet', dest='isrestartwithapset', help=argparse.SUPPRESS, action='store_true', default=False)
1196 | group_non_interactive.add_argument('--showWiFiIP', dest='showwifiip', help='IP address associated with the wireless interface', action='store_true', default=False)
1197 | group_non_interactive.add_argument('--showWiFiMode', dest='showwifimode', help='Show current mode for the wireless interface', action='store_true', default=False)
1198 | group_non_interactive.add_argument('--disableOneTimeSetup', dest='disableonetimesetup', help='Disable one-time setup with WiFi access point and enable WiFi client mode. \
1199 | Append --persist to retain this setting after reboot', action='store_true', default=False)
1200 | group_non_interactive.add_argument('--enableOneTimeSetup', dest='enableonetimesetup', help='Enable one-time setup with WiFi access point and disable WiFi client mode. \
1201 | Append --persist to retain this setting after reboot', action='store_true', default=False)
1202 | group_non_interactive.add_argument('--toggleOneTimeSetup', dest='toggleonetimesetup', help='Switch between one-time setup with WiFi access point and WiFi client mode, and visa-versa. \
1203 | Append --persist to retain this setting after reboot', action='store_true', default=False)
1204 | group_non_interactive.add_argument('--changePassword', metavar='password', dest='changepassword', const='', help=argparse.SUPPRESS, nargs='?')
1205 | group_non_interactive.add_argument('--changeName', metavar='name', dest='changename', help=argparse.SUPPRESS, nargs=1)
1206 | group_non_interactive.add_argument('--changeWiFi', metavar='SSID password', dest='changewifi', help=argparse.SUPPRESS, nargs=2)
1207 | group_non_interactive.add_argument('--showNames', dest='shownames', help='Show device name and SSID', action='store_true', default=False)
1208 | group_non_interactive.add_argument('--webInterface', dest='webInterface', help='Start a web server', action='store_true', default=False)
1209 |
1210 | if len(sys.argv)==1:
1211 | parser.print_help()
1212 | sys.exit(1)
1213 |
1214 | args = parser.parse_args()
1215 |
1216 | if args.name:
1217 | reset("Device Name")
1218 | setEdisonHostname()
1219 |
1220 | if args.password:
1221 | reset("Device Password")
1222 | setEdisonPassword()
1223 |
1224 | if args.wifi:
1225 | connectNetwork()
1226 | if not os.path.isfile(STATE_DIR + "/password-setup.done"):
1227 | print("Warning: SSH is not yet enabled on the wireless interface. To enable SSH access to this device via wireless run configure_edison --password first.")
1228 |
1229 | if args.setup:
1230 | full()
1231 |
1232 | if args.shownames:
1233 | showNames()
1234 |
1235 | if args.isrestartwithapset:
1236 | print(isRestartWithAPSet())
1237 |
1238 | if args.changepassword != None:
1239 | changePassword(args.changepassword)
1240 |
1241 | if args.changename != None:
1242 | changeName(args.changename[0])
1243 |
1244 | if args.showwifiip:
1245 | print(showWiFiIP())
1246 |
1247 | if args.showwifimode:
1248 | print(showWiFiMode())
1249 |
1250 | if args.enableonetimesetup:
1251 | enableOneTimeSetup(args.persist)
1252 |
1253 | if args.disableonetimesetup:
1254 | disableOneTimeSetup(args.persist)
1255 |
1256 | if args.toggleonetimesetup:
1257 | toggleOneTimeSetup(args.persist)
1258 |
1259 | if args.changewifi:
1260 | if configureNetworkAP(args.changewifi):
1261 | enableOneTimeSetup(False)
1262 |
1263 | if args.webInterface:
1264 | os.chdir(os.path.dirname('/usr/lib/edison_config_tools/public/'))
1265 | debug(False)
1266 | run(host='0.0.0.0', port=80)
1267 |
1268 | #print 'restartwithap = ',args.restartwithap
1269 | #print 'persist = ',args.persist
1270 | #print 'setup = ',args.setup
1271 | #print 'name = ',args.name
1272 | #print 'password = ',args.password
1273 | #print 'wifi = ',args.wifi
1274 |
1275 | #print 'showwifiip = ',args.showwifiip
1276 | #print 'disableonetimesetup = ',args.disableonetimesetup
1277 | #print 'enableonetimesetup = ',args.enableonetimesetup
1278 | #print 'changepassword = ',args.changepassword
1279 |
1280 | #print 'changename = ',args.changename
1281 |
1282 | if __name__ == "__main__":
1283 | main()
1284 |
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/etc/hostname:
--------------------------------------------------------------------------------
1 | marspc
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/etc/resolv.conf:
--------------------------------------------------------------------------------
1 | nameserver 94.140.14.140
2 | nameserver 1.0.0.1
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/home/ubuntu/Desktop/marspc.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=MARSPC™
3 | Comment=Homepage of MARSPC™
4 | Icon=/usr/share/icons/mars/marspc.png
5 | Type=Application
6 | Exec=xdg-open https://pc.arm.li/
7 |
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/usr/share/backgrounds/mars/block.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/mars-a1/usr/share/backgrounds/mars/block.jpg
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/usr/share/backgrounds/mars/cosmo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/mars-a1/usr/share/backgrounds/mars/cosmo.jpg
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/usr/share/backgrounds/mars/hexagon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/mars-a1/usr/share/backgrounds/mars/hexagon.jpg
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/usr/share/backgrounds/mars/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/mars-a1/usr/share/backgrounds/mars/home.jpg
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/usr/share/backgrounds/mars/planet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/mars-a1/usr/share/backgrounds/mars/planet.jpg
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/usr/share/backgrounds/mars/wave.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/mars-a1/usr/share/backgrounds/mars/wave.jpg
--------------------------------------------------------------------------------
/vendor-resources/mars-a1/usr/share/icons/mars/marspc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initdc/rootfs-tools/65393a5f8c65cc7e4d7055152a6c1ce09ebcf0d2/vendor-resources/mars-a1/usr/share/icons/mars/marspc.png
--------------------------------------------------------------------------------
/vendor-resources/visionfive-2/root/config.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | add_ubuntu() {
6 | useradd -G sudo -d /home/ubuntu -m -s /bin/bash ubuntu
7 | echo "ubuntu:ubuntu" | chpasswd
8 | echo "root:root" | chpasswd
9 | }
10 |
11 | add_lang_pack() {
12 | apt-get install -y language-pack-en-base
13 | apt-get install -y dialog apt-utils
14 | }
15 |
16 | install_software() {
17 | apt-get install -y dnsutils file htop ifupdown iputils-ping lshw lsof nano net-tools network-manager openssh-server rfkill tree u-boot-tools wget wireless-tools wpasupplicant
18 | apt-get install /tmp/resize-helper_0.12_all.deb
19 | }
20 |
21 | set_sshd_config() {
22 | cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig
23 | sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
24 | sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
25 | }
26 |
27 | main() {
28 | export DEBIAN_FRONTEND="noninteractive"
29 |
30 | # apt-get update
31 |
32 | # add_lang_pack
33 | # install_software
34 | set_sshd_config
35 | # rm -rf /var/lib/apt/*
36 |
37 | add_ubuntu
38 | # systemctl enable getty@ttyS2.service
39 |
40 | unset DEBIAN_FRONTEND
41 | }
42 |
43 | main "$@"
44 |
--------------------------------------------------------------------------------
/vendor-resources/visionfive-2/root/suse.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | change_hostname() {
6 | hostnamectl hostname 'visionfive2'
7 | }
8 |
9 | add_wheel() {
10 | groupadd wheel
11 | sed -i 's/# \%wheel ALL=(ALL:ALL) NOPASSWD: ALL/\%wheel ALL=(ALL:ALL) NOPASSWD: ALL/g' /etc/sudoers
12 | }
13 |
14 | add_suse() {
15 | useradd suse -m -G wheel -s /bin/bash
16 | echo "suse:byinitdc" | chpasswd
17 | echo "root:Byinitdc" | chpasswd
18 | }
19 |
20 | install_software() {
21 | zypper install -y htop lshw nano net-tools tree git-core
22 | }
23 |
24 | main() {
25 | install_software
26 | change_hostname
27 | add_wheel
28 | add_suse
29 | }
30 |
31 | main "$@"
32 |
--------------------------------------------------------------------------------
/vendor-resources/visionfive-2/vf2:
--------------------------------------------------------------------------------
1 | # dd if=/dev/zero of=vf2.img bs=1MB count=0 seek=2100
2 | label: gpt
3 | label-id: 58F2E40C-030E-48C2-95C2-0A45030AB01B
4 | device: vf2.img
5 | unit: sectors
6 | first-lba: 4096
7 | last-lba: 4096000
8 |
9 | sdcard.img1 : start= 4096, size= 4096, type=2E54B353-1271-4842-806F-E436D6AF6985, uuid=A5FEEF7A-E974-471E-B074-9D446B82D2EB, name="spl"
10 | sdcard.img2 : start= 8192, size= 8192, type=5B193300-FC78-40CD-8002-E86C45580B47, uuid=19A94EDA-2B35-450D-B9AF-13BB67C688F1, name="uboot"
11 | sdcard.img3 : start= 16384, size= 598016, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=98DCCB94-E0B4-48C1-8719-0ECD22AF25BA, name="image"
12 | sdcard.img4 : start= 614400, size= 3481600, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=ABD24574-D2AB-48E7-AC81-EE9FD5D9E3BF, name="root", attrs="LegacyBIOSBootable"
13 |
--------------------------------------------------------------------------------
/vendor-resources/visionfive-2/vf2-deb:
--------------------------------------------------------------------------------
1 | # dd if=/dev/zero of=vf2.img bs=1MB count=0 seek=2100
2 | label: gpt
3 | label-id: 6BEBB43B-65F5-4057-BC3A-D9B242D06F29
4 | device: vf2.img
5 | unit: sectors
6 | first-lba: 34
7 | last-lba: 4096000
8 |
9 | vf2.img1 : start= 2048, size= 32768, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=5F7FD372-5546-44DF-B018-A077758CEE2F
10 | vf2.img2 : start= 34816, size= 204800, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=BDC51E7D-66F3-4BA4-AC93-ADF2E8850928
11 | vf2.img3 : start= 239616, size= 3856384, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=3D4C02EB-9C28-46A1-A86B-71666EF51CDB, attrs="LegacyBIOSBootable"
12 |
--------------------------------------------------------------------------------
/vendor-resources/visionfive-2/vf2-fd:
--------------------------------------------------------------------------------
1 | # dd if=/dev/zero of=vf2.img bs=1MB count=0 seek=8500
2 | label: gpt
3 | label-id: 58F2E40C-030E-48C2-95C2-0A45030AB01B
4 | device: vf2.img
5 | unit: sectors
6 | first-lba: 4096
7 | last-lba: 16599040
8 |
9 | sdcard.img1 : start= 4096, size= 4096, type=2E54B353-1271-4842-806F-E436D6AF6985, uuid=A5FEEF7A-E974-471E-B074-9D446B82D2EB, name="spl"
10 | sdcard.img2 : start= 8192, size= 8192, type=5B193300-FC78-40CD-8002-E86C45580B47, uuid=19A94EDA-2B35-450D-B9AF-13BB67C688F1, name="uboot"
11 | sdcard.img3 : start= 16384, size= 598016, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=98DCCB94-E0B4-48C1-8719-0ECD22AF25BA, name="image"
12 | sdcard.img4 : start= 614400, size= 15984640, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=ABD24574-D2AB-48E7-AC81-EE9FD5D9E3BF, name="root", attrs="LegacyBIOSBootable"
13 |
--------------------------------------------------------------------------------