My Love Affair with Synology

In my "Hodge Podge" article in the October 2016 issue, I mentioned how much I love the Synology NAS I have in my server closet (Figure 1). more>>

ONF/ON.Lab's ONOS Project

Networks have become indispensable infrastructure in modern society. The danger is that these networks tend to be closed, proprietary, complex, operationally expensive and inflexible, all of which impede innovation and progress rather than enable them. more>>

Never Trust Yellow Fruit

You've probably heard about the WiFi Pineapple from Hak5. It's a fascinating device that allows you to do some creepy pen testing. It's the sort of tool that could be used for evil, but it's also incredibly useful for securing networks. more>>

Recharge sans contact, récupération d'énergie et CEM - Lyon (69) Le 19 septembre 2017

CAP'tronic et Wurth Elektronik France vous proposent un séminaire sur la CEM, la recharge sans contact et "l'energy harvesting".
Cette journée vous permettra d'avoir un rapide tour d'horizon des principales exigences liées à la compatibilité électromagnétique, des performances des systèmes de transfert d'énergie par induction et de récupération d'énergie.

Inscription en ligne

Intervenants :
Alain LAFUENTE - Wurth Elektronik France, Jean-Marc ALLOUA - CAP'Tronic

PROGRAMME

  • 9H00-9h05 Présentation du programme CAP'Tronic
  • 9h05- 10H15 Introduction à la CEM
  • 10H15-10H30 Pause-café
  • 10H30-12H00 Quelles sont les différentes sources de bruit et leur mode de propagation dans un système électronique
    Méthode de filtrage de mode différentiel et de mode commun
  • 12H00-13H30 Déjeuner/Buffet
  • 13H30-15H00 Transfert d'énergie sans contact
    Les différents standard sur le marché et leur fonctionnement
    Simulation
  • 15H00-15H15 Pause
  • 15H30-16H15 Récolte d'énergie
    Bilan d'énergie d'un système et choix du transducteur
    Simulation
  • 16H15-16H30 Questions/réponses

INFORMATIONS PRATIQUES

Personnes concernées : Ingénieurs, Techniciens, Chefs d'entreprises.

Date : Le 19 septembre 2017

Lieu de l'événement :
KOHE MEETING
45 Quai Rambaud
69002 Lyon

Contact : Jean-Marc ALLOUA
Contact inscription : Dorothée WALLART - 04 38 78 37 36

Prix : Gratuit. Repas en commun pris en charge par CAPTRONIC.

Five Reasons to Love SAP HANA

Five Reasons to Love SAP HANA
If you are reading a blog on SAP HANA, you probably already know that it is an in-memory data platform built to handle massive amounts of data in real time. You probably already know that it can be deployed as an on-premises appliance or purchased as a hybrid or cloud service. more>>

BlueCat DNS Edge

Migration to the cloud, the flexibility of network virtualization and the promise of IoT involve IT transformations that have placed incredible strain on enterprise security. more>>

Free and ready-to-use cross-compilation toolchains

For all embedded Linux developers, cross-compilation toolchains are part of the basic tool set, as they allow to build code for a specific CPU architecture and debug it. Until a few years ago, CodeSourcery was providing a lot of high quality pre-compiled toolchains for a wide range of architectures, but has progressively stopped doing so. Linaro provides some freely available toolchains, but only targetting ARM and AArch64. kernel.org has a set of pre-built toolchains for a wider range of architectures, but they are bare metal toolchains (cannot build Linux userspace programs) and updated infrequently.

To fill in this gap, Free Electrons is happy to announce its new service to the embedded Linux community: toolchains.free-electrons.com.

Free Electrons toolchains

This web site provides a large number of cross-compilation toolchains, available for a wide range of architectures, in multiple variants. The toolchains are based on the classical combination of gcc, binutils and gdb, plus a C library. We currently provide a total of 138 toolchains, covering many combinations of:

  • Architectures: AArch64 (little and big endian), ARC, ARM (little and big endian, ARMv5, ARMv6, ARMv7), Blackfin, m68k (Coldfire and 68k), Microblaze (little and big endian), MIPS32 and MIPS64 (little and big endian, with various instruction set variants), NIOS2, OpenRISC, PowerPC and PowerPC64, SuperH, Sparc and Sparc64, x86 and x86-64, Xtensa
  • C libraries: GNU C library, uClibc-ng and musl
  • Versions: for each combination, we provide a stable version which uses slightly older but more proven versions of gcc, binutils and gdb, and we provide a bleeding edge version with the latest version of gcc, binutils and gdb.

After being generated, most of the toolchains are tested by building a Linux kernel and a Linux userspace, and booting it under Qemu, which allows to verify that the toolchain is minimally working. We plan on adding more tests to validate the toolchains, and welcome your feedback on this topic. Of course, not all toolchains are tested this way, because some CPU architectures are not emulated by Qemu.

The toolchains are built with Buildroot, but can be used for any purpose: build a Linux kernel or bootloader, as a pre-built toolchain for your favorite embedded Linux build system, etc. The toolchains are available in tarballs, together with licensing information and instructions on how to rebuild the toolchain if needed.

We are very much interested in your feedback about those toolchains, so do not hesitate to report bugs or make suggestions in our issue tracker!

This work was done as part of the internship of Florent Jacquet at Free Electrons.

Jetico's BestCrypt Container Encryption for Linux

Cyber-attacks are now constant, threats to privacy are increasing, and more rigid regulations are looming worldwide. To help IT folks relax in the face of these challenges, Jetico updated its BestCrypt Container Encryption solution to include Container Guard. more>>

À nouveau disponible en kiosque : le guide spécial base de données MySQL/MariaDB !

Vous l’avez manqué ? Sachez que notre hors-série « Base de données MySQL/MariaDB » est de retour en kiosque dès aujourd’hui ! À travers ses 5 étapes, vous apprendrez à créer votre propre base de données. Vous découvrirez tout d’abord comment concevoir celle-ci, comment installer votre SGDBR, utiliser le langage SQL pour accéder à votre base, et enfin comment sécuriser cette dernière ! Ce guide complet vous attend également sur notre boutique ainsi que sur notre plateforme de lecture en ligne Connect

Au sommaire

Étape 1 : je conçois ma base de données

p. 08 Comprendre les bases de données relationnelles

p. 22 Utiliser l’interface graphique MySQL Workbench

Étape 2 : j’installe mon SGBDR MySQL MariaDB

p. 34 Choisir MySQL ou MariaDB et l’installer

Étape 3 : j’utilise le langage SQL pour accéder à ma base

p. 50 Utilisez correctement l’instruction Select pour vos requêtes

p. 68 Augmentez les performances de vos bases de données avec les index

Étape 4 : je sécurise ma base et l’accès à mes données

p. 80 Sécurisez votre base MariaDB à l’aide de plugins

Étape 5 : je crée des programmes utilisant mes bases de données

p. 90 Accédez à vos données en C++ avec sqlpp11

p. 104 Utilisez MySQL avec l’API REST et Python

p. 114 Découvrez les nouvelles fonctions natives SQL pour manipuler du contenu JSON

À nouveau disponible en kiosque : le guide spécial base de données MySQL/MariaDB !

Vous l’avez manqué ? Sachez que notre hors-série « Base de données MySQL/MariaDB » est de retour en kiosque dès aujourd’hui ! À travers ses 5 étapes, vous apprendrez à créer votre propre base de données. Vous découvrirez tout d’abord comment concevoir celle-ci, comment installer votre SGDBR, utiliser le langage SQL pour accéder à votre base, et enfin comment sécuriser cette dernière ! Ce guide complet vous attend également sur notre boutique ainsi que sur notre plateforme de lecture en ligne Connect

Au sommaire

Étape 1 : je conçois ma base de données

p. 08 Comprendre les bases de données relationnelles

p. 22 Utiliser l’interface graphique MySQL Workbench

Étape 2 : j’installe mon SGBDR MySQL MariaDB

p. 34 Choisir MySQL ou MariaDB et l’installer

Étape 3 : j’utilise le langage SQL pour accéder à ma base

p. 50 Utilisez correctement l’instruction Select pour vos requêtes

p. 68 Augmentez les performances de vos bases de données avec les index

Étape 4 : je sécurise ma base et l’accès à mes données

p. 80 Sécurisez votre base MariaDB à l’aide de plugins

Étape 5 : je crée des programmes utilisant mes bases de données

p. 90 Accédez à vos données en C++ avec sqlpp11

p. 104 Utilisez MySQL avec l’API REST et Python

p. 114 Découvrez les nouvelles fonctions natives SQL pour manipuler du contenu JSON

SQL Server on Linux

When Wim Coekaerts, Microsoft's vice president for open source, took the stage at LinuxCon 2016 in Toronto last summer, he came not as an adversary, but as a longtime Linux enthusiast promising to bring the power of Linux to Microsoft and vice versa. With the recent launch of SQL Server for Linux, Coekaerts is clearly having an impact. more>>

Low Tech High Tech

Google Cardboard should be terrible. Really, it should. It's literally made of cardboard. I remember as a kid some cereal boxes came with spy glasses you had to cut out of the box itself—and they were terrible. But Google Cardboard is amazing. Granted, you need to add your $750 Android phone to it, but that's already in your pocket anyway. more>>

Android Candy: the Verbification of Video Chat

