Este é o meu pequeno artigo que descreve (quase) tudo o que sei sobre a interface Apple Lightning e tecnologias relacionadas: Tristar, Hydra, HiFive, SDQ, IDBUS, etc. Mas, primeiro, um pequeno aviso ...
Leia este artigo por sua conta e risco! As informações são baseadas em muitos materiais internos da Apple Internal (vazamentos de dados, esquemas, códigos-fonte) que eu leio na diagonal. E, claro, na minha própria pesquisa. Devo avisar que nunca fiz essa pesquisa antes. Portanto, este artigo pode estar usando termos incorretos ou simplesmente estranhos e estar parcial ou completamente incorreto!
Antes de nos aprofundarmos, vamos entender brevemente os termos:
O que é Lightning?
Lightning é a interface digital usada na maioria dos dispositivos Apple iOS desde o final de 2012. Ele substituiu o antigo conector de 30 pinos.
A figura acima é o soquete do conector e a figura abaixo é sua pinagem:
Observe que, no conector, os pinos dos dois lados do conector não estão conectados na mesma ordem. Portanto, o dispositivo host deve determinar a orientação do cabo antes de fazer qualquer coisa.
Embora nem sempre seja esse o caso. Muitos acessórios Lightning que encontrei possuem pinagens espelhadas nos conectores.
O que são Tristar e Hydra?
O Tristar é um circuito integrado embutido em todos os dispositivos com um conector Lightning. É essencialmente um multiplexador:
entre outras coisas, seu principal objetivo é conectar-se ao conector macho Lightning assim que conectado - para determinar a orientação, o ID do acessório e rotear adequadamente as interfaces internas, como USB, UART e SWD.
Hydra é uma nova variante do Tristar, usada desde o iPhone 8 / X. Provavelmente, a mudança mais significativa é o suporte ao carregamento sem fio, mas isso ainda deve ser verificado:
conheço cinco variantes principais do Tristar / Hydra:
- TI THS7383 - Tristar de primeira geração no iPad mini 1 e iPad 4
- NXP CBTL1608A1 - Tristar de primeira geração no iPhone 5 e iPod touch 5
- NXP CBTL1609A1 - misteriosa primeira geração Tristar no iPod nano 7 - fonte
- NXP CBTL1610Ax - TriStar de segunda geração, usado desde o iPhone 5C / 5S e aparentemente em todo o resto que não suporta carregamento sem fio. Existem várias gerações (x é o número da geração)
- NXP CBTL1612Ax - O Hydra é usado com o iPhone 8 / X e, aparentemente, tudo o mais que suporta carregamento sem fio. Existem várias gerações (x é o número da geração)
A partir de agora, usarei apenas o termo TriStar, mas lembre-se de que ele também significa Hydra, pois eles são muito semelhantes na maioria dos aspectos que serão abordados neste texto.
O que é o HiFive?
HiFive é filho do Lightning, ou seja, um conector. Ele também contém uma porta lógica - esse chip é conhecido como SN2025 / BQ2025.
O que são SDQ e IDBUS?
Os dois termos são frequentemente considerados sinônimos dos tipos. Por conveniência, usarei apenas o termo IDBUS, pois ele me parece mais correto (e é assim que a tecnologia é chamada na especificação THS7383).
Portanto, o IDBUS é um protocolo digital usado para comunicação entre o Tristar e o HiFive. Muito semelhante ao protocolo Onewire .
Agora podemos começar
Vamos ouvir as comunicações Tristar e HiFive. Adquira um analisador lógico, um riser Lightning com uma tomada e um conector macho, um acessório (um cabo Lightning para USB normal funciona muito bem) e, claro, um dispositivo com uma porta Lightning.
Primeiro, conecte os canais do analisador lógico às duas linhas de identificação do riser (pinos 4 e 8) e conecte a placa ao dispositivo, mas ainda não conecte o acessório:
imediatamente depois disso, inicie a amostragem (qualquer frequência de 2 MHz ou superior servirá). Você verá algo assim:
Como você pode ver, o Tristar pesquisa cada linha de identificação, uma por uma. Mas como não conectamos nenhum acessório, a pesquisa falhou claramente. Em algum momento, o dispositivo se cansará desse fluxo interminável de falhas e o interromperá. Por enquanto, vamos ver o que exatamente acontece durante a pesquisa:
Primeiro, vemos um longo intervalo (cerca de 1,1 milissegundos), quando o nível é apenas alto, mas nada acontece:
Aparentemente, esse tempo é usado para carregar o capacitor HiFive interno - a energia dele será usada para alimentar os chips lógicos internos.
Muito mais interessante é o que acontece a seguir:
obviamente, esse é um fluxo de alguns dados. Mas como interpretar isso? Como descriptografar? Vamos virtualmente dividi-lo em partes mínimas significativas - o que chamo de palavras :
De fato, uma palavra é uma combinação de queda-crescente-queda:
- Estágio de conteúdo - o intervalo que determina o significado da palavra
- Fase de recuperação - o intervalo aparentemente necessário para processar a fase de conteúdo do lado do receptor e / ou preparar a próxima palavra na fase de envio
Aqui está uma tabela de palavras famosas com espaçamento para os dois estágios discutidos acima (todas as unidades em microssegundos):
Conteúdo | Recuperação | ||||
---|---|---|---|---|---|
Palavra | Mín. | Typ | Máx. | Mín. | Typ |
PAUSA | 12 | quatorze | dezesseis | 2.5 | 4.5 |
DESPERTAR | 22 | 24 | 27 | 1100? | |
ZERO | 6 | 7 | 8 | 3 | |
1 | 1 | 1.7 | 2.5 | 8,5 | |
ZERO e STOP * | 6 | 7 | 8 | dezesseis | |
UM e PARAR * | 1 | 1.7 | 2.5 | 21 |
Agora, usando a tabela acima, podemos criar um decodificador de protocolo simples:
como você pode ver, o host envia um BREAK primeiro - quando o Tristar deseja enviar uma nova solicitação, o host sempre começa com essa palavra. Depois vem o estágio de transferência de dados. Observe que o último (oitavo) bit em um byte possui uma fase de recuperação mais longa. Quando a fase de transferência de dados termina, o host envia outro BREAK. A criança deve enviar uma resposta (após um atraso de pelo menos 2,5 microssegundos - consulte a tabela). Tristar irá esperar cerca de 2,2ms por uma resposta. Se nenhuma resposta for dada dentro desse prazo, o Tristar tentará interrogar outra linha de identificação.
Agora, vamos analisar o estágio de dados usando o exemplo acima -
0x74 0x00 0x02 0x1f
:
0x74
- tipo de solicitação / resposta. Sempre par para uma solicitação e ímpar para uma resposta (tipo de solicitação +1)
0x00 0x02
- dados factuais. Pode estar vazio
0x1f
- este é o CRC8 do byte do tipo de solicitação e de todos os dados (polinômio - 0x31, valor inicial - 0xff)
Vamos conectar algum acessório à nossa plataforma e ver o que acontece.
Usarei o cabo Lightning para USB original da Apple: e aqui está o que aparece no IDBUS após a solicitação
0x74 : HiFive atendeu! E se você rolar mais, verá muitos outros pares de solicitação / resposta:
Algumas solicitações não precisam de resposta:
Interpretação de solicitações e respostas do IDBUS
A solicitação mais importante do IDBUS é 0x74, usada para dois propósitos: instruir o HiFive a ativar a tensão e a amperagem totais (se suportadas pelo acessório), perguntar sobre a configuração dos pinos que o cabo suporta e outros metadados.
Não se sabe muito sobre como os dados de resposta 0x75 são codificados. Mas alguns bits estão disponíveis na antiga especificação Tristar:
Dados da primeira resposta byte 0x75
7 | 6 | cinco | 4 | 3 | 2 | 1 | 0 0 |
---|---|---|---|---|---|---|---|
ACCx | Dx | DADOS [43:40] |
Configuração ACCx quando o ID é encontrado no ID0
ACCx [1: 0] | ACC1 | ACC2 | HOST_RESET |
---|---|---|---|
00 | Hi-Z (IDBUS) | Hi-Z | Hi-Z |
01 | UART1_RX | UART1_TX | Hi-Z |
dez | JTAG_DIO | JTAG_CLK | Hi-Z |
onze | Hi-Z | Hi-Z | ALTO |
Configuração ACCx quando o ID é encontrado no ID1
ACCx [1: 0] | ACC1 | ACC2 | HOST_RESET |
---|---|---|---|
00 | Hi-Z | Hi-Z (IDBUS) | Hi-Z |
01 | UART1_RX | UART1_TX | Hi-Z |
dez | JTAG_DIO | JTAG_CLK | Hi-Z |
onze | Hi-Z | Hi-Z | ALTO |
Configuração Dx quando o ID é encontrado no ID0
Dx [1: 0] | DP1 | DN1 | DP2 | DN2 |
---|---|---|---|---|
00 | Hi-Z | Hi-Z | Hi-Z | Hi-Z |
01 | USB0_DP | USB0_DN | Hi-Z | Hi-Z |
dez | USB0_DP | USB0_DN | UART1_TX | UART1_RX |
onze | Hi-Z | Hi-Z | Hi-Z | Hi-Z |
Configuração de Dx quando o ID é encontrado no ID1
Dx [1: 0] | DP1 | DN1 | DP2 | DN2 |
---|---|---|---|---|
00 | Hi-Z | Hi-Z | Hi-Z | Hi-Z |
01 | Hi-Z | Hi-Z | USB0_DP | USB0_DN |
dez | USB0_DP | USB0_DN | UART1_TX | UART1_RX |
onze | Hi-Z | Hi-Z | Hi-Z | Hi-Z |
Usando essas tabelas, vamos decifrar o ID do nosso cabo (
10 0C 00 00 00 00
), levando em consideração o fato de que a linha de ID é encontrada no pino ID0:
O primeiro byte da resposta do cabo 0x75
7 | 6 | cinco | 4 | 3 | 2 | 1 | 0 0 |
---|---|---|---|---|---|---|---|
ACCx | Dx | DADOS [43:40] | |||||
0 0 | 0 0 | 0 0 | 1 | 0 0 | 0 0 | 0 0 | 0 0 |
Portanto, ACCx é 00. Isso significa que o pino ID0 está simplesmente vinculado ao IDBUS e Dx = 01 significa que os pinos DP1 / DN1 estão configurados como USB0_DP / USB0_DN. Exatamente o que esperávamos de um cabo USB padrão.
Agora vamos interceptar algo mais interessante:
Acessório | ID (HOSTID = 1) |
---|---|
DCSD | 20 00 00 00 00 00 |
KongSWD (sem Astris em execução) | 20 02 00 00 00 00 |
KongSWD (com Astris em execução) | A0 00 00 00 00 00 |
KanziSWD (sem Astris em execução) | 20 0E 00 00 00 00 |
KanziSWD (com Astris em execução) | A0 0C 00 00 00 00 |
Haywire (HDMI) | 0B F0 00 00 00 00 |
Carregando UART | 20 00 10 00 00 00 |
Relâmpagos a 3,5 mm / EarPods com relâmpagos | 04 F1 00 00 00 00 |
Aqui está uma lista completa (?) Das solicitações do IDBUS do @spbdimka :
Dica 1 : Você pode obter facilmente as propriedades de um acessório, incluindo seu ID, usando accctl:
Este é um utilitário interno da Apple que vem com os conjuntos NonUI / InternalUI. Mas você pode executá-lo facilmente em qualquer dispositivo após o jailbreak.
Dica 2 : você pode facilmente obter a configuração de pinos de um cabo usando diags:
tristar -p
Observe que este comando está disponível apenas no iOS 7 ou superior.
Dica 3 : você pode acompanhar facilmente solicitações / respostas 0x74 / 0x75 geradas por análises SWD configurando
debug
env var como 3:
astrisctl setenv debug 3
Então, no COM virtual do cabo, você verá algo assim:
HOSTID
Em uma das tabelas acima, você pode ver a menção de um certo HOSTID. Este é o valor de 16 bits passado na solicitação 0x74. Parece que isso também afeta a resposta do HiFive. Pelo menos, se você defini-lo com um valor inválido (sim, é possível com diags), o HiFive para de trabalhar com ele:
No entanto, o firmware KongSWD / KanziSWD possui uma variável de ambiente disableIdCheck, que você pode configurar para ignorar o HOSTID inválido.
Nota importante: Kong e Kanzi não possuem o HiFive como um chip não programável dedicado. Esses acessórios o emulam com um microcontrolador e / ou FPGA, facilitando a atualização / reprogramação.
DESPERTAR
Na tabela ID do acessório acima, é possível ver que Kong e Kanzi enviam respostas diferentes, dependendo de o Astris estar em execução ou não, que é o software interno da Apple para depuração com sondas SWD (ou sondas). Se você decifrar essas respostas usando as tabelas acima, descobrirá que, quando o Astris falhar ao iniciar, o probe atuará exatamente como DCSD - USB nas linhas D1 e depurará o UART nas linhas D2. Mas quando o software de depuração está em execução, as linhas ACCID mudam para SWD.
Mas e se quisermos lançar o Astris depois que a sonda já estiver conectada ao dispositivo? O que o cabo fará? Como ele alterna entre as linhas ACC e SWD? É aqui que o WAKE entra em jogo! HiFive (ou um dispositivo que o emula) pode iniciarWAKE - e o processo de enumeração IDBUS começará novamente: Tristar enviará uma solicitação 0x74, Kong / Kanzi responderá com uma nova ID, Tristar confirmará e enviará linhas ACC para extensões SWD (o SoC deve oferecer suporte no nível físico, é claro).
Aperto de mão poderoso
A última coisa que eu vou olhar é o aperto de mão poderoso. Esse é um algoritmo de solicitação / resposta do IDBUS que os drivers do kernel Tristar usam antes de permitir o carregamento de acessórios.
Quando o cabo Lightning está apenas em algum lugar, conectado ao carregador / computador, mas não conectado ao dispositivo, o HiFive limita a corrente ao PWR a um valor realmente pequeno (cerca de 10 a 15 mA, de acordo com minhas medidas). Para ativar a corrente total, a solicitação 0x74 deve ser emitida pela Tristar e processada pelo HiFive. Para SecureROM / iBoot, isso é suficiente, mas etapas adicionais devem ser tomadas ao carregar o kernel:
- O TriStar emite duas solicitações 0x70
- Assim que a segunda solicitação é processada pelo HiFive e uma resposta é enviada, ela desliga a corrente por cerca de 20 milissegundos
- Tristar 0x70, 0x80 . HiFive
- , Tristar,
: , . , . ,
ESN Tristar I2C
Outro recurso do Tristar que eu gostaria de falar é o ESN. Este é um pequeno blob que a Tristar armazena em sua EEPROM (no CBTL1610A2 e posterior). Pode ser obtido através do IDBUS usando o cabo do Serial Number Reader (ou o Kanzi, eles são basicamente os mesmos, exceto por diferentes USB-PIDs e gabinetes ligeiramente diferentes).
Simplesmente, enviando esse blob para ttrs.apple.com , você pode obter o número de série do dispositivo ... Esse mecanismo é usado pelos funcionários da Apple Store / Revendedor Apple Premium para recuperar o SN de dispositivos mortos (se o Tristar ainda estiver ativo):
O que acontece no IDBUS quando um ESN é recebido, o @spbdimka documentou :
Treinamento
O procedimento para "Firmware» ESN exigia o treinamento em Tristar (provisionamento). Isso ocorre com o diagnóstico no lado do dispositivo, através do EzLink no lado receptor em três etapas.
Você pode verificar o status usando diags:
tristar --prov_stat
... e também obtenha o ESN:
tristar --esn
A propósito, os diags geralmente têm um rico conjunto de comandos Tristar (disponíveis desde o iOS 7):
Tristar I2C
O Tristar está disponível no barramento I2C (endereço 0x34 para gravação, 0x35 para leitura). É assim que os drivers diag e kernel interagem com ele. Pouco se sabe publicamente
sobre registros . Muitas informações sobre o próprio mapa de registro podem ser obtidas no código-fonte vazado do iBoot (apenas para o THS7383 - parece ser compatível com o CBTL1608 - e o CBTL1610), mas não há muito sobre o que precisa ser escrito lá para obter resultados interessantes. Outra fonte de conhecimento é o módulo Tristar de diags (facilmente recuperado através do SWD enquanto está em execução). Por exemplo, consegui reverter os algoritmos de provisionamento e leitura de ESN. Em seguida, implementei isso como uma adição à minha carga para o iBoot chamada Lina :
Também tentei alterar o algoritmo de escrita ESN, mas falhei - o mecanismo é muito complicado para mim. No entanto, trechos de código da Lina estão disponíveis aqui .
Características elétricas do Tristar
O próprio Tristar é alimentado por uma fonte de 1,8 V. As linhas do IDBUS são tolerantes a 3,0V, de acordo com o meu osciloscópio:
Portanto, sem um circuito de mudança de nível, é melhor não tentar se comunicar com o IDBUS usando dispositivos tolerantes a 5V, como alguns modelos do Arduino ...