Nosso discurso na cimeira Open Source. Mais 15 dias para doar os 2600 euros restantes.

This image has an empty alt attribute; its file name is Notebook_PPC_Board_Layout_alpha-1024x482.png
O design da nossa placa-mãe PPC64

Nossa licença Open Hardware e sugestões para endianness na OSS 2020

Falamos sobre a licença CERN para Open Hardware e endianness na cimeira Open Source + Linux Embedded na Europa, no dia 27 de outubro de 2020.

Licença CERN para Open Hardware

Por que não usar uma licença para software como a GPL?
Licenças para hardware são específicas, portanto são escritas com a nomenclatura apropriada: fabricante, dispositivos, CAD, etc..

Por que escolhemos a licença CERN para Open Hardware v1.2?
Achamos que oferece uma proteção melhor para quem recebe uma licença quando comparada com outras licenças para hardware como a TAPR.

Quem recebe e quem fornece a licença?
No nosso projeto, nós (comunidade Power Progress) recebemos a licença e o licenciador é o fabricante do hardware.

O licenciador pode fabricar e distribuir produtos?
O licenciador pode modificar nosso trabalho, mas essas modificações precisam ser disponibilizadas sob a mesma licença, ou licença equivalente.

Como somos protegidos?
O licenciador é responsável pelo hardware e sua qualidade.

Outras notas importantes
– Firmware, drivers e outro software precisam de suas próprias licenças.
– A propriedade intelectual é nossa.
– A documentação precisa ser fornecida no formato correto para que possa ser livremente modificada (usando uma ferramenta CAD).

Endianness

O que é endianness?

É a maneira com que dados são ordenados na memória de um computador.
Afeta números inteiros que sejam maiores que 1 byte.
Pode ser um problema quando arquiteturas diferentes compartilham informação.
É um dos problemas principais que um desenvolvedor de software precisa ter em mente quando escreve software portátil.

Endianness na memória: Big Endian

Os dados são lidos da esquerda para a direita.
O byte mais significante fica na esquerda.
A palavra no endereço 0x101 é:
0x0203 = 515
A palavra dupla no endereço 0x100 é:
0x01020304 = 16909060

Endianness na memória: Little Endian

Os dados são lidos da direita para a esquerda.
O byte mais importante fica na direita.
A palavra no endereço 0x101 é:
0x0302 = 770
A palavra dupla no endereço 0x100 é:
0x04030201 = 67305985

Conversão de endianness

Existem dois metódos para trocar endianness: manual e automático.

Troca manual

16 bit unsigned swap:
swapped = (num>>8) | (num<<8);

32 bit unsigned swap:
swapped = ((num>>24)&0xff) | // move byte 3 to byte 0
((num<<8)&0xff0000) | // move byte 1 to byte 2 ((num>>8)&0xff00) | // move byte 2 to byte 1
((num<<24)&0xff000000); // byte 0 to byte 3

There are ready-to-use functions that have the same behaviour:
bswap_16(x);
bswap_32(x);
bswap_64(x);

Detecção de arquitetura

Trocas manuais devem ser evitadas. Conhecimento da arquitetura em questão é importante. A arquitetura deve ser detectada e casos específicos implementados, senão o código não será independente de plataformas.

#if __BYTE_ORDER == __LITTLE_ENDIAN
<LITTLE ENDIAN SWAP DEFINITION>
#elif __BYTE_ORDER == __BIG_ENDIAN
<BIG ENDIAN SWAP DEFINITION>
#end

Por exemplo, se o programa requisita uma função little endian em uma plataforma little endian, a função retornará os dados como estão. Em caso contrário, um procedimento de troca será executado.

Conversão de funções

POSIX tem ferramentas úteis para a conversão de endianness chamadas de host-to-network e de network-to-host:

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

Estas funções são executadas sempre que você precisa lidar com um problema de endianness. Tenha em mente que network order é “byte mais significante primeiro”, ou seja, Big Endian.

Existem outras funções para conversão little/big endian. Elas não são padrão, mas são muito úteis:

#include <endian.h>

uint16_t htobe16(uint16_t host_16bits);
uint16_t htole16(uint16_t host_16bits);
uint16_t be16toh(uint16_t big_endian_16bits);
uint16_t le16toh(uint16_t little_endian_16bits);

uint32_t htobe32(uint32_t host_32bits);
uint32_t htole32(uint32_t host_32bits);
uint32_t be32toh(uint32_t big_endian_32bits);
uint32_t le32toh(uint32_t little_endian_32bits);

uint64_t htobe64(uint64_t host_64bits);
uint64_t htole64(uint64_t host_64bits);
uint64_t be64toh(uint64_t big_endian_64bits);
uint64_t le64toh(uint64_t little_endian_64bits);

Leave a Reply

Este site utiliza o Akismet para reduzir spam. Fica a saber como são processados os dados dos comentários.