People who study the history of languages probably will look back at our current time and scratch their heads. We keep inventing verbs! First, Google became the verb we use for searching. Then, "Facebooking" someone became a viable way to contact them. Heck, I forgot about "texting" someone. It seems we just keep taking perfectly good nouns and making them verbs. more>>

Why the Largest Companies in the World Count on Linux Servers

IBM Linux
Linux started its life in the data center as a cheaper alternative to UNIX. At the time, UNIX operating systems ruled the industry and for good reason. They were performant, fault tolerant and extremely stable. They also were very expensive and ran on very proprietary hardware. more>>

Is the Moon Waxing or Waning?

In my last article, I talked about the complications of calculating the phase of the moon and decided simply to scrape the same website that Google uses. more>>

Elixir Cross Referencer: new way to browse kernel sources

Today, we are pleased to announce the initial release of the Elixir Cross-Referencer, or just “Elixir”, for short.

What is Elixir?

Elixir home pageSince 2006, we have provided a Linux source code cross-referencing online tool as a service to the community. The engine behind this website was LXR, a Perl project almost as old as the kernel itself. For the first few years, we used the then-current 0.9.5 version of LXR, but in early 2009 and for various reasons, we reverted to the older 0.3.1 version (from 1999!). In a nutshell, it was simpler and it scaled better.

Recently, we had the opportunity to spend some time on it, to correct a few bugs and to improve the service. After studying the Perl source code and trying out various cross-referencing engines (among which LXR 2.2 and OpenGrok), we decided to implement our own source code cross-referencing engine in Python.

Why create a new engine?

Our goal was to extend our existing service (support for multiple projects, responsive design, etc.) while keeping it simple and fast. When we tried other cross-referencing engines, we were dissatisfied with their relatively low performance on a large codebase such as Linux. Although we probably could have tweaked the underlying database engine for better performance, we decided it would be simpler to stick to the strategy used in LXR 0.3: get away from the relational database engine and keep plain lists in simple key-value stores.

Another reason that motivated a complete rewrite was that we wanted to provide an up-to-date reference (including the latest revisions) while keeping it immutable, so that external links to the source code wouldn’t get broken in the future. As a direct consequence, we would need to index many different revisions for each project, with potentially a lot of redundant information between them. That’s when we realized we could leverage the data model of Git to deal with this redundancy in an efficient manner, by indexing Git blobs, which are shared between revisions. In order to make sure queries under this strategy would be fast enough, we wrote a proof-of-concept in Python, and thus Elixir was born.

What service does it provide?

First, we tried to minimize disruption to our users by keeping the user interface close to that of our old cross-referencing service. The main improvements are:

  • We now support multiple projects. For now, we provide reference for Linux, Busybox and U-Boot.
  • Every tag in each project’s git repository is now automatically indexed.
  • The design has been modernized and now fits comfortably on smaller screens like tablets.
  • The URL scheme has been simplified and extended with support for multiple projects. An HTTP redirector has been set up for backward compatibility.
Elixir supports multiple projects

Elixir supports multiple projects

Among other smaller improvements, it is now possible to copy and paste code directly without line numbers getting in the way.

How does it work?

Elixir is made of two Python scripts: “update” and “query”. The first looks for new tags and new blobs inside a Git repository, parses them and appends the new references to identifiers to a record inside the database. The second uses the database and the Git repository to display annotated source code and identifier references.

The parsing itself is done with Ctags, which provides us with identifier definitions. In order to find the references to these identifiers, Elixir then simply checks each lexical token in the source file against the definition database, and if that word is defined, a new reference is added.

Like in LXR 0.3, the database structure is kept very simple so that queries don’t have much work to do at runtime, thus speeding them up. In particular, we store references to a particular identifier as a simple list, which can be loaded and parsed very fast. The main difference with LXR is that our list includes references from every blob in the project, so we need to restrict it first to only the blobs that are part of the current version. This is done at runtime, simply by computing the intersection of this list with the list of blobs inside the current version.

Finally, we kept the user interface code clearly segregated from the engine itself by making these two modules communicate through a Unix command-line interface. This means that you can run queries directly on the command-line without going through the web interface.

Elixir code example

Elixir code example

What’s next?

Our current focus is on improving multi-project support. In particular, each project has its own quirky way of using Git tags, which needs to be handled individually.

At the user-interface level, we are evaluating the possibility of having auto-completion and/or fuzzy search of identifier names. Also, we are looking for a way to provide direct line-level access to references even in the case of very common identifiers.

On the performance front, we would like to cut the indexation time by switching to a new database back-end that provides efficient appending to large records. Also, we could make source code queries faster by precomputing the references, which would also allow us to eliminate identifier “bleeding” between versions (the case where an identifier shows up as “defined in 0 files” because it is only defined in another version).

If you think of other ways we could improve our service, don’t hesitate to drop us a feature request or a patch!

Bonus: why call it “Elixir”?

In the spur of the moment, it seemed like a nice pun on the name “LXR”. But in retrospect, we wish to apologize to the Elixir language team and the community at large for unnecessary namespace pollution.

Listen to Me Cheaply

I listen to a lot of books. A lot. And honestly, although I've written about the "Listen" app for audiobooks, I tend to use Audible more than anything else anymore. Part of the reason is the Android app finally has more fine-grained speed settings. (I prefer around 1.4x speed.) iPhone people don't have that seemingly simple feature. Just saying. more>>

AdaCore's GNAT Pro, CodePeer, QGen and SPARK Pro

AdaCore recently announced the concurrent annual release of four flagship products in its portfolio of software development and verification tools for mission-critical, safety-critical and security-critical systems. These include version 17.1 of GNAT Pro, CodePeer, QGen and SPARK Pro. more>>

Beyond boot testing: custom tests with LAVA

Since April 2016, we have our own automated testing infrastructure to validate the Linux kernel on a large number of hardware platforms. We use this infrastructure to contribute to the KernelCI project, which tests every day the Linux kernel. However, the tests being done by KernelCI are really basic: it’s mostly booting a basic Linux system and checking that it reaches a shell prompt.

However, LAVA, the software component at the core of this testing infrastructure, can do a lot more than just basic tests.

The need for custom tests

With some of our engineers being Linux maintainers and given all the platforms we need to maintain for our customers, being able to automatically test specific features beyond a simple boot test was a very interesting goal.

In addition, manually testing a kernel change on a large number of hardware platforms can be really tedious. Being able to quickly send test jobs that will use an image you built on your machine can be a great advantage when you have some new code in development that affects more than one board.

We identified two main use cases for custom tests:

  • Automatic tests to detect regression, as does KernelCI, but with more advanced tests, including platform specific tests.
  • Manual tests executed by engineers to validate that the changes they are developing do not break existing features, on all platforms.

Overall architecture

Several tools are needed to run custom tests:

  • The LAVA instance, which controls the hardware platforms to be tested. See our previous blog posts on our testing hardware infrastructrure and software architecture
  • An appropriate root filesystem, that contains the various userspace programs needed to execute the tests (benchmarking tools, validation tools, etc.)
  • A test suite, which contains various scripts executing the tests
  • A custom test tool that glues together the different components

The custom test tool knows all the hardware platforms available and which tests and kernel configurations apply to which hardware platforms. It identifies the appropriate kernel image, Device Tree, root filesystem image and test suite and submits a job to LAVA for execution. LAVA will download the necessary artifacts and run the job on the appropriate device.

Building custom rootfs

When it comes to test specific drivers, dedicated testing, validation or benchmarking tools are sometimes needed. For example, for storage device testing, bonnie++ can be used, while iperf is nice for networking testing. As the default root filesystem used by KernelCI is really minimalist, we need to build our owns, one for each architecture we want to test.

Buildroot is a simple yet efficient tool to generate root filesystems, it is also used by KernelCI to build their minimalist root filesystems. We chose to use it and made custom configuration files to match our needs.

We ended up with custom rootfs built for ARMv4, ARMv5, ARMv7, and ARMv8, that embed for now Bonnie++, iperf, ping (not the Busybox implementation) and other tiny tools that aren’t included in the default Buildroot configuration.

Our Buildroot fork that includes our custom configurations is available as the buildroot-ci Github project (branch ci).

The custom test tool

The custom test tool is the tool that binds the different elements of the overall architecture together.

One of the main features of the tool is to send jobs. Jobs are text files used by LAVA to know what to do with which device. As they are described in LAVA as YAML files (in the version 2 of the API), it is easy to use templates to generate them based on a single model. Some information is quite static such as the device tree name for a given board or the rootfs version to use, but other details change for every job such as the kernel to use or which test to run.

We made a tool able to get the latest kernel images from KernelCI to quickly send jobs without having a to compile a custom kernel image. If the need is to test a custom image that is built locally, the tool is also able to send files to the LAVA server through SSH, to provide a custom kernel image.

The entry point of the tool is ctt.py, which allows to create new jobs, providing a lot of options to define the various aspects of the job (kernel, Device Tree, root filesystem, test, etc.).

This tool is written in Python, and lives in the custom_tests_tool Github project.

The test suite

The test suite is a set of shell scripts that perform tests returning 0 or 1 depending on the result. This test suite is included inside the root filesystem by LAVA as part of a preparation step for each job.

We currently have a small set of tests:

  • boot test, which simply returns 0. Such a test will be successful as soon as the boot succeeds.
  • mmc test, to test MMC storage devices
  • sata test, to test SATA storage devices
  • crypto test, to do some minimal testing of cryptographic engines
  • usb test, to test USB functionality using mass storage devices
  • simple network test, that just validates network connectivity using ping

