Move the LVFS website to the fwupd project
278
README.md
@ -1,94 +1,7 @@
|
|||||||
fwupd
|
fwupd
|
||||||
=====
|
=====
|
||||||
|
|
||||||
fwupd is a simple daemon to allow session software to update device firmware on
|
This project aims to make updating firmware on Linux automatic, safe and reliable.
|
||||||
your local machine. It's designed for desktops, but this project is probably
|
|
||||||
quite interesting for phones, tablets and server farms, so I'd be really happy
|
|
||||||
if this gets used on other non-desktop hardware.
|
|
||||||
|
|
||||||
You can either use a GUI software manager like GNOME Software to view and apply
|
|
||||||
updates, the command-line tool or the system D-Bus interface directly.
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
Updating firmware easily is actually split into two parts:
|
|
||||||
|
|
||||||
* Providing metadata about what vendor updates are available (AppStream)
|
|
||||||
* A mechanism to actually apply the file onto specific hardware (this project)
|
|
||||||
|
|
||||||
What do we actually need to apply firmware easily? A raw binary firmware file
|
|
||||||
isn't so useful, and so Microsoft have decided we should all package it up in a
|
|
||||||
.cab file (a bit like a .zip file) along with a .inf file that describes the
|
|
||||||
update in more detail. The .inf file gives us the hardware ID of what the
|
|
||||||
firmware is referring to, as well as the vendor and a short update description.
|
|
||||||
|
|
||||||
I'm asking friendly upstream vendors to also include a MetaInfo file alongside
|
|
||||||
the .inf file in the firmware .cab file. This means we can have fully localized
|
|
||||||
update descriptions, along with all the usual things you'd expect from an
|
|
||||||
update, e.g. the upstream vendor, the licensing information, etc.
|
|
||||||
|
|
||||||
A lot of people don't have UEFI hardware that is capable of applying capsule
|
|
||||||
firmware updates, so I've also added a ColorHug provider, which predictably also
|
|
||||||
lets you update the firmware on your ColorHug devices.
|
|
||||||
|
|
||||||
I'm also happy to accept patches for other hardware that supports updates,
|
|
||||||
although the internal API isn't 100% stable yet. The provider concept allows
|
|
||||||
vendors to do pretty much anything to get the list of attached hardware, as long
|
|
||||||
as a unique hardware component is in some way mapped to a GUID value.
|
|
||||||
Ideally the tools would be open source, or better still not needing any external
|
|
||||||
tools at all. Reading a VID/PID and then writing firmware to a chip usually
|
|
||||||
isn't rocket science.
|
|
||||||
|
|
||||||
What is standardised is the metadata, using AppStream 0.9 as the interchange
|
|
||||||
format. A lot of tools already talk AppStream and so this makes working with
|
|
||||||
other desktop and server tools very easy. Actually generating the AppStream
|
|
||||||
metadata can either be done using using `appstream-builder` or the Linux
|
|
||||||
Vendor Firmware Service.
|
|
||||||
|
|
||||||
Security
|
|
||||||
--------
|
|
||||||
|
|
||||||
By default, any users are able to install firmware to removable hardware.
|
|
||||||
The logic here is that if the hardware can be removed, it can easily be moved to
|
|
||||||
a device that the user already has root access on, and asking for authentication
|
|
||||||
would just be security theatre.
|
|
||||||
|
|
||||||
For non-removable devices, e.g. UEFI firmware, admin users are able to update
|
|
||||||
firmware without the root password. By default, we already let admin user and
|
|
||||||
root update glibc and the kernel without additional authentication, and these
|
|
||||||
would be a much easier target to backdoor. The firmware updates themselves
|
|
||||||
have a checksum, and the metadata describing this checksum is provided by the
|
|
||||||
distribution either as GPG-signed repository metadata, or installed from a
|
|
||||||
package, which is expected to also be signed. It is important that clients that
|
|
||||||
are downloading firmware for fwupd check the checksum before asking fwupd to
|
|
||||||
update a specific device.
|
|
||||||
|
|
||||||
User Interaction
|
|
||||||
----------------
|
|
||||||
|
|
||||||
No user interaction should be required when actually applying updates. Making
|
|
||||||
it prohibited means we can do the upgrade with a fancy graphical splash screen,
|
|
||||||
without having to worry about locales and input methods. Updating firmware
|
|
||||||
should be no more dangerous than installing a new kernel or glibc package.
|
|
||||||
|
|
||||||
Offline Updates Lifecycle
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Offline updates are done using a special boot target which means that the usual
|
|
||||||
graphical environment is not started. Once the firmware update has completed the
|
|
||||||
system will reboot.
|
|
||||||
|
|
||||||
Devices go through the following lifecycles:
|
|
||||||
|
|
||||||
* created -> `SCHEDULED` -> `SUCCESS` -> deleted
|
|
||||||
* created -> `SCHEDULED` -> `FAILED` -> deleted
|
|
||||||
|
|
||||||
Any user-visible output is available using the `GetResults()` D-Bus method, and
|
|
||||||
the database entry is only deleted once the `ClearResults()` method is called.
|
|
||||||
|
|
||||||
The results are obtained and cleared either using a provider-supplied method
|
|
||||||
or using a small SQLite database located at `/var/lib/fwupd/pending.db`
|
|
||||||
|
|
||||||
ColorHug Support
|
ColorHug Support
|
||||||
----------------
|
----------------
|
||||||
@ -98,195 +11,14 @@ provides. Compile it from source https://github.com/hughsie/colord or grab the
|
|||||||
RPMs here http://people.freedesktop.org/~hughsient/fedora/
|
RPMs here http://people.freedesktop.org/~hughsient/fedora/
|
||||||
|
|
||||||
If you don't want or need this functionality you can use the
|
If you don't want or need this functionality you can use the
|
||||||
`--disable-colorhug` option.
|
<code>--disable-colorhug<code> option.
|
||||||
|
|
||||||
UEFI Support
|
UEFI Support
|
||||||
------------
|
------------
|
||||||
|
|
||||||
If you're wondering where to get `fwupdate` from, either compile it form source
|
If you're wondering where to get <code>fwupdate<code> from, either compile it form source
|
||||||
(you might also need a newer `efivar`) from https://github.com/rhinstaller/fwupdate
|
(you might also need a newer <code>efivar<code>) from https://github.com/rhinstaller/fwupdate
|
||||||
or grab the RPMs here https://pjones.fedorapeople.org/fwupdate/
|
or grab the RPMs here https://pjones.fedorapeople.org/fwupdate/
|
||||||
|
|
||||||
If you don't want or need this functionality you can use the `--disable-uefi`
|
If you don't want or need this functionality you can use the <code>--disable-uefi<code>
|
||||||
option.
|
option.
|
||||||
|
|
||||||
Vendor Firmware Updates
|
|
||||||
=======================
|
|
||||||
|
|
||||||
This document explains what steps a vendor needs to take so that firmware
|
|
||||||
updates are downloaded and applied to user hardware automatically.
|
|
||||||
|
|
||||||
Different hardware update methods can be supported, but would require a new
|
|
||||||
plugin and there would need to be interfaces available to be able to write
|
|
||||||
(or at least trigger) the firmware from userspace as the root user.
|
|
||||||
|
|
||||||
What do I have to do?
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
As per the [Microsoft guidelines](https://msdn.microsoft.com/en-us/library/windows/hardware/dn917810%28v=vs.85%29.aspx),
|
|
||||||
package up your firmware into a `.cab` file, with these files inside:
|
|
||||||
|
|
||||||
* The actual `.cap` file your engineers have created
|
|
||||||
* The `.inf` file describing the .cap file,
|
|
||||||
described [here](https://msdn.microsoft.com/en-us/library/windows/hardware/ff547402%28v=vs.85%29.aspx)
|
|
||||||
* The optional `.asc` file which is a detached GPG signature of the firmware file.
|
|
||||||
* The optional `.metainfo.xml` file with a long description and extra metadata,
|
|
||||||
described [here](http://www.freedesktop.org/software/appstream/docs/sect-Quickstart-Addons.html)
|
|
||||||
|
|
||||||
You can create a `.cab` file using `makecab.exe` on Windows and `gcab --create`
|
|
||||||
on Linux.
|
|
||||||
|
|
||||||
It is recommended you name the `.cab` file with the hardware name and the version
|
|
||||||
number, e.g. `colorhug-als-1.2.3.cab`. It's mandatory that the files inside the
|
|
||||||
`.cab` file have the same basename, for example this is would be valid:
|
|
||||||
|
|
||||||
colorhug2-1.2.3.cab
|
|
||||||
|- firmware.inf
|
|
||||||
|- firmware.bin
|
|
||||||
|- firmware.bin.asc
|
|
||||||
\- firmware.metainfo.xml
|
|
||||||
|
|
||||||
An example `.inf` file might look like this:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[Version]
|
|
||||||
Class=Firmware
|
|
||||||
ClassGuid={f2e7dd72-6468-4e36-b6f1-6488f42c1b52}
|
|
||||||
DriverVer=03/03/2015,3.0.2
|
|
||||||
|
|
||||||
[Firmware_CopyFiles]
|
|
||||||
firmware.bin
|
|
||||||
|
|
||||||
[Firmware_AddReg]
|
|
||||||
HKR,,FirmwareId,,{84f40464-9272-4ef7-9399-cd95f12da696}
|
|
||||||
HKR,,FirmwareVersion,%REG_DWORD%,0x0000000
|
|
||||||
HKR,,FirmwareFilename,,firmware.bin
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
An example `.metainfo.xml` file might look like this:
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!-- Copyright 2015 Richard Hughes <richard@hughsie.com> -->
|
|
||||||
<component type="firmware">
|
|
||||||
<id>84f40464-9272-4ef7-9399-cd95f12da696</id>
|
|
||||||
<name>ColorHugALS Firmware</name>
|
|
||||||
<summary>Firmware for the ColorHugALS Ambient Light Sensor</summary>
|
|
||||||
<description>
|
|
||||||
<p>
|
|
||||||
Updating the firmware on your ColorHugALS device improves performance and
|
|
||||||
adds new features.
|
|
||||||
</p>
|
|
||||||
</description>
|
|
||||||
<url type="homepage">http://www.hughski.com/</url>
|
|
||||||
<metadata_license>CC0-1.0</metadata_license>
|
|
||||||
<project_license>GPL-2.0+</project_license>
|
|
||||||
<developer_name>Hughski Limited</developer_name>
|
|
||||||
<releases>
|
|
||||||
<release version="3.0.2" timestamp="1424116753">
|
|
||||||
<location>http://www.hughski.com/downloads/colorhug-als/firmware/colorhug-als-3.0.2.cab</location>
|
|
||||||
<description>
|
|
||||||
<p>This stable release fixes the following bugs:</p>
|
|
||||||
<ul>
|
|
||||||
<li>Fix the return code from GetHardwareVersion</li>
|
|
||||||
<li>Scale the output of TakeReadingRaw by the datasheet values</li>
|
|
||||||
</ul>
|
|
||||||
</description>
|
|
||||||
</release>
|
|
||||||
</releases>
|
|
||||||
</component>
|
|
||||||
```
|
|
||||||
|
|
||||||
If the firmware is not redistributable you have to indicate it in in the
|
|
||||||
`.metainfo.xml` file with `<project_license>proprietary</project_license>`.
|
|
||||||
If the firmware location is not stable you can use the Linux Vendor Firmware
|
|
||||||
Service to mirror your file.
|
|
||||||
|
|
||||||
Questions
|
|
||||||
---------
|
|
||||||
|
|
||||||
### Where will this data be used?
|
|
||||||
|
|
||||||
We will scrape the `.inf` and `.metainfo.xml` files when building and composing
|
|
||||||
metadata for distributions; end users will still be downloading the `.cab`
|
|
||||||
files directly from the vendor site.
|
|
||||||
|
|
||||||
### How do I know if my appdata XML is correct?
|
|
||||||
|
|
||||||
The best way to validate the data is by using the `appstream-util validate`
|
|
||||||
tool available from the [appstream-glib](https://github.com/hughsie/appstream-glib) project.
|
|
||||||
|
|
||||||
### Where do I submit the `.cab` files?
|
|
||||||
|
|
||||||
The easiest way to upload new firmware is to use the [Linux Vendor Firmware
|
|
||||||
Service](https://beta-lvfs.rhcloud.com/) which will validate your firmware,
|
|
||||||
generate the metadata and mirror them automatically.
|
|
||||||
|
|
||||||
Vendors can also produce and upload the AppStream metadata themselves using the
|
|
||||||
`appstream-builder` command line tool, for example:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
appstream-builder \
|
|
||||||
--basename=colorhug-firmware \
|
|
||||||
--origin=hughski \
|
|
||||||
ColorHug*/firmware-releases/*.*.*/*.cab
|
|
||||||
```
|
|
||||||
|
|
||||||
...will produce this file: http://www.hughski.com/downloads/colorhug-firmware.xml
|
|
||||||
|
|
||||||
Please [email us](mailto://richard@hughsie.com) if you want more help using
|
|
||||||
either generation method.
|
|
||||||
|
|
||||||
### How does fwupd know the device firmware version?
|
|
||||||
|
|
||||||
For generic USB devices you can use a firmware vendor extensions that are used
|
|
||||||
by a few OpenHardware projects. This means the fwupd daemon can obtain the
|
|
||||||
GUID and firmware version without claiming the interface on the device and
|
|
||||||
preventing other software from using it.
|
|
||||||
For closed-source devices a product-specific provider can also be used, although
|
|
||||||
this isn't covered here.
|
|
||||||
|
|
||||||
To implement the firmware version extension just create an interface descriptor
|
|
||||||
with class code `0xff`, subclass code `0x46` and protocol `0x57` pointing to a
|
|
||||||
string descriptor with the firmware version.
|
|
||||||
An example commit to the ColorHug project can be found [here](https://github.com/hughski/colorhug2-firmware/commit/5e1bb64ad722a9d2d95927e305fd869b4a3a46a8).
|
|
||||||
|
|
||||||
Furthermore, using the firmware GUID extension allows fwupd to detect firmware
|
|
||||||
updates for devices it does not know how to update.
|
|
||||||
These types of devices will however show up in the command line and GUI tools,
|
|
||||||
so the user is at least aware that updates are available.
|
|
||||||
|
|
||||||
To implement this, add an interface descriptor with class code `0xff`, subclass
|
|
||||||
code `0x47` and protocol `0x55` pointing to a string descriptor with the GUID.
|
|
||||||
If the GUID matches the '<id>' obtained from the AppStream metadata then the
|
|
||||||
device will be shown.
|
|
||||||
An example commit to the ColorHug project can be found [here](https://github.com/hughski/colorhug2-firmware/commit/f974638ac17b0e50f21987e2f1d982374cabe22c).
|
|
||||||
|
|
||||||
Adding Trusted Keys
|
|
||||||
===================
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
Installing a public key to `/etc/pki/fwupd` allows firmware signed with a
|
|
||||||
matching private key to be recognized as trusted, which may require less
|
|
||||||
authentication to install than for untrusted files. By default trusted firmware
|
|
||||||
can be **upgraded** (but not downgraded) without the user or administrator
|
|
||||||
password.
|
|
||||||
|
|
||||||
Only very few keys will be installed *by default*. These are the keys of
|
|
||||||
vendors who have a proven security track record and a thorough understanding of
|
|
||||||
public-private key security.
|
|
||||||
|
|
||||||
In particular, private keys should **only** be kept on Hardware Security
|
|
||||||
Mechanisms, and used on machines (or virtual machine) that have limited network
|
|
||||||
access, or networking completely disabled. The machine and any backups also
|
|
||||||
need to be kept physically secure.
|
|
||||||
|
|
||||||
Adding a New Key
|
|
||||||
----------------
|
|
||||||
|
|
||||||
If you think your key should be added by default and trusted by all users,
|
|
||||||
please open a pull request with details about your company including items such
|
|
||||||
as a day time phone number and any relevant security policies already in place.
|
|
||||||
|
790
docs/architecture-plan.svg
Normal file
@ -0,0 +1,790 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1052.3622"
|
||||||
|
height="744.09448"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="architecture-plan.svg"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/colord/doc/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="59.99197"
|
||||||
|
inkscape:export-ydpi="59.99197">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Send"
|
||||||
|
style="overflow:visible;">
|
||||||
|
<path
|
||||||
|
id="path3875"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
|
||||||
|
transform="scale(0.2) rotate(180) translate(6,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Mend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Mend"
|
||||||
|
style="overflow:visible;">
|
||||||
|
<path
|
||||||
|
id="path3869"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
|
||||||
|
transform="scale(0.4) rotate(180) translate(10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Sstart"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Sstart"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path3872"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
|
||||||
|
transform="scale(0.2) translate(6,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lstart"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Lstart"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path3860"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
|
||||||
|
transform="scale(0.8) translate(12.5,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Sstart"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Sstart-5"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3872-4"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(0.2,0,0,0.2,1.2,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Send-7"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3875-0"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Sstart"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Sstart-5-1"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3872-4-4"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(0.2,0,0,0.2,1.2,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Send-7-6"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3875-0-2"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Sstart"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Sstart-8"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3872-5"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(0.2,0,0,0.2,1.2,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Send-9"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3875-04"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Send"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Send-7-9"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3875-0-1"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.7"
|
||||||
|
inkscape:cx="491.33991"
|
||||||
|
inkscape:cy="175.26692"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1016"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="867"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2985"
|
||||||
|
empspacing="5"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-308.2677)">
|
||||||
|
<rect
|
||||||
|
style="fill:#f29097;fill-opacity:1;stroke:#000000;stroke-width:2.88675141000000002;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect2987"
|
||||||
|
width="240"
|
||||||
|
height="60"
|
||||||
|
x="420"
|
||||||
|
y="672.36218"
|
||||||
|
ry="20"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
x="541.35742"
|
||||||
|
y="713.39734"
|
||||||
|
id="text2989"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan2991"
|
||||||
|
x="541.35742"
|
||||||
|
y="713.39734"
|
||||||
|
style="text-align:center;text-anchor:middle">fwupd</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="872.36218"
|
||||||
|
x="180"
|
||||||
|
height="60"
|
||||||
|
width="180"
|
||||||
|
id="rect2993"
|
||||||
|
style="fill:#ffffc8;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text2995"
|
||||||
|
y="912.37256"
|
||||||
|
x="268.61694"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:27.5px;text-align:center;text-anchor:middle"
|
||||||
|
y="912.37256"
|
||||||
|
x="268.61694"
|
||||||
|
id="tspan2997"
|
||||||
|
sodipodi:role="line">ESRT</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="672.36218"
|
||||||
|
x="180"
|
||||||
|
height="60"
|
||||||
|
width="180"
|
||||||
|
id="rect2993-4"
|
||||||
|
style="fill:#ffffc8;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.5, 2.5;stroke-dashoffset:0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="80.000001%"
|
||||||
|
id="text2995-9"
|
||||||
|
y="701.61426"
|
||||||
|
x="269.32861"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:80.00000119%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:27.5px;line-height:80.00000119%;text-align:center;text-anchor:middle"
|
||||||
|
y="701.61426"
|
||||||
|
x="269.32861"
|
||||||
|
id="tspan2997-9"
|
||||||
|
sodipodi:role="line">Vendor</tspan><tspan
|
||||||
|
style="font-size:27.5px;line-height:80.00000119%;text-align:center;text-anchor:middle"
|
||||||
|
y="723.61426"
|
||||||
|
x="269.32861"
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4991">Provders</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffc8;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect3023-9"
|
||||||
|
width="180"
|
||||||
|
height="60"
|
||||||
|
x="180"
|
||||||
|
y="772.36218"
|
||||||
|
ry="20"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
x="269.21448"
|
||||||
|
y="812.61426"
|
||||||
|
id="text3025-0"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3027-2"
|
||||||
|
x="269.21448"
|
||||||
|
y="812.61426"
|
||||||
|
style="font-size:27.5px;text-align:center;text-anchor:middle">Udev</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="672.36218"
|
||||||
|
x="720"
|
||||||
|
height="60"
|
||||||
|
width="180"
|
||||||
|
id="rect3053"
|
||||||
|
style="fill:#ff96ff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3055"
|
||||||
|
y="709.94885"
|
||||||
|
x="810.50354"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:27.5px;text-align:center;text-anchor:middle"
|
||||||
|
y="709.94885"
|
||||||
|
x="810.50354"
|
||||||
|
id="tspan3057"
|
||||||
|
sodipodi:role="line">systemd</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="fill:#64ffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect3059"
|
||||||
|
width="180"
|
||||||
|
height="60"
|
||||||
|
x="719.54187"
|
||||||
|
y="772.36218"
|
||||||
|
ry="20"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
x="809.04504"
|
||||||
|
y="809.94885"
|
||||||
|
id="text3061"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3063"
|
||||||
|
x="809.04504"
|
||||||
|
y="809.94885"
|
||||||
|
style="font-size:27.5px;text-align:center;text-anchor:middle">pending.db</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Send)"
|
||||||
|
d="m 360,712.36218 60,0"
|
||||||
|
id="path3841"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Send)"
|
||||||
|
d="m 360,792.36218 115,0 0,-60"
|
||||||
|
id="path3843"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:;marker-end:url(#Arrow1Send)"
|
||||||
|
d="m 360,892.36218 140,0 0,-160"
|
||||||
|
id="path3845"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Sstart);marker-end:none"
|
||||||
|
d="m 718.97997,712.36218 -60,0"
|
||||||
|
id="path3849"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Sstart);marker-end:url(#Arrow1Send)"
|
||||||
|
d="m 720,792.36218 -110,0 0,-60"
|
||||||
|
id="path3851"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.95742708px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 40,652.36218 880,0"
|
||||||
|
id="path5615"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||||
|
x="48.285713"
|
||||||
|
y="643.2193"
|
||||||
|
id="text5617"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan5619"
|
||||||
|
x="48.285713"
|
||||||
|
y="643.2193"
|
||||||
|
style="font-size:32px">session</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||||
|
x="48.857143"
|
||||||
|
y="683.21936"
|
||||||
|
id="text5621"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan5623"
|
||||||
|
x="48.857143"
|
||||||
|
y="683.21936"
|
||||||
|
style="font-size:32px">system</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="452.36218"
|
||||||
|
x="440"
|
||||||
|
height="60"
|
||||||
|
width="200"
|
||||||
|
id="rect5625"
|
||||||
|
style="fill:#83a2ff;fill-opacity:1;stroke:#000000;stroke-width:2.635;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000096;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:;marker-end:url(#Arrow1Send-7)"
|
||||||
|
d="m 540,672.36218 0,-160"
|
||||||
|
id="path5631"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="552.36218"
|
||||||
|
x="280"
|
||||||
|
height="60"
|
||||||
|
width="180.64258"
|
||||||
|
id="rect5625-3"
|
||||||
|
style="fill:#83a2ff;fill-opacity:1;stroke:#000000;stroke-width:2.50445843;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text5627-6"
|
||||||
|
y="590.36218"
|
||||||
|
x="372.64258"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:27.5px;text-align:center;text-anchor:middle"
|
||||||
|
y="590.36218"
|
||||||
|
x="372.64258"
|
||||||
|
id="tspan5629-6"
|
||||||
|
sodipodi:role="line">fwupdmgr</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="452.36218"
|
||||||
|
x="720"
|
||||||
|
height="60"
|
||||||
|
width="180"
|
||||||
|
id="rect5657"
|
||||||
|
style="fill:#a6bdbd;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="89.999998%"
|
||||||
|
id="text5659"
|
||||||
|
y="480.50946"
|
||||||
|
x="810.64258"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:89.99999762%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:27.5px;line-height:89.99999762%;text-align:center;text-anchor:middle"
|
||||||
|
y="480.50946"
|
||||||
|
x="810.64258"
|
||||||
|
id="tspan5661"
|
||||||
|
sodipodi:role="line">download</tspan><tspan
|
||||||
|
style="font-size:27.5px;line-height:89.99999762%;text-align:center;text-anchor:middle"
|
||||||
|
y="502.10947"
|
||||||
|
x="810.64258"
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4993">cache</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000096;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Sstart-5);marker-end:none"
|
||||||
|
d="m 460,592.36218 40,0 0,80"
|
||||||
|
id="path5663"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="452.36218"
|
||||||
|
x="180"
|
||||||
|
height="60"
|
||||||
|
width="180"
|
||||||
|
id="rect5675"
|
||||||
|
style="fill:#cbffc8;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4.61880207000000009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Send-7)"
|
||||||
|
d="m 360,492.36218 80,0"
|
||||||
|
id="path5673"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text5677"
|
||||||
|
y="492.19128"
|
||||||
|
x="268.98621"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:27.5px;text-align:center;text-anchor:middle"
|
||||||
|
y="492.19128"
|
||||||
|
x="268.98621"
|
||||||
|
id="tspan5679"
|
||||||
|
sodipodi:role="line">Internet</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4.61880207;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Sstart-5);marker-end:url(#Arrow1Send-7)"
|
||||||
|
d="m 640,492.36218 80,0"
|
||||||
|
id="path5673-3"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
x="370"
|
||||||
|
y="807.36218"
|
||||||
|
id="text7146-2-2"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan7148-7-6"
|
||||||
|
x="370"
|
||||||
|
y="807.36218"
|
||||||
|
style="font-size:12px">Gudev + rules</tspan></text>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text7584"
|
||||||
|
y="784.36218"
|
||||||
|
x="665"
|
||||||
|
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:12px"
|
||||||
|
y="784.36218"
|
||||||
|
x="665"
|
||||||
|
id="tspan7586"
|
||||||
|
sodipodi:role="line">sqlite</tspan></text>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3912"
|
||||||
|
y="486.36218"
|
||||||
|
x="660"
|
||||||
|
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:12px"
|
||||||
|
y="486.36218"
|
||||||
|
x="660"
|
||||||
|
id="tspan3914"
|
||||||
|
sodipodi:role="line">$home</tspan></text>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text5627-8"
|
||||||
|
y="495.72552"
|
||||||
|
x="532.26953"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:28.10403442px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
transform="scale(1.0144841,0.98572269)"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:21.25px;text-align:center;text-anchor:middle"
|
||||||
|
y="495.72552"
|
||||||
|
x="532.26953"
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3086-5">gnome-software</tspan></text>
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4995"
|
||||||
|
d="m 579.85714,672.36218 0,-160"
|
||||||
|
style="fill:none;stroke:#000096;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Sstart-5)"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3912-9"
|
||||||
|
y="-587.11932"
|
||||||
|
x="536.76471"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
transform="matrix(0,1,-1,0,0,0)"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:12px"
|
||||||
|
y="-587.11932"
|
||||||
|
x="536.76471"
|
||||||
|
id="tspan3914-1"
|
||||||
|
sodipodi:role="line">UpdateMetadata()</tspan></text>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3912-9-1"
|
||||||
|
y="-547.26221"
|
||||||
|
x="542.479"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
transform="matrix(0,1,-1,0,0,0)"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:12px"
|
||||||
|
y="-547.26221"
|
||||||
|
x="542.479"
|
||||||
|
id="tspan3914-1-0"
|
||||||
|
sodipodi:role="line">GetDevices()</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="871.09338"
|
||||||
|
x="-899.54187"
|
||||||
|
height="60"
|
||||||
|
width="180"
|
||||||
|
id="rect2993-0"
|
||||||
|
style="fill:#ffffc8;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
transform="scale(-1,1)"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text2995-2"
|
||||||
|
y="908.68005"
|
||||||
|
x="809.47473"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:27.5px;text-align:center;text-anchor:middle"
|
||||||
|
y="908.68005"
|
||||||
|
x="809.47473"
|
||||||
|
id="tspan2997-94"
|
||||||
|
sodipodi:role="line">sysfs</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Send-7-6)"
|
||||||
|
d="m 720.04697,892.36218 -140,0 0,-160.00005"
|
||||||
|
id="path3845-0"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3912-93"
|
||||||
|
y="484.21933"
|
||||||
|
x="367.75699"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:12px"
|
||||||
|
y="484.21933"
|
||||||
|
x="367.75699"
|
||||||
|
id="tspan3914-6"
|
||||||
|
sodipodi:role="line">metadata</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
x="368.57144"
|
||||||
|
y="507.07648"
|
||||||
|
id="text5147"
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan5149"
|
||||||
|
x="368.57144"
|
||||||
|
y="507.07648"
|
||||||
|
style="font-size:12px">firmware</tspan></text>
|
||||||
|
<rect
|
||||||
|
ry="20"
|
||||||
|
y="-1011.0447"
|
||||||
|
x="440"
|
||||||
|
height="60"
|
||||||
|
width="200"
|
||||||
|
id="rect5625-0"
|
||||||
|
style="fill:#64ffff;fill-opacity:1;stroke:#000000;stroke-width:2.63499999;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
transform="scale(1,-1)"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Sstart);marker-end:url(#Arrow1Send)"
|
||||||
|
d="m 540,739.61613 0,210"
|
||||||
|
id="path5631-5"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text5627-8-5"
|
||||||
|
y="1000.9299"
|
||||||
|
x="532.25916"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:28.10403442px;line-height:125%;font-family:'Bitstream Vera Sans';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||||
|
xml:space="preserve"
|
||||||
|
transform="scale(1.0144841,0.98572269)"
|
||||||
|
inkscape:export-filename="/home/hughsie/Code/fwupd/docs/website/img/architecture-plan.png"
|
||||||
|
inkscape:export-xdpi="71.67067"
|
||||||
|
inkscape:export-ydpi="71.67067"><tspan
|
||||||
|
style="font-size:21.25px;text-align:center;text-anchor:middle"
|
||||||
|
y="1000.9299"
|
||||||
|
x="532.25916"
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3086-5-8">AppStream XML</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 34 KiB |
7
docs/website/.htaccess
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
RewriteEngine on
|
||||||
|
RewriteCond %{HTTP:X-Forwarded-Proto} !https
|
||||||
|
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
|
||||||
|
|
||||||
|
# Don't compress gzipped files
|
||||||
|
SetEnv no-gzip 1
|
||||||
|
SetEnv dont-vary 1
|
3
docs/website/.openshift/action_hooks/build
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
ln -s ${OPENSHIFT_DATA_DIR}uploads ${OPENSHIFT_REPO_DIR}uploads
|
||||||
|
ln -s ${OPENSHIFT_DATA_DIR}downloads ${OPENSHIFT_REPO_DIR}downloads
|
40
docs/website/README.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
Linux Vendor Firmware Service
|
||||||
|
=============================
|
||||||
|
|
||||||
|
This is the website for the Linux Vendor Firmware Service
|
||||||
|
|
||||||
|
IMPORTANT: This needs to be hosted over SSL, i.e. with a `https://` prefix.
|
||||||
|
|
||||||
|
Using
|
||||||
|
-----
|
||||||
|
|
||||||
|
Using `index.html` you can upload files to the upload directory.
|
||||||
|
You can also dump all the user-visible databases using `dump.php`.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
The default upload path of /var/www/html/lvfs/uploads needs to be writable by
|
||||||
|
the apache user. You might have to tweak your SELinux policy too.
|
||||||
|
|
||||||
|
We also need a SQL server somewhere, with the following tables set up:
|
||||||
|
|
||||||
|
CREATE TABLE `firmware` (
|
||||||
|
`vendor_key` varchar(36) DEFAULT NULL,
|
||||||
|
`update_contact` varchar(255) DEFAULT NULL,
|
||||||
|
`addr` varchar(16) DEFAULT NULL,
|
||||||
|
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
`filename` varchar(255) DEFAULT NULL,
|
||||||
|
`hash` varchar(40) DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`guid` varchar(36) NOT NULL DEFAULT '',
|
||||||
|
`name` varchar(128) DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
Just modify the `db.php` file with your login credentials. You can insert
|
||||||
|
authorised vendors with:
|
||||||
|
|
||||||
|
INSERT INTO `users` (`guid`, `name`) VALUES
|
||||||
|
('06350563-5b58-4c1d-8959-d9a216188604', 'Vendor1'),
|
||||||
|
('579caa6c-29d3-4efa-8f4d-bd2ff46af798', 'Vendor2');
|
8671
docs/website/banner.svg
Normal file
After Width: | Height: | Size: 653 KiB |
35
docs/website/db.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License Version 2
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function lvfs_connect_db() {
|
||||||
|
return new mysqli($_ENV["OPENSHIFT_MYSQL_DB_HOST"],
|
||||||
|
$_ENV["OPENSHIFT_MYSQL_DB_USERNAME"],
|
||||||
|
$_ENV["OPENSHIFT_MYSQL_DB_PASSWORD"],
|
||||||
|
"beta",
|
||||||
|
(int) $_ENV["OPENSHIFT_MYSQL_DB_PORT"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function lvfs_disconnect_db($db) {
|
||||||
|
$db->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
171
docs/website/developers.html
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
Licensed under the GNU General Public License Version 2 -->
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>fwupd: Firmware Update Daemon</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300' rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" media="screen"/>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1 class="banner">fwupd: Firmware<br> Update Daemon</h1>
|
||||||
|
|
||||||
|
<h1>Introduction</h1>
|
||||||
|
<p>
|
||||||
|
A lot of people don't have UEFI hardware that is capable of applying capsule
|
||||||
|
firmware updates, so I've also added a ColorHug provider, which predictably also
|
||||||
|
lets you update the firmware on your <a href="http://www.hughski.com/">ColorHug</a> devices.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
I'm also happy to accept patches for other hardware that supports updates.
|
||||||
|
The provider concept allows vendors to do pretty much anything to get the list
|
||||||
|
of attached hardware, as long as a unique hardware component is in some way
|
||||||
|
mapped to a GUID value.
|
||||||
|
Ideally the tools would be open source, or better still not needing any external
|
||||||
|
tools at all.
|
||||||
|
Reading a VID/PID and then writing firmware to a chip usually isn't rocket science.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="http://www.freedesktop.org/software/appstream/docs/">AppStream 0.9</a>
|
||||||
|
is used as the interchange format for update descriptions.
|
||||||
|
A lot of tools already talk AppStream and so this makes working with
|
||||||
|
other desktop and server tools very easy. Actually generating the AppStream
|
||||||
|
metadata can either be done using using <code>appstream-builder</code> or the
|
||||||
|
<a href="vendors.html">Linux Vendor Firmware Service</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h1>Architecture</h1>
|
||||||
|
<p>
|
||||||
|
fwupd is implemented as a D-Bus activated service that is autostarted when
|
||||||
|
required.
|
||||||
|
</p>
|
||||||
|
<img src="img/architecture-plan.png" alt="architecture-plan"/>
|
||||||
|
<p>
|
||||||
|
The 'client' which is typically <code>gnome-software</code> or <code>fwupd</code>
|
||||||
|
does all the query, download and schedule steps.
|
||||||
|
This means that the daemon has no network access and only acts as the mechanism
|
||||||
|
for clients.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Getting the code</h2>
|
||||||
|
<p>
|
||||||
|
The latest code is always available at <a href="https://github.com/hughsie/fwupd">GitHub</a>
|
||||||
|
and this is also the place to file <a href="https://github.com/hughsie/fwupd/issues">bugs or feature requests</a>.
|
||||||
|
You can trivially get the code by doing:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
$ git clone https://github.com/hughsie/fwupd.git
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
You can also install all the required dependancies using:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
$ sudo dnf install docbook-utils gettext intltool libgudev1-devel \
|
||||||
|
colord-devel polkit-devel libgcab1-devel \
|
||||||
|
sqlite-devel gpgme-devel fwupdate-devel
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>How does fwupd know the device firmware version?</h2>
|
||||||
|
<p>
|
||||||
|
There are currently several ways to detect the firmware version:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>USB firmware version extensions (see below)</li>
|
||||||
|
<li>The <code>bcdVersion</code> for some USB devices</li>
|
||||||
|
<li>Parsing the option ROM and searching for serial numbers</li>
|
||||||
|
<li>Using <code>libfwupdate</code> to get the ESRT table data</li>
|
||||||
|
<li>Using a custom provider (not covered here)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>USB Firmware Version Extensions</h3>
|
||||||
|
<p>
|
||||||
|
For generic USB devices you can use a firmware vendor extensions that are used
|
||||||
|
by several OpenHardware projects.
|
||||||
|
This means the fwupd daemon can obtain the GUID and firmware version without
|
||||||
|
claiming the interface on the device and preventing other software from using it.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To implement the firmware version extension just create an interface descriptor
|
||||||
|
with class code <code>0xff</code>, subclass code <code>0x46</code> and
|
||||||
|
protocol <code>0x57</code> pointing to a string descriptor with the firmware version.
|
||||||
|
An example commit to the ColorHug project can be found
|
||||||
|
<a href="https://github.com/hughski/colorhug2-firmware/commit/5e1bb64ad722a9d2d95927e305fd869b4a3a46a8">here</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Furthermore, using the firmware GUID extension allows fwupd to detect firmware
|
||||||
|
updates for devices it does not know how to update.
|
||||||
|
These types of devices will however show up in the command line and GUI tools,
|
||||||
|
so the user is at least aware that updates are available.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To implement this, add an interface descriptor with class code <code>0xff</code>, subclass
|
||||||
|
code <code>0x47</code> and protocol <code>0x55</code> pointing to a string descriptor with the GUID.
|
||||||
|
If the GUID matches the <code><id></code> obtained from the AppStream metadata then the
|
||||||
|
device will be shown.
|
||||||
|
An example commit to the ColorHug project can be found
|
||||||
|
<a href="https://github.com/hughski/colorhug2-firmware/commit/f974638ac17b0e50f21987e2f1d982374cabe22c">here</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Offline Updates Lifecycle</h2>
|
||||||
|
<p>
|
||||||
|
Offline updates are done using a special boot target which means that the usual
|
||||||
|
graphical environment is not started. Once the firmware update has completed the
|
||||||
|
system will reboot.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Devices go through the following lifecycles:
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li>created → <code>SCHEDULED</code> → <code>SUCCESS</code> → deleted</li>
|
||||||
|
<li>created → <code>SCHEDULED</code> → <code>FAILED</code> → deleted</li>
|
||||||
|
</ol>
|
||||||
|
<p>
|
||||||
|
Any user-visible output is available using the <code>GetResults()</code> D-Bus method, and
|
||||||
|
the database entry is only deleted once the <code>ClearResults()</code> method is called.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The results are obtained and cleared either using a provider-supplied method
|
||||||
|
or using a small SQLite database located at <code>/var/lib/fwupd/pending.db</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Adding Trusted Keys</h2>
|
||||||
|
<p>
|
||||||
|
Installing a public key to <code>/etc/pki/fwupd</code> allows firmware signed with a
|
||||||
|
matching private key to be recognized as trusted, which may require less
|
||||||
|
authentication to install than for untrusted files.
|
||||||
|
By default trusted firmware can be <b>upgraded</b> (but not downgraded)
|
||||||
|
without the user or administrator
|
||||||
|
password.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Only very few keys will be installed <i>by default</i>. These are the keys of
|
||||||
|
vendors who have a proven security track record and a thorough understanding of
|
||||||
|
public-private key security.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In particular, private keys should <b>only</b> be kept on Hardware Security
|
||||||
|
Mechanisms, and used on machines (or virtual machine) that have limited network
|
||||||
|
access, or networking completely disabled.
|
||||||
|
The machine and any backups also need to be kept physically secure.
|
||||||
|
</p>
|
||||||
|
<h3>Adding a New Key</h3>
|
||||||
|
<p>
|
||||||
|
If you think your key should be added by default and trusted by all users,
|
||||||
|
please open a pull request with details about your company including items such
|
||||||
|
as a daytime phone number and any relevant security policies already in place.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="index.html">Go back to the main page</a></p>
|
||||||
|
|
||||||
|
<p class="footer">
|
||||||
|
Copyright <a href="mailto:richard@hughsie.com">Richard Hughes 2015</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
55
docs/website/dump.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
Licensed under the GNU General Public License Version 2 -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Linux Vendor Firmware Service</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" media="screen"/>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>History</h1>
|
||||||
|
|
||||||
|
<table class="history">
|
||||||
|
<tr>
|
||||||
|
<th>Vendor</th>
|
||||||
|
<th>Filename</th>
|
||||||
|
<th>Hash</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
include 'db.php';
|
||||||
|
|
||||||
|
function lvfs_get_vendor_name($db, $id) {
|
||||||
|
$res = $db->query('SELECT name FROM users WHERE guid = "' . $id . '";');
|
||||||
|
return $res->fetch_assoc()['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = lvfs_connect_db();
|
||||||
|
$res = $db->query('SELECT * FROM firmware');
|
||||||
|
while ($row = $res->fetch_assoc()) {
|
||||||
|
$vendor_name = lvfs_get_vendor_name($db, $row["vendor_key"]);
|
||||||
|
echo '<tr>';
|
||||||
|
echo '<td>' . $vendor_name . '</td>';
|
||||||
|
echo '<td>' . $row["filename"] . '</td>';
|
||||||
|
echo '<td>' . $row["hash"] . '</td>';
|
||||||
|
echo '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
lvfs_disconnect_db($db);
|
||||||
|
|
||||||
|
?>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p class="footer">
|
||||||
|
Copyright <a href="mailto:richard@hughsie.com">Richard Hughes 2015</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
BIN
docs/website/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
docs/website/img/architecture-plan.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
docs/website/img/dbus.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
docs/website/img/gnome-software1-thumb.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
docs/website/img/gnome-software1.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
docs/website/img/gnome-software2-thumb.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
docs/website/img/gnome-software2.png
Normal file
After Width: | Height: | Size: 57 KiB |
100
docs/website/img/nav-devs.svg
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="94.142853"
|
||||||
|
height="94.142853"
|
||||||
|
viewBox="0 0 94.14285 94.142852"
|
||||||
|
id="svg48042"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="nav-devs.svg">
|
||||||
|
<defs
|
||||||
|
id="defs48044" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1"
|
||||||
|
inkscape:cx="-11.37141"
|
||||||
|
inkscape:cy="75.907192"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1376"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:bbox-paths="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid48871"
|
||||||
|
originx="-3.6083983e-06"
|
||||||
|
originy="0.14284787" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata48047">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-446.69823,-860.95734)">
|
||||||
|
<g
|
||||||
|
transform="translate(160.26965,499.59515)"
|
||||||
|
id="g48765">
|
||||||
|
<circle
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4e9a06;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="circle43602"
|
||||||
|
cx="333.5"
|
||||||
|
cy="408.43362"
|
||||||
|
r="47.071426" />
|
||||||
|
<g
|
||||||
|
style="display:inline"
|
||||||
|
transform="matrix(-2,0,0,2,941.00042,-178.66898)"
|
||||||
|
inkscape:label="builder"
|
||||||
|
id="g27305">
|
||||||
|
<rect
|
||||||
|
y="285.01559"
|
||||||
|
x="295.50021"
|
||||||
|
height="16"
|
||||||
|
width="16"
|
||||||
|
id="rect27307"
|
||||||
|
style="display:inline;opacity:0;fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||||
|
<path
|
||||||
|
id="path27321"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
d="m 299.50023,293.01558 1.06629,1.91069 -0.98216,2.08931 -0.53125,0 0.44712,-2.46875 -1.45313,-0.26562 0.0194,1.73011 -0.57544,-0.004 -0.44398,-1.67945 -0.57812,0.1562 0.0157,2.5 -0.5625,0.0312 -0.82813,-2.5625 1.39553,-1.44525 0.006,-0.98548 2.99242,-0.006 z m 3.40623,-6.01019 a 1.5277282,1.5277282 0 0 1 1.52832,1.52734 1.5277282,1.5277282 0 0 1 -0.12305,0.59473 l 1.49902,1.82031 a 2.5,2.5 0 0 1 0.18946,-0.01 2.5,2.5 0 0 1 2.5,2.5 2.5,2.5 0 0 1 -2.5,2.5 2.5,2.5 0 0 1 -2.5,-2.5 2.5,2.5 0 0 1 0.29394,-1.17089 l -0.87793,-2.20704 a 1.5277282,1.5277282 0 0 1 -0.01,9.8e-4 1.5277282,1.5277282 0 0 1 -1.35645,-0.82715 l -1.95019,0.44824 a 1.5277282,1.5277282 0 0 1 -1.51075,1.30664 1.5277282,1.5277282 0 0 1 -1.52734,-1.52733 1.5277282,1.5277282 0 0 1 1.52734,-1.52832 1.5277282,1.5277282 0 0 1 1.36817,0.85351 l 1.94239,-0.49805 a 1.5277282,1.5277282 0 0 1 1.50683,-1.2832 z m 4.10939,9.60003 1.42579,1.41016 0.9082,0.2207 c 0.0884,0.0276 0.15625,0.13433 0.15625,0.25586 l 0,1.52344 -7.00586,0 0,-1.54492 c 0,-0.14377 0.0693,-0.19958 0.19922,-0.23438 l 0.77539,-0.2207 1.54492,-1.40039 a 3.328125,3.328125 0 0 0 0.98047,0.15234 3.328125,3.328125 0 0 0 1.01562,-0.16211 z"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
125
docs/website/img/nav-hw.svg
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="94.142853"
|
||||||
|
height="94.142853"
|
||||||
|
viewBox="0 0 94.14285 94.142852"
|
||||||
|
id="svg48042"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="nav-hw.svg">
|
||||||
|
<defs
|
||||||
|
id="defs48044" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1"
|
||||||
|
inkscape:cx="-4.0358056"
|
||||||
|
inkscape:cy="88.064222"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1376"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
units="px"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:snap-bbox-midpoints="true"
|
||||||
|
inkscape:bbox-nodes="true"
|
||||||
|
inkscape:bbox-paths="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid48871"
|
||||||
|
originx="-3.6083983e-06"
|
||||||
|
originy="0.14284787" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata48047">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-446.69823,-860.95734)">
|
||||||
|
<g
|
||||||
|
transform="translate(42.269653,499.59515)"
|
||||||
|
id="g48771">
|
||||||
|
<g
|
||||||
|
id="g43614"
|
||||||
|
transform="translate(292,5)">
|
||||||
|
<circle
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||||
|
id="circle43616"
|
||||||
|
cx="159.5"
|
||||||
|
cy="403.43362"
|
||||||
|
r="47.071426" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:label="media-removable"
|
||||||
|
id="g9503"
|
||||||
|
transform="matrix(1.9999998,0,0,1.9999998,194.03088,-543.63768)"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
inkscape:label="input-projector"
|
||||||
|
id="g9435"
|
||||||
|
transform="translate(19.968586,0)">
|
||||||
|
<g
|
||||||
|
inkscape:label="insert-headphones"
|
||||||
|
id="g9437"
|
||||||
|
transform="translate(20.031414,0)">
|
||||||
|
<g
|
||||||
|
inkscape:label="musicplayer"
|
||||||
|
id="g9439"
|
||||||
|
transform="translate(20,0)">
|
||||||
|
<rect
|
||||||
|
y="467"
|
||||||
|
x="61.000198"
|
||||||
|
height="16"
|
||||||
|
width="16.000002"
|
||||||
|
id="rect9441"
|
||||||
|
style="fill:none;stroke:none" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||||
|
d="m 133.0002,473 0,5.06173 c 0,2.7358 -1.784,4.93827 -4,4.93827 -2.216,0 -4,-2.20247 -4,-4.93827 l 0,-5.06173 z"
|
||||||
|
id="rect9463"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssscc" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||||
|
d="m 126.00022,468 0,4 5.99998,0 0,-4 -5.99998,0 z m 0.99998,1 1.00002,0 0,1 -1.00002,0 0,-1 z m 3,0 1.00002,0 0,1 -1.00002,0 0,-1 z"
|
||||||
|
id="rect9466"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
102
docs/website/img/nav-users.svg
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="26.569204mm"
|
||||||
|
height="26.569204mm"
|
||||||
|
viewBox="0 0 94.14285 94.142852"
|
||||||
|
id="svg48042"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="nav-users.svg">
|
||||||
|
<defs
|
||||||
|
id="defs48044" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.35"
|
||||||
|
inkscape:cx="-787.41252"
|
||||||
|
inkscape:cy="422.59513"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1376"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata48047">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-446.69823,-860.81449)">
|
||||||
|
<g
|
||||||
|
transform="translate(277.26966,499.45229)"
|
||||||
|
id="g48757">
|
||||||
|
<circle
|
||||||
|
r="47.071426"
|
||||||
|
cy="408.43362"
|
||||||
|
cx="216.5"
|
||||||
|
id="path38742"
|
||||||
|
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#f57900;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||||
|
<g
|
||||||
|
transform="matrix(2,0,0,2,118.95231,-282.61415)"
|
||||||
|
inkscape:label="avatar-default"
|
||||||
|
id="g6234"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none"
|
||||||
|
id="rect20566"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
x="41.000198"
|
||||||
|
y="337"
|
||||||
|
inkscape:label="a" />
|
||||||
|
<g
|
||||||
|
transform="translate(-577.9998,-648.3622)"
|
||||||
|
id="g3938">
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||||
|
d="m 629.55469,993.45593 c -0.70541,0.62353 -1.53918,0.90625 -2.55469,0.90625 -1.01551,0 -1.85318,-0.29053 -2.55859,-0.91406 -1.10938,0.36328 -2.43603,1.28775 -2.4375,2.90234 L 622,999.36218 c -7.2e-4,0.554 0.446,1.00002 1,1.00002 l 8,0 c 0.554,0 1,-0.44602 1,-1.00002 l 0,-3 c 0,-1.38672 -1.10231,-2.5558 -2.44531,-2.90625 z"
|
||||||
|
id="path3940-5"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csccsssscc" />
|
||||||
|
<circle
|
||||||
|
transform="matrix(1.2,0,0,1.2,567.6,579.36217)"
|
||||||
|
id="path3942-6"
|
||||||
|
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate"
|
||||||
|
cx="49.5"
|
||||||
|
cy="342.5"
|
||||||
|
r="2.5" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
65
docs/website/index.html
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
Licensed under the GNU General Public License Version 2 -->
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>fwupd: Updating Firmware in Linux</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300' rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" media="screen"/>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1 class="banner">fwupd: Updating<br>Firmware in Linux</h1>
|
||||||
|
|
||||||
|
<h1>Introduction</h1>
|
||||||
|
<p>
|
||||||
|
This project aims to make updating firmware on Linux automatic, safe and reliable.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<nav class="buttons">
|
||||||
|
<a id="users" href="users.html">For end users</a>
|
||||||
|
<a id="devs" href="developers.html">For developers</a>
|
||||||
|
<a id="hw" href="vendors.html">For hardware vendors</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h2>About</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To update a BIOS or network card firmware in Linux traditionally meant rebooting into Microsoft Windows, or
|
||||||
|
preparing a MSDOS floppy disk (!) and hoping that everything would
|
||||||
|
work after the update.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Now that we have UEFI as a boot mechanism it's much more important to
|
||||||
|
update firmware on devices, as these updates can fix serious security bugs.
|
||||||
|
Periodically searching a vendor website for updates is a manual and
|
||||||
|
error-prone task and not something we should ask users to do.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Providing a firmware update service actually requires two things:
|
||||||
|
<ol>
|
||||||
|
<li>Vendors providing information about what updates are available for specific hardware</li>
|
||||||
|
<li>A mechanism to actually deploy the firmware onto the hardware itself</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Traditionally firmware is packaged up in a <code>cab</code> file which includes
|
||||||
|
an <code>inf</code> file that describes the update in more detail.
|
||||||
|
We can also add extra metadata so we can have fully localized update descriptions,
|
||||||
|
along with all the usual things you'd expect from an update, for example,
|
||||||
|
security classification and licensing information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="footer">
|
||||||
|
Copyright <a href="mailto:richard@hughsie.com">Richard Hughes 2015</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
60
docs/website/result.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
Licensed under the GNU General Public License Version 2 -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Linux Vendor Firmware Service</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" media="screen"/>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if ($_GET["result"] == 'True')
|
||||||
|
echo '<h1>Result: Success</h1>';
|
||||||
|
else
|
||||||
|
echo '<h1>Result: Failed</h1>';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<table class="history">
|
||||||
|
<tr>
|
||||||
|
<th>Test</th>
|
||||||
|
<th>Result</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function lvfs_result($get_id, $title, $error_msg) {
|
||||||
|
echo '<tr><td>' . $title . '</td><td>';
|
||||||
|
if ($_GET[$get_id] == 'False')
|
||||||
|
echo '☐ ' . $error_msg;
|
||||||
|
else
|
||||||
|
echo '☑ Passed';
|
||||||
|
echo '</td></tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
lvfs_result('authkey', 'Auth Key', 'Did not match any registered vendors');
|
||||||
|
lvfs_result('sizecheck', 'Size Check', 'File was too small or large');
|
||||||
|
lvfs_result('filetype', 'File Type', 'Not a valid <code>cab</code> file');
|
||||||
|
lvfs_result('metadata', 'Metadata', 'The firmware file had no valid metadata');
|
||||||
|
lvfs_result('exists', 'Version Check', 'The firmware file already exists');
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="vendors.html">Go back to the submission page</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="footer">
|
||||||
|
Copyright <a href="mailto:richard@hughsie.com">Richard Hughes 2015</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
172
docs/website/style.css
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
body {
|
||||||
|
background: #fefeff;
|
||||||
|
color: #000000;
|
||||||
|
font-family: "Open Sans", Sans-Serif;
|
||||||
|
font-weight: 400;
|
||||||
|
max-width: 50em;
|
||||||
|
margin: 1em auto;
|
||||||
|
padding: 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
color: #000000;
|
||||||
|
font-family: "Open Sans", Sans-Serif;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.banner {
|
||||||
|
display: block;
|
||||||
|
width: 290px;
|
||||||
|
padding: 230px 0 0 240px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 150px;
|
||||||
|
background: url('banner.svg') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.noteinformation {
|
||||||
|
background: #f5f5ff;
|
||||||
|
border: 1px outset #000000;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
padding: 3px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.upload {
|
||||||
|
width: 60%;
|
||||||
|
margin: 2em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.history {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.history th {
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 120%;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
.history td {
|
||||||
|
padding: .5em .5em .5em 0;
|
||||||
|
font-size: 70%;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.title {
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.footer {
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.caption {
|
||||||
|
color: #000000;
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
color: #000000;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.indextitle {
|
||||||
|
color: #000147;
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.indextitle {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 250%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.title {
|
||||||
|
color: #000000;
|
||||||
|
background-color: #f5f5ff;
|
||||||
|
border: 1px outset #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.caption {
|
||||||
|
border: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: #000000;
|
||||||
|
font: 1.1em 'Courier New', Courier, Fixed;
|
||||||
|
margin-left: .3em;
|
||||||
|
margin-right: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
color: #000000;
|
||||||
|
background: #eeeeee;
|
||||||
|
border: 1px outset #000000;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #147;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #147;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.title {
|
||||||
|
color: #000000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.buttons {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
nav.buttons a {
|
||||||
|
outline: none;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 140px 4px 10px 4px;
|
||||||
|
width: 30%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center 30%;
|
||||||
|
background-size: 96px;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
transition: background-size 200ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.buttons a:hover {
|
||||||
|
background-size: 115px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#users { background-image: url('img/nav-users.svg'); }
|
||||||
|
#devs { background-image: url('img/nav-devs.svg'); }
|
||||||
|
#hw { background-image: url('img/nav-hw.svg'); }
|
||||||
|
|
||||||
|
input.submit {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
outline: none;
|
||||||
|
margin-top: 1em;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-image: linear-gradient(to bottom, #1e5894, #033266);
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
background-image: linear-gradient(to bottom, #3e78b4, #235296);
|
||||||
|
color: white;
|
||||||
|
width: 60%;
|
||||||
|
}
|
125
docs/website/upload.php
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License Version 2
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
include 'db.php';
|
||||||
|
|
||||||
|
$uploaddir = $_ENV["OPENSHIFT_DATA_DIR"] . '/uploads/';
|
||||||
|
|
||||||
|
function lvfs_check_auth($db, $auth_token) {
|
||||||
|
if ($auth_token == '')
|
||||||
|
return False;
|
||||||
|
if (!($stmt = $db->prepare('SELECT * FROM users WHERE guid = ?;')))
|
||||||
|
die("failed to prepare: " . $db->error);
|
||||||
|
$stmt->bind_param("s", $auth_token);
|
||||||
|
if (!$stmt->execute())
|
||||||
|
die("failed to execute: " . $db->error);
|
||||||
|
$res = $stmt->get_result();
|
||||||
|
$stmt->close();
|
||||||
|
if ($res->num_rows > 0)
|
||||||
|
return True;
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lvfs_upload_firmware($db, $auth_token, $uploaddir, $file) {
|
||||||
|
|
||||||
|
$success = False;
|
||||||
|
$uri = 'result.php?';
|
||||||
|
|
||||||
|
# check auth key
|
||||||
|
if (!lvfs_check_auth($db, $auth_token)) {
|
||||||
|
$success = False;
|
||||||
|
$uri = $uri . 'authkey=False&';
|
||||||
|
}
|
||||||
|
|
||||||
|
# check size
|
||||||
|
$size = $file['size'];
|
||||||
|
if ($size > 102400 || $size < 1280) {
|
||||||
|
$success = False;
|
||||||
|
$uri = $uri . 'sizecheck=False&';
|
||||||
|
}
|
||||||
|
|
||||||
|
# check the file is really a cab file
|
||||||
|
$data = file_get_contents($file['tmp_name']);
|
||||||
|
if (strcmp(substr($data,0,4), "MSCF") != 0) {
|
||||||
|
$success = False;
|
||||||
|
$uri = $uri . 'filetype=False&';
|
||||||
|
}
|
||||||
|
|
||||||
|
# check for metadata
|
||||||
|
if (strpos($data, ".metainfo.xml") == FALSE) {
|
||||||
|
$success = False;
|
||||||
|
$uri = $uri . 'metadata=False&';
|
||||||
|
}
|
||||||
|
|
||||||
|
# check the file does not already exist
|
||||||
|
$id = sha1($data);
|
||||||
|
$result = $db->query('SELECT * FROM firmware WHERE hash = "' . $id . '";');
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
$success = False;
|
||||||
|
$uri = $uri . 'exists=False&';
|
||||||
|
}
|
||||||
|
|
||||||
|
# only save if we passed all tests
|
||||||
|
if ($success = True) {
|
||||||
|
$destination = $uploaddir . $id . '.cab';
|
||||||
|
#$destination = $uploaddir . $file['name'];
|
||||||
|
$handle = fopen($destination, "w");
|
||||||
|
if ($handle == FALSE) {
|
||||||
|
header('HTTP/1.0 403 Forbidden');
|
||||||
|
echo 'Write permission for ' . $uploaddir . ' missing';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fwrite($handle, $data) == FALSE) {
|
||||||
|
header('HTTP/1.0 413 Request Entity Too Large');
|
||||||
|
echo 'Failed to write file';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fclose($handle);
|
||||||
|
|
||||||
|
# log to database
|
||||||
|
$success = True;
|
||||||
|
$query = "INSERT INTO firmware (vendor_key, update_contact, addr, timestamp, filename, hash) " .
|
||||||
|
"VALUES (?, ?, ?, CURRENT_TIMESTAMP, ?, ?);";
|
||||||
|
if (!($stmt = $db->prepare($query)))
|
||||||
|
die("failed to prepare: " . $db->error);
|
||||||
|
$stmt->bind_param("sssss",
|
||||||
|
$auth_token,
|
||||||
|
$_POST['update_contact'],
|
||||||
|
$_SERVER['REMOTE_ADDR'],
|
||||||
|
$file['name'],
|
||||||
|
$id);
|
||||||
|
if (!$stmt->execute())
|
||||||
|
die("failed to execute: " . $stmt->error);
|
||||||
|
$stmt->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $uri . 'result=' . $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
# connect to database and upload firmware
|
||||||
|
$db = lvfs_connect_db();
|
||||||
|
$location = lvfs_upload_firmware($db, $_POST['auth'], $uploaddir, $_FILES['file']);
|
||||||
|
lvfs_disconnect_db($db);
|
||||||
|
|
||||||
|
header('Location: ' . $location);
|
||||||
|
|
||||||
|
?>
|
165
docs/website/users.html
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
Licensed under the GNU General Public License Version 2 -->
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>fwupd: Firmware Update Daemon</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300' rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" media="screen"/>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico"/>
|
||||||
|
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1 class="banner">fwupd: Firmware<br> Update Daemon</h1>
|
||||||
|
|
||||||
|
<h1>Introduction</h1>
|
||||||
|
<p>
|
||||||
|
fwupd is a simple daemon to allow session software to update device firmware on
|
||||||
|
your local machine. It's designed for desktops, but this project is
|
||||||
|
also usable on phones, tablets and on headless servers.
|
||||||
|
You can either use a GUI software manager like GNOME Software to view and apply
|
||||||
|
updates, the command-line tool or the system D-Bus interface directly.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Using GNOME Software</h2>
|
||||||
|
<p>
|
||||||
|
New versions of GNOME Software will show and auto-download pending updates automatically:
|
||||||
|
</p>
|
||||||
|
<a href="img/gnome-software1.png"><img alt="gnome-software updates panel" src="img/gnome-software1-thumb.png"/></a>
|
||||||
|
<p>
|
||||||
|
Double clicking on the <code>cab</code> file is also supported:
|
||||||
|
</p>
|
||||||
|
<a href="img/gnome-software2.png"><img alt="gnome-software updates panel" src="img/gnome-software2-thumb.png"/></a>
|
||||||
|
|
||||||
|
<h2>Using the command line</h2>
|
||||||
|
<p>
|
||||||
|
fwupd ships a command line <code>fwupdmgr</code> program.
|
||||||
|
This allows administrators to get the list of upgradable devices,
|
||||||
|
schedule offline updates or installing firmware on the live system.
|
||||||
|
</p>
|
||||||
|
<pre class="prettyprint">
|
||||||
|
$ fwupdmgr get-devices
|
||||||
|
Device: ro__sys_devices_pci0000_00_0000_00_1d_0_usb2_2_1_2_1_4_2_1_4_1_0
|
||||||
|
DisplayName: USB 3.0 VL812 B2 Hub
|
||||||
|
Provider: Udev
|
||||||
|
Guid: 26470009-97a8-4028-867a-bbbac6ee7bf0
|
||||||
|
Version: 9090
|
||||||
|
Internal: False
|
||||||
|
AllowOnline: False
|
||||||
|
AllowOffline: False
|
||||||
|
Device: ro__sys_devices_pci0000_00_0000_00_01_0_0000_01_00_0
|
||||||
|
DisplayName: Barts LE [Radeon HD 6790]
|
||||||
|
Provider: Udev
|
||||||
|
Guid: e9b8eebd-b5f8-18d4-9fbd-d7da7711985c
|
||||||
|
Version: 013.012.000.019.000000
|
||||||
|
Internal: False
|
||||||
|
AllowOnline: False
|
||||||
|
AllowOffline: False
|
||||||
|
Device: CHug-usb:00:01:04:04
|
||||||
|
DisplayName: ColorHugALS
|
||||||
|
Provider: ColorHug
|
||||||
|
Guid: 84f40464-9272-4ef7-9399-cd95f12da696
|
||||||
|
Version: 4.0.0
|
||||||
|
Internal: False
|
||||||
|
AllowOnline: True
|
||||||
|
AllowOffline: True
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
You can see all the command line options using <code>--help</code>:
|
||||||
|
</p>
|
||||||
|
<pre class="prettyprint">
|
||||||
|
$ fwupdmgr --help
|
||||||
|
Usage:
|
||||||
|
fwupdmgr [OPTION…]
|
||||||
|
|
||||||
|
clear-results Clears the results from the last update
|
||||||
|
get-details Gets details about a firmware file
|
||||||
|
get-devices Get all devices that support firmware updates
|
||||||
|
get-results Gets the results from the last update
|
||||||
|
get-updates Gets the list of updates for connected hardware
|
||||||
|
install Install a firmware file on this hardware
|
||||||
|
update-offline Install the update the next time the computer is rebooted
|
||||||
|
update-online Install the update now
|
||||||
|
update-prepared Install prepared updates now
|
||||||
|
|
||||||
|
Help Options:
|
||||||
|
-h, --help Show help options
|
||||||
|
|
||||||
|
Application Options:
|
||||||
|
-v, --verbose Show extra debugging information
|
||||||
|
-f, --force Force the installation of firmware
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Using the D-Bus API</h2>
|
||||||
|
<p>
|
||||||
|
If there are supported devices available then the fwupd daemon will be
|
||||||
|
launched when queried for the first time.
|
||||||
|
This exports an interface that can be queried from any language with
|
||||||
|
a D-Bus binding such as C, Python or Java.
|
||||||
|
</p>
|
||||||
|
<a href="img/dbus.png"><img alt="d-feet screenshot" src="img/dbus.png"/></a>
|
||||||
|
<pre class="prettyprint">
|
||||||
|
$ $ gdbus call --system --dest org.freedesktop.fwupd --object-path / --method org.freedesktop.fwupd.GetDevices
|
||||||
|
({'ro__sys_devices_pci0000_00_0000_00_1d_0_usb2_2_1_2_1_4_2_1_4_1_0':
|
||||||
|
{'Vendor': <'VIA'>,
|
||||||
|
'Guid': <'26470009-97a8-4028-867a-bbbac6ee7bf0'>,
|
||||||
|
'DisplayName': <'USB 3.0 VL812 B2 Hub'>,
|
||||||
|
'Provider': <'Udev'>,
|
||||||
|
'Version': <'9090'>,
|
||||||
|
'Flags': <uint64 0>},
|
||||||
|
'ro__sys_devices_pci0000_00_0000_00_01_0_0000_01_00_0':
|
||||||
|
{'Vendor': <'Advanced Micro Devices, Inc. [AMD/ATI]'>,
|
||||||
|
'Guid': <'e9b8eebd-b5f8-18d4-9fbd-d7da7711985c'>,
|
||||||
|
'DisplayName': <'Barts LE [Radeon HD 6790]'>,
|
||||||
|
'Provider': <'Udev'>,
|
||||||
|
'RomFilename': <'/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/rom'>,
|
||||||
|
'Version': <'013.012.000.019.000000'>,
|
||||||
|
'Flags': <uint64 0>},
|
||||||
|
'CHug-usb:00:01:04:04':
|
||||||
|
{'Guid': <'84f40464-9272-4ef7-9399-cd95f12da696'>,
|
||||||
|
'DisplayName': <'ColorHugALS'>,
|
||||||
|
'Provider': <'ColorHug'>,
|
||||||
|
'Version': <'4.0.0'>,
|
||||||
|
'Flags': <uint64 6>}},)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Security</h2>
|
||||||
|
<p>
|
||||||
|
By default, any users are able to install firmware to removable hardware.
|
||||||
|
The logic here is that if the hardware can be removed, it can easily be moved to
|
||||||
|
a device that the user already has root access on, and asking for authentication
|
||||||
|
would just be security theatre.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For non-removable devices, e.g. UEFI firmware, admin users are able to update
|
||||||
|
trusted firmware without the root password.
|
||||||
|
By default, we already let admin user and root update glibc and the kernel
|
||||||
|
without additional authentication, and these would be a much easier target to backdoor.
|
||||||
|
The firmware updates themselves are signed and have a checksum, and the metadata
|
||||||
|
describing this checksum is provided by the distribution either as
|
||||||
|
GPG-signed repository metadata, or installed from a package, which is
|
||||||
|
expected to also be signed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>User Interaction</h2>
|
||||||
|
<p>
|
||||||
|
No user interaction should be required when actually applying updates.
|
||||||
|
Making it prohibited means we can do the upgrade with a fancy graphical
|
||||||
|
splash screen, without having to worry about locales and input methods.
|
||||||
|
Updating firmware should be no more dangerous than installing a new kernel
|
||||||
|
or glibc package.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="index.html">Go back to the main page</a></p>
|
||||||
|
|
||||||
|
<p class="footer">
|
||||||
|
Copyright <a href="mailto:richard@hughsie.com">Richard Hughes 2015</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
198
docs/website/vendors.html
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
|
||||||
|
Licensed under the GNU General Public License Version 2 -->
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Linux Vendor Firmware Service</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300' rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" href="style.css" type="text/css" media="screen"/>
|
||||||
|
<link rel="shortcut icon" href="favicon.ico"/>
|
||||||
|
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1 class="banner">Linux Vendor<br>Firmware Service</h1>
|
||||||
|
|
||||||
|
<h1>Introduction</h1>
|
||||||
|
<p>
|
||||||
|
This page provides a place for hardware vendors to submit packaged
|
||||||
|
firmware updates, typically <code>cab</code> files.
|
||||||
|
This <em>fire-and-forget</em> service allows vendors to submit firmware updates
|
||||||
|
without generating and hosting metadata themselves.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Clients such as <a href="https://github.com/hughsie/fwupd/blob/master/README.md">fwupd</a>
|
||||||
|
periodically check for updated metadata at this site and will offer the firmware
|
||||||
|
to end users or be installed automatically depending on site policy.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
NOTE: This service should only be used to distribute firmware that is
|
||||||
|
<em>flashed</em> onto non-volatile memory.
|
||||||
|
It is not designed for firmware that has to be uploaded to devices every time
|
||||||
|
the device is used.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
There is no charge to vendors for the hosting or distribution of content.
|
||||||
|
</p>
|
||||||
|
<p>When files are submitted the following actions are performed:</p>
|
||||||
|
<ol>
|
||||||
|
<li>The update metadata is <a href="https://github.com/hughsie/fwupd/blob/master/README.md#what-do-i-have-to-do">checked for correctness</a>.</li>
|
||||||
|
<li>The firmware capsule is signed with <a href="mooo">our GPG key</a>.</li>
|
||||||
|
<li>The new <code>cab</code> file is moved to <a href="dump.php">our infrastructure</a>.</li>
|
||||||
|
<li>The metadata is added to <a href="downloads/firmware.xml.gz">our database</a>.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h1>Upload Firmware</h1>
|
||||||
|
<p>
|
||||||
|
<b>It is imperative that updates have been verified to work correctly on
|
||||||
|
all matching hardware.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Legal</h2>
|
||||||
|
<p>By uploading a firmware file you must agree that:</p>
|
||||||
|
<ul>
|
||||||
|
<li>You are legally permitted to submit the firmware.</li>
|
||||||
|
<li>The submitted firmware file is permitted to be mirrored by our site.</li>
|
||||||
|
<li>The firmware installation must complete without requiring user input.</li>
|
||||||
|
<li>Firmware must not engage in malicious activity (e.g. be viruses, worms, or exploit security issues).</li>
|
||||||
|
<li>Firmware can only be removed from this archive in exceptional cases.</li>
|
||||||
|
</ul>
|
||||||
|
<form action="upload.php" method="post" enctype="multipart/form-data">
|
||||||
|
<table class="upload">
|
||||||
|
<tr>
|
||||||
|
<th width="150px">Vendor Key:</th>
|
||||||
|
<td><input type="text" id="auth" name="auth" placeholder="5be94d63-58d2-410e-bc49-eecb22637a8e" required size="36"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr><th width="150px">Contact Email:</th><td><input type="email" name="update_contact" required size="36"/></td></tr>
|
||||||
|
<tr><th width="150px">Firmware:</th><td><input type="file" name="file" required/></td></tr>
|
||||||
|
</table>
|
||||||
|
<input type="submit" class="submit" value="Upload"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h1>Help With Submitting Firmware</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you are <b>not</b> using the UEFI capsule update method you need to write a
|
||||||
|
plugin for fwupd to trigger the firmware update from userspace.
|
||||||
|
At the moment there is just UEFI and ColorHug providers, but others are welcome.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As per the <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/dn917810%28v=vs.85%29.aspx">Microsoft guidelines</a>
|
||||||
|
package up your firmware into a <code>cab</code> file, with these files inside:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>The actual <code>cap</code> file your engineers have created</li>
|
||||||
|
<li>The <code>inf</code> file <a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff547402%28v=vs.85%29.aspx">describing the .cap file</a>.</li>
|
||||||
|
<li>The optional <code>asc</code> file which is a detached GPG signature of the firmware file.</li>
|
||||||
|
<li>The optional <code>metainfo.xml</code> file with <a href="http://www.freedesktop.org/software/appstream/docs/sect-Quickstart-Addons.html">a long description and extra metadata</a></li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
You can create a <code>cab</code> file using <code>makecab.exe</code> on Windows and <code>gcab --create</code>
|
||||||
|
on Linux.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
It is recommended you name the <code>cab</code> file with the hardware name and the version
|
||||||
|
number, e.g. <code>colorhug-als-1.2.3.cab</code>. It's mandatory that the files inside the
|
||||||
|
<code>cab</code> file have the same basename, for example this is would be valid:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<pre>
|
||||||
|
colorhug2-1.2.3.cab
|
||||||
|
|- firmware.inf
|
||||||
|
|- firmware.bin
|
||||||
|
|- firmware.bin.asc
|
||||||
|
\- firmware.metainfo.xml
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
An example <code>inf</code> file looks like this:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<pre class="prettyprint lang-sh">
|
||||||
|
[Version]
|
||||||
|
Class=Firmware
|
||||||
|
ClassGuid={f2e7dd72-6468-4e36-b6f1-6488f42c1b52}
|
||||||
|
DriverVer=03/03/2015,3.0.2
|
||||||
|
|
||||||
|
[Firmware_CopyFiles]
|
||||||
|
firmware.bin
|
||||||
|
|
||||||
|
[Firmware_AddReg]
|
||||||
|
HKR,,FirmwareId,,{84f40464-9272-4ef7-9399-cd95f12da696}
|
||||||
|
HKR,,FirmwareVersion,%REG_DWORD%,0x0000000
|
||||||
|
HKR,,FirmwareFilename,,firmware.bin
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
An example <code>metainfo.xml</code> file looks like this:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<pre class="prettyprint">
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Copyright 2015 Richard Hughes <richard@hughsie.com> -->
|
||||||
|
<component type="firmware">
|
||||||
|
<id>84f40464-9272-4ef7-9399-cd95f12da696</id>
|
||||||
|
<name>ColorHugALS Firmware</name>
|
||||||
|
<summary>Firmware for the ColorHugALS Ambient Light Sensor</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Updating the firmware on your ColorHugALS device improves performance and
|
||||||
|
adds new features.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
<url type="homepage">http://www.hughski.com/</url>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-2.0+</project_license>
|
||||||
|
<developer_name>Hughski Limited</developer_name>
|
||||||
|
<releases>
|
||||||
|
<release version="3.0.2" timestamp="1424116753">
|
||||||
|
<location>http://www.hughski.com/downloads/colorhug-als/firmware/colorhug-als-3.0.2.cab</location>
|
||||||
|
<description>
|
||||||
|
<p>This stable release fixes the following bugs:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Fix the return code from GetHardwareVersion</li>
|
||||||
|
<li>Scale the output of TakeReadingRaw by the datasheet values</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
|
</component>
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If the firmware is not free software you have to indicate it in the
|
||||||
|
<code>metainfo.xml</code> file with <code><project_license>proprietary</project_license></code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Why does the LVFS project sign my firmware?</h2>
|
||||||
|
<p>
|
||||||
|
The Linux Vendor Firmware Project signs the firmware image and repacks
|
||||||
|
the files into a new cabinet file for several reasons:
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Only trusted vendors have access to the LVFS service, so we can be sure the firmware actually came from the vendor</li>
|
||||||
|
<li>Clients do not (yet) verify the signatures in the <code>cat</code> file</li>
|
||||||
|
<li>Not all software trusts the Microsoft WHQL certificate</li>
|
||||||
|
<li>We ensure that only required files are included in the cabinet file, typically making the download size much smaller</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Validation</h2>
|
||||||
|
<p>
|
||||||
|
The best way to validate the metainfo file or firmware before submission is by using the
|
||||||
|
<code>appstream-util validate</code> tool available from the
|
||||||
|
<a href="https://github.com/hughsie/appstream-glib">appstream-glib</a> project.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><a href="index.html">Go back to the main page</a></p>
|
||||||
|
|
||||||
|
<p class="footer">
|
||||||
|
Copyright <a href="mailto:richard@hughsie.com">Richard Hughes 2015</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|