All those tests only require the target hardware platform itself. However, for more elaborate network tests, we needed to get two devices to interact with each other: the target hardware platform and a reference PC platform. For this, we use the LAVA MultiNode API. It allows to have a test that spans multiple devices, which we use to perform multiple iperf sessions to benchmark the bandwidth. This test has therefore one part running on the target device (network-board) and one part running on the reference PC platform (network-laptop).

Our current test suite is available as the test_suite Github project. It is obviously limited to just a few tests for now, we hope to extend the tests in the near future.

First use case: daily tests

As previously stated, it’s important for us to know about regressions introduced in the upstream kernel. Therefore, we have set up a simple daily cron job that:

  • Sends custom jobs to all boards to validate the latest mainline Linux kernel and latest linux-nextli>
  • Aggregates results from the past 24 hours and sends emails to subscribed addresses
  • Updates a dashboard that displays results in a very simple page

A nice dashboard showing the tests of the Beaglebone Black and the Nitrogen6x.

Second use case: manual tests

The custom test tool ctt.py has a simple command line interface. It’s easy for someone to set it up and send custom jobs. For example:

ctt.py -b beaglebone-black -m network

will start the network test on the BeagleBone Black, using the latest mainline Linux kernel built by KernelCI. On the other hand:

ctt.py -b armada-7040-db armada-8040-db -t mmc --kernel arch/arm64/boot/Image --dtb-folder arch/arm64/boot/dts/

will run the mmc test on the Marvell Armada 7040 and Armada 8040 development boards, using the locally built kernel image and Device Tree.

The result of the job is sent over e-mail when the test has completed.

Conclusion

Thanks to this custom test tool, we now have an infrastructure that leverages our existing lab and LAVA instance to execute more advanced tests. Our goal is now to increase the coverage, by adding more tests, and run them on more devices. Of course, we welcome feedback and contributions!

Matinale : "Nautisme & plaisance : quelles sont les opportunités pour l'économie numérique ? - Saint-Malo (35) Le 29 juin 2017

CAP'TRONIC s'associe à Rennes Atalante pour sa prochaine Matinale sur le thème "Nautisme & plaisance : quelles sont les opportunités pour l'économie numérique ?" qui aura lieu à Saint-Malo.

Programme


Interventions de :

- Sabrina Pincet, chargée d'étude à Bretagne Développement Innovation
- Régis Guyon, animateur de l'axe Naval et nautisme au Pôle Mer Bretagne Atlantique
- Cyril Boissy, responsable de l'activité Balises chez Syrlinks
- Fabrice Barbin, dirigeant de Synergiz

Ils aborderont les points suivants :

- Panorama de la filière nautisme en Bretagne.
- Quels sont les principaux enjeux et quels sont ceux pour lesquels le numérique peut apporter des réponses ?
- Actions et projets compétitifs du Pôle Mer Bretagne sur la filière nautique au croisement du numérique : quels sont les technologies et les domaines porteurs (construction, maintenance, sécurité, navigation, nouveaux usages, services…) ?
- Vision et stratégie de l'entreprise Syrlinks pour développer des produits technologiques grand public.
- Depuis l'analyse des usages, Synergiz décline des solutions pures numériques au monde du nautisme. Exemple du projet HoloSail.

Inscription en ligne

Contact : Rennes Atalante - Tél : 02 99 12 73 73

Introduction à la programmation UEFI – Réalisation d’un PONG!

L’UEFI, c’est quoi ?

De plus en plus d’ordinateurs portables vendus aujourd’hui sur le marché sont équipés de firmwares UEFI : “Unified Extensible Firmware Interface”. En effet, ce nouveau standard vient remplacer les EFI qui sont eux-mêmes apparus en remplacement du BIOS qui commençait à connaître ses limites. Pourtant mal accueilli lors de son apparition, l’UEFI apporte des avancées majeures par rapport à ses prédécesseurs, avec notamment, la prise en charge de la souris et des graphismes avancés.

L’UEFI a pour principal but, comme son nom l’indique, d’unifier, de standardiser la norme EFI. En effet, les BIOS ne devant respecter aucune spécification particulière*, les constructeurs étaient libres de choisir leurs propres conventions. Ainsi, cela rendait le développement de programmes dits Bare Metal (c’est-à-dire tournant directement après le démarrage de la machine, sans système d’exploitation ni aucune autre couche d’abstraction) plus compliqué et surtout non portable. La dernière spécification de l’UEFI à ce jour peut être trouvée à l’adresse http://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6%20Errata%20A%20final.pdf , cette version sera utilisée tout au long de ce tutoriel.

 

* La présence de la table d’interruptions des BIOS montre la volonté d’uniformiser ces derniers. Cependant, certaines de ces interruptions ne sont pas implémentées de la même manière, voire pas du tout, d’un ordinateur à l’autre. Cette table est trouvable ici : https://en.wikipedia.org/wiki/BIOS_interrupt_call#Interrupt_table

Le kit de développement

EDK II et GNU-EFI

Deux principaux kits de développement existent pour faire du développement : UEFI: EDK II et Gnu-efi. Chacun présente des avantages et des inconvénients.

Le premier est complet, possède des librairies assez riches ainsi qu’une documentation trouvable facilement (http://www.bluestop.org/edk2/docs/trunk/index.html). Cependant, il est plus long de mettre en place un simple Hello World étant donné que sa compilation mène à la modification de fichiers de configuration du kit, les .dsc notamment.

Le second est léger, simple à installer et à utiliser: un Makefile classique permet de compiler les programmes. Les librairies fournies et la documentation sont toutes aussi légères.

Pour ce tutoriel, notre choix s’est porté sur l’EDK II, un guide d’installation avec la mise en place d’un Hello World peut être trouvé à cette adresse (guide en anglais) : https://github.com/tianocore/tianocore.github.io/wiki/Getting-Started-with-EDK-II .

Quant aux conventions de codage de l’EDK II, elles peuvent être trouvées à cette adresse http://cran.org.uk/edk2/docs/specs/EDK2_C_Coding_Standards_Specification.pdf

Compilation et tests

Afin de tester un programme écrit, il faut le compiler avec l’EDK II, dont le procédé est décrit dans le guide du lien ci-dessus, puis, le fichier .EFI généré doit être mis sous le nom de BOOTX64.EFI (pour les machines 64bits) sur une clé USB FAT16 ou FAT32 afin de former l’arborescence suivante :

└── EFI
    └── BOOT
       └── BOOTX64.EFI

Tout au long de ce tutoriel, les tests ont été effectués sur un Dell Latitude E5520 muni d’un BIOS/UEFI en version A05. Afin de démarrer sur clé USB en mode UEFI sur cette machine, il faut la démarrer en appuyant sur F12, puis en sélectionnant BIOS Setup. Une fenêtre apparaît, cliquez  (ou sélectionnez) Boot Sequence, qui se trouve dans la catégorie Général, puis cochez l’option UEFI. Il est ensuite possible de choisir l’ordre de préférence de démarrage. Un simple redémarrage est nécessaire pour démarrer sur la clé.
Note: Si le démarrage n’est pas automatique, il faut sélectionner la clé usb dans le menu qui s’affiche lors de l’appui sur F12 au démarrage.
Le fichier .inf utilisé pour la compilation du projet est le suivant (trouvable avec les sources dont le lien est fourni à la fin de cet article) :

# Pong.inf
[Defines]
INF_VERSION = 1.25
BASE_NAME = Pong
FILE_GUID = 82d8802a-1a10-4651-8279-b7e82d1e8126
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
[Sources]
Pong.c

[Packages]
MdePkg/MdePkg.dec

[LibraryClasses]
UefiApplicationEntryPoint
UefiLib

[Guids]

[Ppis]

[Protocols]

[FeaturePcd]

[Pcd]

Les fichiers d’en-tête inclus dans notre projet sont les suivants :

#include <Uefi.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Protocol/GraphicsOutput.h>

PONG!

Afin de commencer à développer pour UEFI, lançons-nous dans le codage du classique Pong. Notre choix s’est porté sur Pong car il permet d’utiliser des avancées intéressantes de l’UEFI comme l’affichage graphique ou la gestion des événements du clavier.
Voici le résultat final :

L’affichage est basique et consiste en de petits carrés blancs de taille fixée (10 pixels dans notre cas) que nous appellerons cellules. Évidemment, il est possible d’avoir un affichage plus poussé mais cela requiert plus de temps. Les deux raquettes seront contrôlées par le ou les utilisateurs.

Commençons par créer un fichier nommé Pong.c qui contiendra notre boucle principale de jeu.

EFI_STATUS EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
  return EFI_SUCCESS;
}

Le point d’entrée du programme, UefiMain, est spécifié dans le fichier .inc dont nous avons donné le contenu dans la partie précédente.
L’argument SystemTable qui nous est envoyé est défini dans la spécification (page 149) comme tel :

typedef struct {
EFI_TABLE_HEADER Hdr;
CHAR16 *FirmwareVendor;
UINT32 FirmwareRevision;
EFI_HANDLE ConsoleInHandle;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
EFI_HANDLE ConsoleOutHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
EFI_HANDLE StandardErrorHandle;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
EFI_RUNTIME_SERVICES *RuntimeServices;
EFI_BOOT_SERVICES *BootServices;
UINTN NumberOfTableEntries;
EFI_CONFIGURATION_TABLE *ConfigurationTable;
} EFI_SYSTEM_TABLE;

Ainsi, il nous permet d’obtenir des pointeurs vers différentes structures, contenant des fonctions qui nous intéresseront par la suite. En particulier, on y trouve les structures ConIn et ConOut qui gèrent la console UEFI ainsi que la structure BootServices qui contient notamment les fonctions AllocatePool, pour allouer de l’espace mémoire, et locateProtocol, pour localiser un protocole.

NOTE : La structure BootServices est aussi accessible grâce à une variable globale notée gBS. De même, la variable globale gST pointe vers la SystemTable précédente.

L’accès aux fonctionnalités de l’UEFI se fait à l’aide de protocoles. Un protocole est identifié par un GUID, Globally Unique Identifier. Une fois acquis, le protocole définit une structure contenant des pointeurs de fonctions. Afin d’acquérir un protocole, la solution la plus simple est d’utiliser la fonction locateProtocol de la variable gBS globale, ou l’argument SystemTable. Voici la signature de la fonction (trouvable page 260 de la spécification) :

typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_PROTOCOL) (
    IN EFI_GUID *Protocol,
    IN VOID *Registration OPTIONAL,
    OUT VOID **Interface
);

Le premier argument de cette fonction est le GUID du protocole recherché, le second est optionnel et permet de spécifier une clé d’enregistrement qui peut être obtenue par la fonction EFI_BOOT_SERVICES.RegisterProtocolNotify(), le troisième argument est la référence vers le pointeur du protocole. Ce dernier sera affecté en fonction du résultat de la fonction.

En cas de succès, cette fonction renvoie Ret = EFI_SUCCESS et le pointeur Interface est mis à jour en conséquence. En cas d’erreur, la macro EFI_ERROR(Ret) est non nulle.

 

Remarque sur la gestion de la mémoire

Les programmes que nous écrivons ont pour but d’être exécutés juste après le démarrage de la machine, avant n’importe quel système d’exploitation. Ainsi, la mémoire et le processeur leur seront totalement dédiés. Il est possible d’allouer de la mémoire dynamiquement, dans le tas, grâce aux fonctions AllocatePool et AllocatePages se trouvant dans la table gBS (BOOT_SERVICES). Évidemment, les fonctions pour libérer ces espaces de mémoires alloués y sont aussi présentes. Cependant, les même problèmes que l’utilisation des fonctions malloc et free de la librairie C standard surviennent : utiliser l’espace dans le tas peut mener facilement à des fuites mémoires. De plus, utiliser la pile pour stocker des mémoires tampons (buffer) de grande taille est aussi déconseillé. En effet, les programmes compilés avec EDK II n’ont pas de système de protection de pile (canary). C’est pourquoi il est conseillé d’utiliser l’espace dit statique (static) du programme, cela permettra de déterminer à la compilation la taille utilisée par le programme. De plus, cela aura aussi pour effet de rendre le programme plus rapide étant donné qu’il n’y a nul besoin d’appeler les fonctions citées précédemment.

Protocole graphique et dessin

Dans cette partie, nous allons essayer dans un premier temps d’afficher des cellules, ce qui nous permettra ensuite d’afficher les raquettes, la balle puis le score. Commençons par regarder la spécification de l’API graphique. La spécification de l’UEFI définit le protocole graphique (page 565) comme tel :

typedef struct EFI_GRAPHICS_OUTPUT_PROTCOL {
EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode;
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;
EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt;
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
} EFI_GRAPHICS_OUTPUT_PROTOCOL;

La première fonction permet de tester si un mode est disponible et si oui, fournit aussi les informations qui y sont liées, comme la résolution. La seconde permet de changer de mode d’affichage. Enfin, la troisième fonction est celle qui nous intéresse, elle permet d’afficher des pixels à l’écran, à partir d’un buffer notamment. La structure Mode permet de récupérer les informations sur le mode d’affichage courant.

Commençons donc par définir la variable globale qui contiendra le protocole:

static EFI_GRAPHICS_OUTPUT_PROTOCOL* Gop = NULL;

Il nous est possible de définir une variable afin d’y stocker le GUID de ce protocole, cependant, EDK II contient déjà une définition de ce dernier, sous le nom de gEfiGraphicsOutputProtocolGuid. Nous pouvons donc essayer de récupérer ce protocole.

static EFI_GRAPHICS_OUTPUT_PROTOCOL* Gop = NULL;

EFI_STATUS EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
  EFI_STATUS St = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid,
                                      NULL,
                                      (VOID**) &Gop);
  if (EFI_ERROR(St)) {
    Print(L"Unable to locate Graphics Output Protocol\n");
    Exit(1);
  }
  return EFI_SUCCESS;
}

Si la fonction ne renvoie pas d’erreur, notre structure GoP sera remplie avec les champs précédemment vus. Nous pouvons dès lors utiliser la fonction Blt qui nous servira à dessiner. Rappelons que nos cellules de notre zone de jeu ont une taille de CELLSIZE x CELLSIZE pixels, où CELLSIZE = 10. Voici la signature de la fonction Blt :

typedef
EFI_STATUS
(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) (
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
IN UINTN SourceX,
IN UINTN SourceY,
IN UINTN DestinationX,
IN UINTN DestinationY,
IN UINTN Width,
IN UINTN Height,
IN UINTN Delta OPTIONAL
);

Ainsi, si on veut dessiner un carré blanc de taille CELLSIZE à la position (0, 0), l’appel suivant suffit :

EFI_GRAPHICS_OUTPUT_BLT_PIXEL White = {0xFF, 0xFF, 0xFF, 0};
Gop->Blt(Gop, &White, EfiBltVideoFill,
         0, 0,
         0, 0,
         CELLSIZE, CELLSIZE,
         0);

La description complète de la fonction ainsi que les différentes options pour cette dernière se trouvent dans la spécification. Les couleurs ont comme type EFI_GRAPHICS_OUTPUT_BLT_PIXEL, ce qui correspond à une simple structure contenant, dans l’ordre, les champs : Blue, Green, Red, Reserved, où Reserved doit toujours être à 0.

Après compilation et exécution, voici le résultat :

Nous pouvons dès lors écrire une fonction DrawCell qui se chargera de dessiner une cellule à l’écran aux coordonnées X et Y fournies. L’idéal serait que cette même fonction puisse aussi effacer une cellule, c’est-à-dire la remettre en noir. Pour ce faire, Il nous suffit de prendre en argument un booléen :

VOID
DrawCell(UINT32 X, UINT32 Y, BOOLEAN Reset)
{
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL White = {0xFF, 0xFF, 0xFF, 0};
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black = {0, 0, 0, 0};
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color = (Reset)?Black:White;
  Gop->Blt(Gop, &Color, EfiBltVideoFill,
	   0, 0,
	   X*CELLSIZE, Y*CELLSIZE,
	   CELLSIZE, CELLSIZE,
	   0);
}

Le type BOOLEAN est défini dans l’EDK II, de même que les valeurs TRUE et FALSE associées.

Grâce à cette fonction, il devient simple de dessiner des cellules à l’écran, nous pouvons donc définir des fonctions DrawBall, EraseBall, DrawBat, EraseBat, toutes aussi simples qui auront respectivement pour rôle de dessiner la balle, l’effacer, dessiner une raquette, en effacer une. La différence entre ces deux objets est leur taille. En effet, une raquette a une taille arbitraire de 1x10 cellules ( = 10x100 pixels). Écrivons ces fonctions, en ajoutant des définitions de tailles en plus :

#define CELLSIZE 10
#define BALLSIZE CELLSIZE
#define BATCELLS 10

VOID
DrawBall(UINT32 X, UINT32 Y)
{
  DrawCell(X, Y, FALSE);
}

VOID
EraseBall(UINT32 X, UINT32 Y)
{
  DrawCell(X, Y, TRUE);
}

VOID
DrawBat(UINT32 X, UINT32 Y)
{
  UINT32 i;
  for(i = 0; i < BATCELLS; i++){
    DrawCell(X, Y+i, 0);
  }
}

VOID
EraseBat(UINT32 X, UINT32 Y)
{
  UINT32 i;
  for(i = 0; i < BATCELLS; i++){
    DrawCell(X, Y+i, 1);
  }
}

Nous avons maintenant les fonctions qui vont nous permettre de dessiner les différents éléments que l’on peut retrouver sur un PONG classique.

La gestion des événements

Maintenant, ce qui nous intéresse est l’interaction avec l’utilisateur. Comment va-t-il contrôler les raquettes ?

Toujours dans la structure de BOOT_SERVICES que nous avons vu au début, se trouve une fonction nommée WaitForEvent dont voici la signature :

typedef
EFI_STATUS
(EFIAPI * EFI_WAIT_FOR_EVENT)(
IN UINTN NumberOfEvents,
IN EFI_EVENT *Event,
OUT UINTN *Index)

Le premier argument est le nombre d’événements, le second est le tableau des événements qui a donc une taille de NumberOfEvents, et le dernier est un pointeur de sortie pour stocker l’indice de l’événement qui est survenu. Cette fonction est similaire à la fonction POSIX select dans le sens où, ici, ce sont les EFI_EVENT qui jouent le rôle de descripteur.

Il nous suffit donc de récupérer le type EFI_EVENT correspondant au clavier afin de pouvoir appeler cette fonction.

Cette fois-ci, c’est dans la variable globale gST, qui est de type EFI_SYSTEM_TABLE, que nous allons trouver ce qu’il nous faut. Voici comment est définie cette structure dans la spécification (page 149) :

typedef struct {
  EFI_TABLE_HEADER Hdr;
  CHAR16 *FirmwareVendor;
  UINT32 FirmwareRevision;
  EFI_HANDLE ConsoleInHandle;
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
  EFI_HANDLE ConsoleOutHandle;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
  EFI_HANDLE StandardErrorHandle;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
  EFI_RUNTIME_SERVICES *RuntimeServices;
  EFI_BOOT_SERVICES *BootServices;
  UINTN NumberOfTableEntries;
  EFI_CONFIGURATION_TABLE *ConfigurationTable;
} EFI_SYSTEM_TABLE;

Tous les champs sont expliqués en détail dans la spécification. Les champs les plus importants ici sont :

ConOut, qui est le protocole qui se charge des sorties sur la console, il va donc permettre d’afficher du texte de manière standard (blanc sur fond noir, de haut en bas) ou de manière plus poussée (à n’importe quel endroit, avec des couleurs personnalisées) si l’UEFI sur lequel il s’exécute le permet
ConIn, qui est le protocole qui se charge de recevoir des événements du clavier.

Celui qui va nous intéresser est ce dernier, voici les champs qui le composent :

typedef struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL {
EFI_INPUT_RESET Reset;
EFI_INPUT_READ_KEY ReadKeyStroke;
EFI_EVENT WaitForKey;
} EFI_SIMPLE_TEXT_INPUT_PROTOCOL;

On retrouve le champ WaitForKey de type EFI_EVENT que nous avons vu plus tôt. C’est donc celui-ci qu’il faudra passer à la fonction WaitForEvent. Le champ ReadKeyStroke pointe vers une fonction qui renvoie une structure contenant l’information sur la touche qui a été appuyée. Voici un morceau de code qui nous permet de tester si la touche y a été appuyée :

UINTN EventIndex;
EFI_INPUT_KEY Key;
gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &EventIndex);
gST->ConIn->ReadKeyStroke(gST->ConIn, &Key);

if(Key.UnicodeChar == 'y'){
  Print(L"Y key pressed !\n");
}

Cependant, il est intéressant de remarquer qu’en utilisant cette fonction WaitForEvent, le système se met en pause jusqu’au moment où il reçoit cette interruption. Dans le cas du jeu PONG, si le système attend que l’utilisateur tape sur le clavier en permanence, la balle ne pourra pas avancer, le jeu étant suspendu systématiquement. La solution est de soit utiliser la fonction CheckEvent de notre variable global gBS soit d’utiliser directement la commande ReadKeyStroke. Prenons cette seconde solution, voici la signature de cette fonction :

typedef
EFI_STATUS
(EFIAPI *EFI_INPUT_READ_KEY) (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
OUT EFI_INPUT_KEY *Key
);

Ce qui est intéressant de voir dans cette signature est la valeur de retour qui est un EFI_STATUS qui peut prendre ces valeurs :

EFI_SUCCESS Les informations de la touches ont été récupérees
EFI_NOT_READY Aucune donnée n’était disponible (aucune touche n’a été appuyée)
EFI_DEVICE_ERROR Aucun donnée récupérée à cause d’un problème matériel

Ainsi, on peut effectuer un Poll sur les événements du clavier en testant la valeur de retour de la fonction que nous venons de voir. Voici un appel non bloquant qui teste si la touche y a été appuyée :

EFI_INPUT_KEY Key;
EFI_STATUS Poll = gST->ConIn->ReadKeyStroke(gST->ConIn, &Key);
if(Poll == EFI_SUCCESS){
  if(Key.UnicodeChar == 'y'){
    Print(L"Y key pressed !\n");
  }
}

Cas des touches spéciales : comme nous venons de le voir, il est assez simple de tester si une touche est un caractère, grâce au champs UnicodeChar de la structure de type EFI_INPUT_KEY. Néanmoins, cette structure contient aussi un champs ScanCode qui est utilisé quand l’utilisateur appuie sur des touches “spéciales”, les touches qui vont nous intéresser sont :

– Code 0x1 – Haut (flèche directionnelle)
– Code 0x2 – Bas (flèche directionnelle)
La liste complète est disponible page 510 de la spécification (Table 100).

Code principal du jeu

Nous avons maintenant tous les outils nécessaires afin de faire notre Pong. Reprenons notre fonction UefiMain de notre fichier Pong.c de la première partie du tuto :

EFI_STATUS EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
{
  EFI_STATUS St = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid,
                                      NULL,
                                      (VOID**) &Gop);
  if (EFI_ERROR(St)) {
    Print(L"Unable to locate Graphics Output Protocol\n");
    Exit(1);
  }
  return EFI_SUCCESS;
}

Grâce à ce protocole graphique, nous allons pouvoir récupérer la résolution de l’écran dans le mode d’affichage courant. Grâce à cette résolution, nous allons pouvoir calculer la taille de la zone de jeu, c’est-à-dire le nombre de cellules dans lequel se déroulera notre jeu.

CONST UINT32 ScreenWidth  = Gop->Mode->Info->HorizontalResolution;
CONST UINT32 ScreenHeight = Gop->Mode->Info->VerticalResolution;
CONST UINT32 GameWidth  = ScreenWidth / CELLSIZE;
CONST UINT32 GameHeight = ScreenHeight / CELLSIZE;

À partir de là, nous pouvons déjà définir la position de nos éléments. La balle sera placée au centre du terrain, les raquettes seront de part et d’autre du terrain, définissons quelques variables qui contiendront données sur la position de nos éléments tout au long de la partie :

UINT32 BallX = GameWidth / 2;
UINT32 BallY = GameHeight / 2;
UINT32 LeftBatPos  = (GameHeight / 2) - (BATCELLS / 2);
UINT32 RightBatPos = (GameHeight / 2) - (BATCELLS / 2);
CONST UINT32 LOWESTPOS = GameHeight - BATCELLS;
CONST UINT32 XRIGHTBAT = GameWidth-1;

Les raquettes se déplaçant seulement de haut en bas, leur position en X ne changera pas en cours de partie, nous pouvons donc définir dès maintenant, en tant que constante, la position en X de la raquette se trouvant à droite de l’écran ainsi que la position Y la plus basse jusqu’où peuvent aller les raquettes.

CONST UINT32 LOWESTPOS = GameHeight - BATCELLS;
CONST UINT32 XRIGHTBAT = GameWidth-1;

En incluant les fonctions de dessin que nous avons écrites dans la deuxième partie, nous pouvons d’ors et déjà afficher nos éléments à l’écran.

DrawBat(0, LeftBatPos);
DrawBat(XRIGHTBAT, RightBatPos);
DrawBall(BallX, BallY);

Après compilation et lancement, voici le résultat que l’on obtient

Nous avons donc l’affichage de notre zone de jeu qui est fonctionnel, ajoutons maintenant un peu de dynamisme à notre jeu.

Pour ce faire, on ajoute 2 variations de vitesse à notre balle (exprimées en cellule(s)/tour de boucle), vitesse en X et vitesse en Y, ainsi qu’une simple variation de vitesse pour nos raquettes. Ensuite, ajoutons la boucle principale munie d’un booléen qui a pour rôle de l’arrêter.

INT32 SpeedX = -1;
INT32 SpeedY = 1;
CONST INT32 BATSPEED = 4;
//Main loop
BOOLEAN Stop = FALSE;
while(!Stop){

}

Ce que nous allons essayer de faire maintenant est de faire réagir les raquettes aux touches du clavier. Pour la raquette de droite, les touches pour monter et descendre sont respectivement la flèche du haut et la flèche du bas, ce qui correspond aux codes 0x1 et 0x2. Pour la raquette de gauche prenons les touches ‘s’ pour monter et ‘x’ pour descendre.

N’oublions pas que le clavier est en qwerty par défaut, ces touches se situent au même endroit sur un clavier azerty et qwerty. De plus, des événements peuvent arriver à des intervalles de temps très réduits. L’idéal est donc de gérer ces événements dans le même tour de boucle, ainsi, on empêche la limite d’un seul événement par tour. Nous allons donc utiliser une boucle qui les traitera :

INT32 SpeedX = -1;
INT32 SpeedY = 1;
CONST INT32 BATSPEED = 4;
//Main loop
BOOLEAN Stop = FALSE;
while(!Stop){
    //Check for keys event
    EFI_STATUS Poll;
    do{
       //Check the keys and move the bats if needed
       EFI_INPUT_KEY Key;
       Poll = gST->ConIn->ReadKeyStroke(gST->ConIn, &Key);
       if(Poll == EFI_SUCCESS){
          if(Key.ScanCode == 0 && Key.UnicodeChar == 's'){
             EraseBat(0, LeftBatPos);
             if(LeftBatPos < BATSPEED){
                LeftBatPos = 0;
             } else {
                LeftBatPos -= BATSPEED;
             }
             DrawBat(0, LeftBatPos);
          } else if(Key.ScanCode == 0 && Key.UnicodeChar == 'x'){
             EraseBat(0, LeftBatPos); 
             LeftBatPos += BATSPEED;
             if(LeftBatPos > LOWESTPOS)
                LeftBatPos = LOWESTPOS;
                DrawBat(0, LeftBatPos);
             } else if(Key.ScanCode == 1){
                EraseBat(XRIGHTBAT, RightBatPos);
                if(RightBatPos < BATSPEED){
                   RightBatPos = 0;
                } else {
                   RightBatPos -= BATSPEED;
                }
                DrawBat(XRIGHTBAT, RightBatPos);
             } else if(Key.ScanCode == 2){
                EraseBat(XRIGHTBAT, RightBatPos); 
                RightBatPos += BATSPEED;
                if(RightBatPos > LOWESTPOS)
                   RightBatPos = LOWESTPOS;
                DrawBat(XRIGHTBAT, RightBatPos);
             }
       }
    }while(Poll == EFI_SUCCESS);
}

Voyons ce morceau de code un peu plus en détail.

On exécute une première fois la fonction ReadKeyStroke afin de savoir si une touche a été appuyée sur le clavier, s’il y en a effectivement eu une, alors la variable Poll renvoyée est EFI_SUCCESS et la structure Key est mise à jour en conséquence. Dès lors, nous pouvons comparer sa valeur avec celles décidées plus tôt, voyons le cas de la raquette de gauche :

if(Key.ScanCode == 0 && Key.UnicodeChar == 's'){
   EraseBat(0, LeftBatPos);
   if(LeftBatPos < BATSPEED){
      LeftBatPos = 0;
   } else {
      LeftBatPos -= BATSPEED;
   }
   DrawBat(0, LeftBatPos);
} else if(Key.ScanCode == 0 && Key.UnicodeChar == ’x’){
   EraseBat(0, LeftBatPos);
   LeftBatPos += BATSPEED;
   if(LeftBatPos > LOWESTPOS)
      LeftBatPos = LOWESTPOS;
   DrawBat(0, LeftBatPos);
}

Nous commençons par tester si la touche appuyée n’est pas spéciale (Key.ScanCode == 0) et s’il s’agit bien de la touche ‘s’. Si tel est le cas, alors on efface la raquette gauche de l’affichage, on la déplace, puis on la redessine à sa nouvelle position. Le principe est le même avec la touche ‘x’ pour déplacer la raquette vers le bas, la seule différence est la limite qui devient LOWESTPOS et non plus 0.

Les explications sont identiques pour la raquette de droite, seule la position en X diffère. Compilons et exécutons. Voici ce qu’il est possible de faire maintenant :

Chargeons nous maintenant du mouvement de la balle et de son interaction avec les raquettes. La première chose a faire lorsque l’on rentre dans notre boucle est d’effacer la balle de l’affichage, grâce à la fonction EraseBall. Puis, après la boucle à événements, nous mettons à jour la position de la balle en fonction de sa vitesse et enfin on redessine la balle à sa nouvelle position. Pour résumer, voici le bloc de code à écrire dans notre boucle principale :

EraseBall(BallX, BallY);
// Boucle à événement clavier do...while
BallX += SpeedX;
BallY += SpeedY;
DrawBall(BallX, BallY);

Si nous compilons et exécutons ce programme directement, le premier problème qui apparaît est la vitesse. Le processeur va effectuer les opérations trop rapidement pour que le jeu soit jouable. La solution la plus simple est de faire en sorte que le processeur s’endorme à chaque tour de boucle. Pour ce faire, il existe une fonction Stall qui se trouve dans la variable globale gBS. Cette fonction prend en argument des microsecondes. Faisons dormir le processeur 50ms à chaque tour de boucle avec la ligne suivante :

gBS->Stall(50000);

La balle se déplace maintenant à une vitesse acceptable mais elle sort assez rapidement du terrain. Ce que nous allons donc faire est que nous allons replacer la balle au centre lorsqu’elle sort en changeant sa direction (Si la balle se déplaçait de droite à gauche au moment de sa sortie du terrain, elle se déplacera de droite à gauche lors de son replacement au centre) et nous allons aussi faire en sorte qu’elle rebondisse lorsqu’elle touche les bords haut et bas du terrain.

Pour ce faire, il faut effectuer des tests sur la position de la balle avant le code de calcul de la nouvelle position. Le code précédent devient donc :

EraseBall(BallX, BallY);

// Boucle à événement clavier do...while

if(BallX == 0 || BallX == GameWidth){
   BallX = GameWidth / 2;
   BallY = GameHeight / 2;
   SpeedX *= -1;
}

if(BallY <= 0 || BallY >= GameHeight) {
   SpeedY *= -1;
}

BallX += SpeedX;
BallY += SpeedY;
DrawBall(BallX, BallY);
gBS->Stall(50000);

Après compilation et exécution, on voit que la balle bouge maintenant, au même titre que les raquettes. Cependant, il n’est toujours pas possible de l’arrêter avec les raquettes, elle ne fait que traverser ces dernières, il nous faut donc ajouter un cas au if que nous venons d’écrire. Il faut tester si une raquette bloque la balle en fonction des coordonnées de ces deux éléments : si le résultat est vrai, alors il faut changer la direction (et donc la vitesse) de la balle.

Le code précédent devient :

EraseBall(BallX, BallY);

// Boucle à événement clavier do...while

if(BallX == 0 || BallX == GameWidth){
   BallX = GameWidth / 2;
   BallY = GameHeight / 2;
   SpeedX *= -1;
} else if(BatBlockBall(0, LeftBatPos, BallX, BallY) ||
          BatBlockBall(XRIGHTBAT, RightBatPos, BallX, BallY)){
      SpeedX *= -1;
}

if(BallY <= 0 || BallY >= GameHeight) {
   SpeedY *= -1;
}
BallX += SpeedX;
BallY += SpeedY;
DrawBall(BallX, BallY);
gBS->Stall(50000);

Ici, c’est la fonction BatBlockBall, à qui on donne les coordonnées d’une raquette et d’une balle, qui va nous dire s’il y a une collision entre ces deux là. Le test de collision est simple : si la balle a des coordonnées comprises entre la coordonnée Y la plus haute et la plus basse de la raquette et que la distance en X entre la balle et la raquette est 1, alors il y a collision. Ce qui nous donne la fonction suivante :

BOOLEAN
BatBlockBall(UINT32 BatX, UINT32 BatY, UINT32 BallX, UINT32 BallY)
{
  INT32 SBatX  = BatX;
  INT32 SBallX = BallX;
  if(ABS(SBatX-SBallX) != 1){
    return FALSE;
  }

  return (BatY <= BallY) && ((BatY + BATCELLS) >= BallY);
}

La macro ABS est définie dans EDK II. En lui passant notre soustraction, elle fournit la valeur absolue qui correspond à notre distance.

La compilation et l’exécution mènera maintenant à un PONG simple mais fonctionnel.

Pour aller plus loin : l’affichage du score

Le jeu fonctionne correctement mais il est trop simple, il n’est pas possible de savoir qui a le plus de point et surtout, les points ne sont simplement pas comptabilisés. Supposons que les scores vont de 0 à 9, il faut écrire une fonction prenant en argument les deux scores et qui les affiche en haut, au centre de l’écran. Pour cela, il faut des patterns qui décrivent comment dessiner un chiffre. La solution retenue est simple : chaque chiffre est un tableau à deux dimensions de 5 lignes par 4 colonnes où chaque cellule blanche vaut 1 et chaque cellule noire vaut 0.

Exemple du pattern pour dessiner le chiffre 0:

// Codage de 0
{{1, 1, 1, 1},
 {1, 0, 0, 1},
 {1, 0, 0, 1},
 {1, 0, 0, 1},
 {1, 1, 1, 1}}

Après avoir écrit les patterns de chaque chiffre, plaçons les dans un tableau nommé NUMBERS de taille 10, dans un fichier Numbers.h. La fonction de dessin du score qui en ressort est la suivante :

/* Dans Numbers.h */
#define NUMBERHEIGHT 5
#define NUMBERWIDTH  4

/* Dans Pong.c */
VOID
DrawOneNumber(UINT8 Score, UINT32 X)
{
  UINT32 i, j;
  for(i = 0; i < NUMBERHEIGHT; i++){
    for(j = 0; j < NUMBERWIDTH; j++){
      if(NUMBERS[Score][i][j]){
        DrawCell(X+j, i, 0);
      }
    }
  }
}

VOID
DrawScore(UINT8 RightScore, UINT8 LeftScore, CONST UINT32 GameWidth)
{
  UINT32 X = (GameWidth / 2);
  DrawOneNumber(RightScore, X-1-NUMBERWIDTH);
  DrawOneNumber(LeftScore, X+1);
}

Ces fonctions permettent donc l’affichage du score de manière simple. Il faut aussi écrire la fonction qui efface les pixels du score (au cas où le score change), il suffit simplement de remettre à 0 les pixels qui se trouvent dans la zone de dessin du score.

VOID
EraseScore(CONST UINT32 GameWidth)
{
  UINT32 i, j;
  UINT32 start = (GameWidth / 2) - 1 - NUMBERWIDTH;
  for(i = 0 ; i < NUMBERHEIGHT; i++){
    for(j = start; j < start + 2 + 2*NUMBERWIDTH; j++){
      DrawCell(j, i, 1);
    }
  }
}

Nous avons les outils pour afficher le score des joueurs. Pour gérer le score dans notre jeu, ajoutons deux variables qui auront pour rôle de compter le score de chacune des raquettes, avant la boucle principale. Le score est à mettre à jour lorsque la balle sort du terrain, c’est-à-dire lorsque la balle a pour coordonnée X, 0 ou GameWidth. Il faut donc modifier la séquence de if...else écrite précédemment afin de distinguer le cas où la balle sort du côté gauche ou du côté droit.

if(BallX == 0){
   ++RightScore;
   if(RightScore >= 9){
     Stop = TRUE;
   }
   BallX = GameWidth / 2;
   BallY = GameHeight / 2;
   SpeedX *= -1;
   EraseScore(GameWidth);
   DrawScore(LeftScore, RightScore, GameWidth);
} else if(BallX == GameWidth){
   ++LeftScore;
   if(LeftScore >= 9){
     Stop = TRUE;
   }
   BallX = GameWidth / 2;
   BallY = GameHeight / 2;
   SpeedX *= -1;
   EraseScore(GameWidth);
   DrawScore(LeftScore, RightScore, GameWidth);
} else if(BatBlockBall(0, LeftBatPos, BallX, BallY) ||
          BatBlockBall(XRIGHTBAT, RightBatPos, BallX, BallY)){
   SpeedX *= -1;
}

Voyons ce qui change : maintenant, lorsque la balle sort du côté gauche, X = 0, le score du joueur droit est incrémenté, si son score est supérieur ou égal à 9, le jeu s’arrête, sinon, la balle est repositionnée au centre, sa direction change et l’ancien score est effacé puis le nouveau est affiché. Le code pour la partie droite est similaire.

Vous trouverez le code source complet du jeu, intégrant aussi les scores, à l’adresse suivante :
https://github.com/Openwide-Ingenierie/Pong-UEFI

À vous de jouer !

Problème d’affichage

Lorsque la balle passe par-dessus le score, ce dernier est en partie effacé, ceci est dû au fait que lorsque la balle se déplace, elle efface les cellules en les mettant en noir, sans tenir compte de la couleur qui se trouvait à sa place avant son passage.
Une solution consiste à sauvegarder la couleur de la cellule où la balle se déplace. Ainsi, lors de l’effacement de la balle, il est possible de remettre la cellule à sa couleur d’origine. Il peut être judicieux d’utiliser l’option EfiBltVideoToBltBuffer de la fonction Blt du protocole graphique.

Contrôle avec la souris

L’UEFI offre la possibilité d’utiliser la souris à travers un protocole nommé Simple Pointer Protocol, décrit page 540 de la spécification. Pourquoi ne pas l’utiliser pour déplacer une des raquettes ?

Vous avez désormais tous les outils pour résoudre ces problèmes.

Orchestration with MCollective, Part II

In my last article, I introduced how MCollective could be used for general orchestration tasks. more>>

Puppet's Cloud Discovery: Know What's Running in Your Cloud

The promise of automation always has been its ability to manage a wide range of tasks across all your systems, whether they're in your own data center or somewhere in the cloud. But in order to automate, you need to know what you have, and that's getting harder these days. more>>

L’édito de GNU/Linux Magazine n°205 !

On ne peut pas gagner à tous les coups ! C’est le constat qu’il m’a malheureusement fallu faire en essayant de lutter une énième fois contre l’obsolescence programmée… Comme toujours avec les tablettes et autres smartphones, la batterie est la première à donner des signes de faiblesse. En l’occurrence, sur une tablette de 5 ans, c’est tout à fait normal. Ce qui l’est moins, c’est de ne pas proposer de batterie amovible ! Alors bien sûr, sur une tablette on ne peut pas faire autrement (je ne connais aucun modèle avec batterie amovible). On peut se dire que le changement de batterie ne sera pas à la portée de tout le monde, mais que l’on peut raisonnablement penser qu’avec deux ou trois notions d’électronique on devrait arriver à démonter et remonter ladite tablette. La décision prise, on peut découper le scénario de la réparation en 4 phases :

Phase 1 – la planification : il faut trouver où acheter la batterie d’origine ou de remplacement en se méfiant des mauvaises imitations et s’équiper en outils permettant de démonter la tablette (de petits outils en plastique pour extraire la partie électronique de sa gangue de plastique sans tout abîmer).

Phase 2 – l’attente : il y a de gros risques pour que la batterie ait un long parcours en bateau à effectuer et il faudra donc être patient.

Phase 3 – l’action : vous avez reçu tous les éléments et vous prenez une demi-heure pour changer cette satanée batterie qui ne tient plus qu’une demi-heure et s’arrête sans avertissement. Premier constat : même pour des outils en plastique il faut choisir quelque chose de qualité ! À la moitié du démontage l’outil casse et il faut donc continuer… comme on peut…

Il suffit ensuite de retirer des vis et du scotch protégeant des nappes, et d’ouvrir les connecteurs de nappe pour retirer lesdites nappes. Oui, mais là aussi il y a un problème : après 5 ans d’utilisation, que devient une petite pièce en plastique située à côté d’un radiateur ? Elle devient cassante ! J’ai donc pu retirer trois nappes sur quatre, mais ce n’est malheureusement pas suffisant pour faire fonctionner la tablette.

Phase 4 – la résignation : il va falloir changer de tablette. Bien entendu il serait possible de passer du temps à bidouiller le connecteur, mais pour ça il faut justement avoir du temps… En attendant, la tablette sera donc remisée dans un coin jusqu’à ce que la prochaine la remplace (il ne faut pas être exagérément optimiste sur le temps dont on va disposer pour réparer une tablette que l’on n’utilise plus).

Bilan de l’opération : les constructeurs sont vraiment très forts et produisent des objets qui restent réparables le temps de la garantie, mais qui le sont beaucoup plus difficilement par la suite. J’en avais d’ailleurs fait également l’expérience avec une souris pour gamer qui au bout d’un an et demi d’utilisation a dû être mise au rebut (après une réparation de fortune qui a tenu 6 mois). Bilan connexe : finalement, je n’ai vraiment pas besoin d’une tablette ! 🙂

Profitez donc de votre magazine, son contenu se déprécie beaucoup moins rapidement que tout le matériel électronique que vous utilisez !

Tristan Colombo

GNU/Linux Magazine n°205 vous attend en kiosque, sur notre boutique ainsi que sur notre plateforme de lecture en ligne Connect

Créez la vie grâce à l’algorithme de Conway !

Le nouveau numéro de GNU/Linux Magazine vous explique comment créer la vie en implémentant l’algorithme du jeu de la vie de Conway en Python ! En feuilletant le sommaire, vous découvrirez également comment construire votre moteur physique 2D, concevoir des interfaces graphiques avec Glade, mettre en place un contrôleur CAN MCP2515 dans une Raspberry Pi ou encore développer des technologies et services pour le cloud computing. Ce numéro 205 vous attend en kiosque, sur notre boutique ainsi que sur notre plateforme de lecture en ligne Connect

Au sommaire

Actus & Humeur

p. 06 Cloud Computing : développer des technologies et services natifs

IA, Robotique & Science

p. 10 Comment recréer notre monde en quelques divisions et additions
p. 24 Le jeu de la vie de Conway : implémentation et petites adaptations

Système & Réseau

p. 36 Utiliser (enfin) Midnight Commander

IoT & Embarqué

p. 42 CANOpen avec Raspberry Pi

Kernel & Bas niveau

p. 56 Jouons avec les bits… en Python

Hack & Bidouille

p. 68 Afficher du texte sur un écran de leds WS2812

Libs & Modules

p. 78 Développement rapide d’applications GTK+ avec Glade

Mobile & Web

p. 90 De beaux chronogrammes avec WaveDrom

Sécurité & Vulnérabilité

p. 94 La faille Dirty COW

Le guide spécial sécurité des objets connectés vous attend en kiosque !

Pouvez-vous encore faire confiance à votre réfrigérateur ? MISC vous propose un hors-série spécial « Sécurité des objets connectés » pour en savoir plus sur le sujet ;-) Ce guide développe 4 principaux axes : les standards utilisés, l’évaluation des risques, les attaques et enfin l’amélioration de la sécurité de l’IoT. Retrouvez-le dès à présent chez votre marchand de journaux, sur notre boutique ainsi que sur notre plateforme de lecture en ligne Connect.

Au sommaire

Les standards utilisés

p. 08 Introduction à la sécurité des objets connectés

p. 10Étude de chiffrement dans un réseau IoT : le cas LoRaWan

p. 24 MQTT : le protocole IoT qui distribue vos données personnelles à tous ?

Évaluation des risques

p. 36 L’Internet des objets et le droit

p. 42 La CCTV : un système de surveillance en circuits ouverts ?

p. 54 Investigation numérique dans votre portefeuille

Attaques sur les objets

p. 68 Analyse d’une caméra Wireless P2P Cloud

p. 88 Les objets connectés peuvent-ils être infectés ?

Amélioration de la sécurité

p. 104 La cryptographie symétrique à bas coût : comment protéger des données avec très peu de ressources ?

p. 116 Des preuves mathématiques pour la sécurité des objets connectés ?

Créez la vie grâce à l’algorithme de Conway !

Le nouveau numéro de GNU/Linux Magazine vous explique comment créer la vie en implémentant l’algorithme du jeu de la vie de Conway en Python ! En feuilletant le sommaire, vous découvrirez également comment construire votre moteur physique 2D, concevoir des interfaces graphiques avec Glade, mettre en place un contrôleur CAN MCP2515 dans une Raspberry Pi ou encore développer des technologies et services pour le cloud computing. Ce numéro 205 vous attend en kiosque, sur notre boutique ainsi que sur notre plateforme de lecture en ligne Connect

Au sommaire

Actus & Humeur

p. 06 Cloud Computing : développer des technologies et services natifs

IA, Robotique & Science

p. 10 Comment recréer notre monde en quelques divisions et additions
p. 24 Le jeu de la vie de Conway : implémentation et petites adaptations

Système & Réseau

p. 36 Utiliser (enfin) Midnight Commander

IoT & Embarqué

p. 42 CANOpen avec Raspberry Pi

Kernel & Bas niveau

p. 56 Jouons avec les bits… en Python

Hack & Bidouille

p. 68 Afficher du texte sur un écran de leds WS2812

Libs & Modules

p. 78 Développement rapide d’applications GTK+ avec Glade

Mobile & Web

p. 90 De beaux chronogrammes avec WaveDrom

Sécurité & Vulnérabilité

p. 94 La faille Dirty COW

Recent improvements in Buildroot QA

Over the last few releases, a significant number of improvements in terms of QA-related tooling has been done in the Buildroot project. As an embedded Linux build system, Buildroot has a growing number of packages, and maintaining all of those packages is a challenge. Therefore, improving the infrastructure around Buildroot to make sure that packages are in good shape is very important. Below we provide a summary of the different improvements that have been made.

Buildroot

check-package script

Very much like the Linux kernel has a checkpatch.pl script to help contributors validate their patches, Buildroot now has a check-package script that allows to validate the coding style and check for common errors in Buildroot packages. Contributors are encouraged to use it to avoid common mistakes typically spotted during the review process.

check-package is capable of checking the .mk file, the Config.in, the .hash file of packages as well as the patches that apply to packages.

Contributed by Ricardo Martincoski, and written in Python, this tool will first appear in the next stable release 2017.05, to be published at the end of the month.

Buildroot’s page of package stats has been updated with a new column Warnings that lists the number of check-package issues to be fixed on each package. Not all packages have been fixed yet!

test-pkg script

Besides coding style issues, another problem that the Buildroot community faces when accepting contributions of new packages or package updates, is that those contributions have rarely been tested on a large number of toolchain/architecture configurations. To help contributors in this testing, a test-pkg tool has been added.

Provided a Buildroot configuration snippet that enables the package to be tested, test-pkg tool will iterate over a number of toolchain/architecture configurations and make sure the package builds fine for all those configurations. The set of configurations being tested is the one used by Buildroot autobuilder’s infrastructure, which allows us to make sure that a package will not fail to build as soon as it is added into the tree. Contributors are therefore encouraged to use this tool for their package related contributions.

A very primitive version of this tool was originally contributed by Thomas Petazzoni, but it’s finally Yann E. Morin who took over, cleaned up the code, extended it and made it more generic, and contributed the final tool.

Runtime testing infrastructure

The Buildroot autobuilder infrastructure has been running for several years, and tests random configurations of Buildroot packages to make sure they build properly. This infrastructure allows the Buildroot developers to make sure that all combinations of packages build properly on all architectures, and has been a very useful tool to help increase Buildroot quality. However, this infrastructure does not perform any sort of runtime testing.

To address this, a new runtime testing infrastructure has recently been contributed to Buildroot by Thomas Petazzoni. Contrary to the autobuilder infrastructure that tests random configurations, this runtime testing infrastructure tests a well-defined set of configurations, and uses Qemu to make sure that they work properly. Located in support/testing this test infrastructure currently has only 25 test cases, but we plan to extend this over time with more and more tests.

For example, the ISO9660 test makes sure that Buildroot is capable of building an ISO9660 image that boots properly under Qemu. The test suite validates that it works in different configurations: using either Grub, Grub2 or Syslinux as a bootloader, and using a root filesystem entirely contained in an initramfs or inside the ISO9660 filesystem itself.

Besides doing run-time tests of packages, this infrastructure will also allow us to test various core Buildroot functionalities. We also plan to have the tests executed on a regular basis on a CI infrastructure such as Gitlab CI.

DEVELOPERS file and e-mail notification

Back in the 2016.11 release, we added a top-level file called DEVELOPERS, which plays more or less the same role as the Linux kernel’s MAINTAINERS file: associate parts of Buildroot, especially packages, with developers interested in this area. Since Buildroot doesn’t have a concept of per-package maintainers, we decided to simply call the file DEVELOPERS.

Thanks to the DEVELOPERS file, we are able to:

  • Provide the get-developers tool, which parses patches and returns a list of e-mail addresses to which the patches should be sent, very much like the Linux kernel get_maintainer.pl tool. This allows developers who have contributed a package to be notified when a patch is proposed for the same package, and get the chance to review/test the patch.
  • Notify the developers of a package of build failures caused by this package in the Buildroot autobuilder infrastructure. So far, all build results of this infrastructure were simply sent every day on the mailing list, which made it unpractical for individual developers to notice which build failures they should look at. Thanks to the DEVELOPERS file, we now send a daily e-mail individually to the developers whose packages are affected by build failures.
  • Notify the developers of the support for a given CPU architecture of build failures caused on the autobuilders for this architecture, in a manner similar to what is done for packages.

Thanks to this, we have seen developers who were not regularly following the Buildroot mailing list contribute again fixes for build failures caused by their packages, increasing the overall Buildroot quality. The DEVELOPERS file and the get-developers script, as well as the related improvements to the autobuilder infrastructure were contributed by Thomas Petazzoni.

Build testing of defconfigs on Gitlab CI

Buildroot contains a number of example configurations called defconfigs for various hardware platforms, which allow to build a minimal embedded Linux system, known to work on such platforms. At the time of this writing, Buildroot has 146 defconfigs for platforms ranging from popular development boards (Raspberry Pi, BeagleBone, etc.) to evaluation boards from SoC vendors and Qemu machine emulation.

In order to make sure all those defconfigs build properly, we used to have a job running on Travis CI, but we started to face limitations, especially in the maximum allowed build duration. Therefore, Arnout Vandecappelle migrated this on Gitlab CI and things have been running smoothly since then.

Atelier Cybersécurité - Mulhouse (68) Le 15 juin 2017

Dans le cadre du salon Industries du Futur qui se déroulera les 14 et 15 juin 2017 à Mulhouse, CAP'TRONIC organise en collaboration avec la French tech et RHENATIC, un atelier sur le thème de la cybersécurité.

Pirater un objet connecté, c'est surtout accéder au réseau auquel il est connecté...
Il est donc nécessaire, pour les concepteurs, d'anticiper les menaces possibles et de mettre en place les parades pour les contrer.

A travers des démonstrations, ce séminaire mettra en lumière des éléments essentiels à une bonne "cyberdéfense".

Programme :

- Partage de fichiers de manière sécurisée, sécurisation d'applications web, sécurisation des informations critiques
Arnaud LAPREVOT - LYBEROT
http://Lybero.net

- Analyse et détection de codes malveillants
Philippe ANTOINE - INRIA
https://www.inria.fr/centre/nancy/innovation/rii-2016/demos/simorfo

- Solution de cartographie de réseau et de détection de signaux faibles caractéristiques de cyberattaques
Franck BERRUYER - SENTRYO
https://www.sentryo.net/fr/

Pour vous inscrire : cliquez-ici

Contact :

Jean-Christophe MARPEAU - 03.83.59.56.51

Lieu de l'événement :

Parc Expo
120 rue Lefebvre
68100 Mulhouse

Plus d'information : http://www.industriesdufutur.eu

La sécurisation des IoT - Mulhouse (68) Le 14 juin 2017

Dans le cadre du salon Industries du Futur qui se déroulera les 14 et 15 juin 2017 à Mulhouse, CAP'TRONIC organise en collaboration avec la French tech et RHENATIC, une conférence sur le thème de la cybersécurité.

Ignoré depuis de longues années, la cybersécurité revient sur le devant de la scène..
Du fait des dernières attaques, le sujet est maintenant au cœur des préoccupations des décideurs. D'autant que le développement des attaques informatiques se fait en parallèle à l'exposition du marché des IoT (Objets connectés).

L'IoT se développe, les entreprises s'en équipent, les particuliers aussi. Si l'IoT a pour but de nous simplifier la vie et de nous faire gagner du temps, il est indispensable maintenant d'intégrer au niveau des exigences de conception, une dose de gestion du risque, une dose de protection des données (sécurité offensive, sécurité défensive) et une dose de protection des logiciels et des systèmes (développement, test et validation, contrôle permanent en fonctionnement).

L'ampleur des systèmes impliquant des objets connectés et les conséquences d'un piratage sont désormais si importantes qu'il est vital pour les entreprises d'anticiper les besoins de sécurité.

Programme :

Le 14 juin à 10h00

- état de l'art de la sécurité dans l'IoT,
- typologie des cyberattaques,
- labels et certifications dans ce domaine et audits à entreprendre,
- problématiques rencontrées par les intégrateurs,
- mise en conformité des entreprises eu égard au Règlement général sur les données personnelles,
- sanctions encourues
- retours d'expériences

Pour vous inscrire : cliquez-ici

Contact :

Jean-Christophe MARPEAU - 03.83.59.56.51

Lieu de l'événement :

Parc Expo
120 rue Lefebvre
68100 Mulhouse

Plus d'information : http://www.industriesdufutur.eu