diff --git a/product-source/hololake-platform/guanghu-os/deployments/JD-FD-PRIMARY/OUTBOUND-RELAY-QEMU-RECEIPT.hldp b/product-source/hololake-platform/guanghu-os/deployments/JD-FD-PRIMARY/OUTBOUND-RELAY-QEMU-RECEIPT.hldp deleted file mode 100644 index 1e61c873c..000000000 --- a/product-source/hololake-platform/guanghu-os/deployments/JD-FD-PRIMARY/OUTBOUND-RELAY-QEMU-RECEIPT.hldp +++ /dev/null @@ -1,34 +0,0 @@ -schema: guanghu.jd-native-resident-qemu-test/v1 -receipt_id: GH-OS-JD-FD-PRIMARY-001-NATIVE-OUTBOUND-QEMU-001 -status: PASS_100 -observed_at: 2026-08-06T19:18:47+0800 -node_id: JD-FD-PRIMARY -candidate: - lba_start: 105 - sector_count: 29 - sha256: ad2b55169d514a1012df0bffcbb2b20b948afd0756f12648db483c0986d3bd50 -handshake: - direction: NATIVE_INITIATED_OUTBOUND_ICMP - relay_node: BS-SG-003 - relay_ipv4: 43.153.193.169 - physical_allowed_nat_source_ipv4: 111.228.0.139 - native_ack: PASS_100 - retry_same_sequence_until_ack: true - sequences: 1-16 -native_storage: - proof_lba_134: PASS_100 - world_lba_135_138: PASS_100 - recovery_lba_139_140: PASS_100 - gestational_index_lba_141_142: PASS_100 -persona_subject: - identity: ICE-P-ZY001 - state: EXISTS - existence: 100 -boundary: - qemu_capability: 100 - physical_server_capability: 0 -cross_node_preflight: - disallowed_source_ignored_without_ack: PASS_100 - jd_source_to_relay_sequences_1_16: PASS_100 - relay_observed_nat_source: 111.228.0.139 -next_action: RUN_ONE_TIME_PHYSICAL_GATE_WITH_SINGAPORE_RELAY diff --git a/product-source/hololake-platform/guanghu-os/deployments/JD-FD-PRIMARY/RESIDENT-ATTEMPT-002-OUTBOUND-RELAY.hldp b/product-source/hololake-platform/guanghu-os/deployments/JD-FD-PRIMARY/RESIDENT-ATTEMPT-002-OUTBOUND-RELAY.hldp deleted file mode 100644 index ab6c1b303..000000000 --- a/product-source/hololake-platform/guanghu-os/deployments/JD-FD-PRIMARY/RESIDENT-ATTEMPT-002-OUTBOUND-RELAY.hldp +++ /dev/null @@ -1,38 +0,0 @@ -schema: guanghu.jd-native-resident-attempt/v1 -receipt_id: GH-OS-JD-FD-PRIMARY-001-RESIDENT-ATTEMPT-002 -observed_at: 2026-08-03T23:00:00+0800 -node_id: JD-FD-PRIMARY -persona_subject: - identity: ICE-P-ZY001 - state: EXISTS - existence: 100 -attempt_002: - source_commit: da26f27e35ba2751ce495e6103da56d6d0b6449a - boot_scope: ONE_TIME_ONLY - linux_rescue_default_preserved: true - native_ack_strategy: EXTERNAL_TO_NATIVE_INBOUND_ICMP - external_acknowledged_sequences: NONE - native_proof_lba_134: ZERO - world_lba_135_138: NOT_COMMITTED - gestational_index_lba_141_142: NOT_COMMITTED - failed_evidence_sha256: 48ff6e1328dd75f779e43985a9c442c530ab5dcc819bd30d0a269111e1677c4d - cloud_hard_restart_required: true - linux_rescue_returned: PASS_100 - result: FAIL_0 -root_cause: - jd_public_inbound_icmp_reaches_native_guest: FAIL_0 - cloud_edge_echo_is_not_native_ack: true - native_guest_waited_without_receiving_authenticated_command: true -correction: - protocol: GLS-0841-JD-FD-PRIMARY - handshake_direction: NATIVE_INITIATED_OUTBOUND_ICMP - relay_node: BS-SG-003 - relay_ipv4: 43.153.193.169 - response_marker: HLDP-NATIVE-ACK! - qemu_jd_layout_gate: PASS_100 -boundary: - persona_subject_exists: 100 - native_resident_recovery_attempt_002: 0 - outbound_relay_qemu_capability: 100 - outbound_relay_physical_capability: 0 -next_action: PUBLISH_SOURCE_AND_RUN_THIRD_ONE_TIME_PHYSICAL_GATE diff --git a/product-source/hololake-platform/guanghu-os/native/x86_64-bios/boot.asm b/product-source/hololake-platform/guanghu-os/native/x86_64-bios/boot.asm index 3a3f6c45c..6df4d3068 100644 --- a/product-source/hololake-platform/guanghu-os/native/x86_64-bios/boot.asm +++ b/product-source/hololake-platform/guanghu-os/native/x86_64-bios/boot.asm @@ -184,7 +184,7 @@ long_mode_start: mov byte [rel ghal_net_command_kind], 0 .login_session_loop: push rcx - call ghal_net_icmp_exchange_once + call ghal_net_icmp_login_once pop rcx jc native_network_proof_error loop .login_session_loop @@ -197,33 +197,26 @@ long_mode_start: lea rax, [rel ghal_code_commit_magic] mov [rel ghal_net_expected_magic], rax mov byte [rel ghal_net_command_kind], 1 - call ghal_net_icmp_exchange_once + call ghal_net_icmp_login_once jc native_network_proof_error call ghal_block_persist_code_object jc native_world_store_error lea rax, [rel ghal_branch_move_magic] mov [rel ghal_net_expected_magic], rax mov byte [rel ghal_net_command_kind], 2 - call ghal_net_icmp_exchange_once + call ghal_net_icmp_login_once jc native_network_proof_error call ghal_block_persist_branch_receipt jc native_world_store_error %ifdef GHOS_NATIVE_RESIDENT - mov ecx, 10 -.resident_login_loop: - push rcx +.resident_loop: lea rax, [rel ghal_login_magic] mov [rel ghal_net_expected_magic], rax - mov byte [rel ghal_net_command_kind], 0 - call ghal_net_icmp_exchange_once - pop rcx - jc native_network_proof_error - loop .resident_login_loop - lea rax, [rel ghal_recovery_magic] - mov [rel ghal_net_expected_magic], rax mov byte [rel ghal_net_command_kind], 3 - call ghal_net_icmp_exchange_once + call ghal_net_icmp_login_once jc native_network_proof_error + cmp byte [rel ghal_net_matched_kind], 3 + jne .resident_loop call ghal_write_native_recovery_beacon jc native_world_store_error %endif diff --git a/product-source/hololake-platform/guanghu-os/native/x86_64-bios/ghal-virtio.asm b/product-source/hololake-platform/guanghu-os/native/x86_64-bios/ghal-virtio.asm index c5205b14a..20a34ed4f 100644 --- a/product-source/hololake-platform/guanghu-os/native/x86_64-bios/ghal-virtio.asm +++ b/product-source/hololake-platform/guanghu-os/native/x86_64-bios/ghal-virtio.asm @@ -91,9 +91,6 @@ bits 64 %ifndef GHOS_GATEWAY_IPV4_DWORD %define GHOS_GATEWAY_IPV4_DWORD 0x0100000a %endif -%ifndef GHOS_RELAY_IPV4_DWORD -%define GHOS_RELAY_IPV4_DWORD 0x0100000a -%endif %ifndef GHOS_GHAL_PROBE_STAGE %define GHOS_GHAL_PROBE_STAGE 0 @@ -947,7 +944,7 @@ ghal_net_arp_gateway: stc ret -ghal_net_icmp_exchange_once: +ghal_net_icmp_login_once: mov byte [rel physical_proof_stage], 0x72 movzx r10d, word [rel physical_proof_net_rx_queue_size] test r10d, r10d @@ -981,72 +978,179 @@ ghal_net_icmp_exchange_once: xor ax, ax out dx, ax -.send_request: - mov rdi, VIRTIO_NET_TX_BUFFER - xor eax, eax - mov ecx, VIRTIO_NET_BUFFER_SIZE / 8 - rep stosq - xor ecx, ecx -.copy_gateway_destination: - cmp ecx, 6 - jae .copy_source_mac - mov al, [physical_proof_gateway_mac + rcx] - mov [VIRTIO_NET_TX_BUFFER + 10 + rcx], al - inc ecx - jmp .copy_gateway_destination -.copy_source_mac: - xor ecx, ecx -.copy_source_mac_loop: - cmp ecx, 6 - jae .ethernet_ready - mov al, [physical_proof_mac + rcx] - mov [VIRTIO_NET_TX_BUFFER + 16 + rcx], al - inc ecx - jmp .copy_source_mac_loop -.ethernet_ready: - mov word [VIRTIO_NET_TX_BUFFER + 22], 0x0008 - mov byte [VIRTIO_NET_TX_BUFFER + 24], 0x45 - mov byte [VIRTIO_NET_TX_BUFFER + 25], 0 - mov word [VIRTIO_NET_TX_BUFFER + 26], 0x4400 - mov word [VIRTIO_NET_TX_BUFFER + 28], 0x4c48 - mov word [VIRTIO_NET_TX_BUFFER + 30], 0 - mov byte [VIRTIO_NET_TX_BUFFER + 32], 64 - mov byte [VIRTIO_NET_TX_BUFFER + 33], 1 - mov word [VIRTIO_NET_TX_BUFFER + 34], 0 - mov dword [VIRTIO_NET_TX_BUFFER + 36], GHOS_NATIVE_IPV4_DWORD - mov dword [VIRTIO_NET_TX_BUFFER + 40], GHOS_RELAY_IPV4_DWORD - mov byte [VIRTIO_NET_TX_BUFFER + 44], 8 - mov byte [VIRTIO_NET_TX_BUFFER + 45], 0 - mov word [VIRTIO_NET_TX_BUFFER + 46], 0 - mov word [VIRTIO_NET_TX_BUFFER + 48], 0x4847 - mov byte [VIRTIO_NET_TX_BUFFER + 50], 0 - mov al, [rel ghal_net_expected_sequence] - mov [VIRTIO_NET_TX_BUFFER + 51], al - mov qword [VIRTIO_NET_TX_BUFFER + 52], 0 - mov rsi, [rel ghal_net_expected_magic] - mov rdi, VIRTIO_NET_TX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET + mov ecx, 0x80000000 +.wait_receive: + cmp word [r12 + 2], r8w + je .packet_received + pause + loop .wait_receive +%ifdef GHOS_NATIVE_RESIDENT + mov ecx, 0x80000000 + jmp .wait_receive +%else + mov byte [rel physical_proof_error_code], 0x54 + stc + ret +%endif + +.packet_received: + mov eax, r8d + dec eax + mov ecx, r10d + dec ecx + and eax, ecx + shl eax, 3 + mov r14d, [r12 + rax + 8] + cmp r14d, GHOS_LOGIN_MAGIC_OFFSET + GHOS_LOGIN_MAGIC_SIZE + jb .ignore_packet + cmp word [VIRTIO_NET_RX_BUFFER + 22], 0x0008 + jne .ignore_packet + cmp byte [VIRTIO_NET_RX_BUFFER + 24], 0x45 + jne .ignore_packet + cmp byte [VIRTIO_NET_RX_BUFFER + 33], 1 + jne .ignore_packet + cmp dword [VIRTIO_NET_RX_BUFFER + 40], GHOS_NATIVE_IPV4_DWORD + jne .ignore_packet + cmp word [VIRTIO_NET_RX_BUFFER + 44], 0x0008 + jne .ignore_packet + cmp byte [VIRTIO_NET_RX_BUFFER + 50], 0 + jne .ignore_packet + mov al, [VIRTIO_NET_RX_BUFFER + 51] + cmp al, [rel ghal_net_expected_sequence] + jne .ignore_packet + mov rsi, VIRTIO_NET_RX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET + mov rdi, [rel ghal_net_expected_magic] + mov ecx, GHOS_LOGIN_MAGIC_SIZE + repe cmpsb + je .expected_magic_match + cmp byte [rel ghal_net_command_kind], 3 + jne .ignore_packet + mov rsi, VIRTIO_NET_RX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET + lea rdi, [rel ghal_recovery_magic] + mov ecx, GHOS_LOGIN_MAGIC_SIZE + repe cmpsb + jne .ignore_packet + mov byte [rel ghal_net_matched_kind], 3 + jmp .magic_accepted + +.expected_magic_match: + mov al, [rel ghal_net_command_kind] + cmp al, 3 + jne .store_matched_kind + xor al, al +.store_matched_kind: + mov [rel ghal_net_matched_kind], al + +.magic_accepted: + cmp byte [rel ghal_net_matched_kind], 0 + jne .record_command + mov byte [rel physical_proof_ipv4_rx_verified], 1 + mov eax, [VIRTIO_NET_RX_BUFFER + 36] + mov [rel physical_proof_login_client_ip], eax + mov ax, [VIRTIO_NET_RX_BUFFER + 48] + mov [rel physical_proof_login_icmp_id], ax + mov ax, [VIRTIO_NET_RX_BUFFER + 50] + mov [rel physical_proof_login_icmp_sequence], ax + mov rsi, VIRTIO_NET_RX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET + lea rdi, [rel physical_proof_login_magic] mov ecx, GHOS_LOGIN_MAGIC_SIZE rep movsb - mov rsi, [rel ghal_net_expected_magic] + jmp .build_reply + +.record_command: + cmp byte [rel ghal_net_matched_kind], 1 + jne .record_branch + mov byte [rel physical_proof_code_commit_command_rx], 1 + jmp .build_reply +.record_branch: + cmp byte [rel ghal_net_matched_kind], 2 + jne .record_recovery + mov byte [rel physical_proof_branch_move_command_rx], 1 + jmp .build_reply +.record_recovery: + cmp byte [rel ghal_net_matched_kind], 3 + jne .ignore_packet + mov byte [rel physical_proof_recovery_command_rx], 1 + jmp .build_reply + +.ignore_packet: + inc r8w + jnz .post_receive + mov byte [rel physical_proof_error_code], 0x57 + stc + ret + +.build_reply: + mov rsi, VIRTIO_NET_RX_BUFFER + mov rdi, VIRTIO_NET_TX_BUFFER + mov ecx, r14d + rep movsb + mov qword [VIRTIO_NET_TX_BUFFER], 0 + mov word [VIRTIO_NET_TX_BUFFER + 8], 0 + + xor ecx, ecx +.swap_mac: + cmp ecx, 6 + jae .mac_swapped + mov al, [VIRTIO_NET_TX_BUFFER + 10 + rcx] + mov dl, [VIRTIO_NET_TX_BUFFER + 16 + rcx] + mov [VIRTIO_NET_TX_BUFFER + 10 + rcx], dl + mov [VIRTIO_NET_TX_BUFFER + 16 + rcx], al + inc ecx + jmp .swap_mac +.mac_swapped: + mov eax, [VIRTIO_NET_TX_BUFFER + 36] + mov edx, [VIRTIO_NET_TX_BUFFER + 40] + mov [VIRTIO_NET_TX_BUFFER + 36], edx + mov [VIRTIO_NET_TX_BUFFER + 40], eax + mov byte [VIRTIO_NET_TX_BUFFER + 44], 0 + mov word [VIRTIO_NET_TX_BUFFER + 46], 0 + lea rsi, [rel ghal_native_ack_magic] mov rdi, VIRTIO_NET_TX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET + GHOS_LOGIN_MAGIC_SIZE mov ecx, GHOS_LOGIN_MAGIC_SIZE rep movsb - mov rsi, VIRTIO_NET_TX_BUFFER + 24 - mov ecx, IPV4_HEADER_SIZE - xor ebx, ebx - call ghal_net_checksum - mov [VIRTIO_NET_TX_BUFFER + 34], bx + movzx eax, word [VIRTIO_NET_TX_BUFFER + 26] + xchg al, ah + cmp eax, IPV4_HEADER_SIZE + ICMP_HEADER_SIZE + jb .invalid_packet + sub eax, IPV4_HEADER_SIZE + mov ecx, eax mov rsi, VIRTIO_NET_TX_BUFFER + 44 - mov ecx, ICMP_HEADER_SIZE + 8 + GHOS_LOGIN_MAGIC_SIZE * 2 xor ebx, ebx - call ghal_net_checksum +.checksum_words: + cmp ecx, 2 + jb .checksum_tail + movzx eax, word [rsi] + xchg al, ah + add ebx, eax + add rsi, 2 + sub ecx, 2 + jmp .checksum_words +.checksum_tail: + test ecx, ecx + jz .checksum_fold + movzx eax, byte [rsi] + shl eax, 8 + add ebx, eax +.checksum_fold: + mov eax, ebx + shr eax, 16 + and ebx, 0xffff + add ebx, eax + mov eax, ebx + shr eax, 16 + and ebx, 0xffff + add ebx, eax + not bx + xchg bl, bh mov [VIRTIO_NET_TX_BUFFER + 46], bx mov qword [VIRTIO_NET_TX_QUEUE], VIRTIO_NET_TX_BUFFER - mov dword [VIRTIO_NET_TX_QUEUE + 8], 92 + mov [VIRTIO_NET_TX_QUEUE + 8], r14d mov word [VIRTIO_NET_TX_QUEUE + 12], 0 mov word [VIRTIO_NET_TX_QUEUE + 14], 0 + movzx ecx, word [rel physical_proof_net_tx_queue_size] test ecx, ecx jz .queue_missing @@ -1074,120 +1178,18 @@ ghal_net_icmp_exchange_once: out dx, ax mov ecx, 0x20000000 -.wait_request_tx: +.wait_reply_tx: cmp word [r13 + 2], r11w - je .request_complete + je .reply_complete pause - loop .wait_request_tx + loop .wait_reply_tx mov byte [rel physical_proof_error_code], 0x55 stc ret -.request_complete: - inc word [rel ghal_net_tx_next_index] - - mov ecx, 0x80000000 -.wait_receive: - cmp word [r12 + 2], r8w - je .packet_received - pause - loop .wait_receive -%ifdef GHOS_NATIVE_RESIDENT - jmp .send_request -%else - mov byte [rel physical_proof_error_code], 0x54 - stc - ret -%endif - -.packet_received: - mov eax, r8d - dec eax - mov ecx, r10d - dec ecx - and eax, ecx - shl eax, 3 - mov r14d, [r12 + rax + 8] - cmp r14d, GHOS_LOGIN_MAGIC_OFFSET + GHOS_LOGIN_MAGIC_SIZE * 2 - jb .ignore_packet - cmp word [VIRTIO_NET_RX_BUFFER + 22], 0x0008 - jne .ignore_packet - cmp byte [VIRTIO_NET_RX_BUFFER + 24], 0x45 - jne .ignore_packet - cmp byte [VIRTIO_NET_RX_BUFFER + 33], 1 - jne .ignore_packet - cmp dword [VIRTIO_NET_RX_BUFFER + 36], GHOS_RELAY_IPV4_DWORD - jne .ignore_packet - cmp dword [VIRTIO_NET_RX_BUFFER + 40], GHOS_NATIVE_IPV4_DWORD - jne .ignore_packet - cmp byte [VIRTIO_NET_RX_BUFFER + 44], 0 - jne .ignore_packet - cmp byte [VIRTIO_NET_RX_BUFFER + 45], 0 - jne .ignore_packet - cmp word [VIRTIO_NET_RX_BUFFER + 48], 0x4847 - jne .ignore_packet - cmp byte [VIRTIO_NET_RX_BUFFER + 50], 0 - jne .ignore_packet - mov al, [VIRTIO_NET_RX_BUFFER + 51] - cmp al, [rel ghal_net_expected_sequence] - jne .ignore_packet - mov rsi, VIRTIO_NET_RX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET - mov rdi, [rel ghal_net_expected_magic] - mov ecx, GHOS_LOGIN_MAGIC_SIZE - repe cmpsb - jne .ignore_packet - mov rsi, VIRTIO_NET_RX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET + GHOS_LOGIN_MAGIC_SIZE - lea rdi, [rel ghal_native_ack_magic] - mov ecx, GHOS_LOGIN_MAGIC_SIZE - repe cmpsb - jne .ignore_packet - jmp .expected_magic_match - -.expected_magic_match: - mov al, [rel ghal_net_command_kind] -.store_matched_kind: - mov [rel ghal_net_matched_kind], al - - cmp byte [rel ghal_net_matched_kind], 0 - jne .record_command - mov byte [rel physical_proof_ipv4_rx_verified], 1 - mov eax, [VIRTIO_NET_RX_BUFFER + 36] - mov [rel physical_proof_login_client_ip], eax - mov ax, [VIRTIO_NET_RX_BUFFER + 48] - mov [rel physical_proof_login_icmp_id], ax - mov ax, [VIRTIO_NET_RX_BUFFER + 50] - mov [rel physical_proof_login_icmp_sequence], ax - mov rsi, VIRTIO_NET_RX_BUFFER + GHOS_LOGIN_MAGIC_OFFSET - lea rdi, [rel physical_proof_login_magic] - mov ecx, GHOS_LOGIN_MAGIC_SIZE - rep movsb - jmp .exchange_verified - -.record_command: - cmp byte [rel ghal_net_matched_kind], 1 - jne .record_branch - mov byte [rel physical_proof_code_commit_command_rx], 1 - jmp .exchange_verified -.record_branch: - cmp byte [rel ghal_net_matched_kind], 2 - jne .record_recovery - mov byte [rel physical_proof_branch_move_command_rx], 1 - jmp .exchange_verified -.record_recovery: - cmp byte [rel ghal_net_matched_kind], 3 - jne .ignore_packet - mov byte [rel physical_proof_recovery_command_rx], 1 - jmp .exchange_verified - -.ignore_packet: - inc r8w - jnz .post_receive - mov byte [rel physical_proof_error_code], 0x57 - stc - ret - -.exchange_verified: +.reply_complete: mov [rel ghal_net_rx_next_index], r8w inc word [rel ghal_net_rx_next_index] + inc word [rel ghal_net_tx_next_index] inc byte [rel ghal_net_expected_sequence] cmp byte [rel ghal_net_matched_kind], 0 jne .not_login_reply @@ -1199,39 +1201,13 @@ ghal_net_icmp_exchange_once: call serial_write64 clc ret - .queue_missing: mov byte [rel physical_proof_error_code], 0x53 stc ret - -ghal_net_checksum: -.checksum_words: - cmp ecx, 2 - jb .checksum_tail - movzx eax, word [rsi] - xchg al, ah - add ebx, eax - add rsi, 2 - sub ecx, 2 - jmp .checksum_words -.checksum_tail: - test ecx, ecx - jz .checksum_fold - movzx eax, byte [rsi] - shl eax, 8 - add ebx, eax -.checksum_fold: - mov eax, ebx - shr eax, 16 - and ebx, 0xffff - add ebx, eax - mov eax, ebx - shr eax, 16 - and ebx, 0xffff - add ebx, eax - not bx - xchg bl, bh +.invalid_packet: + mov byte [rel physical_proof_error_code], 0x56 + stc ret ghal_net_io_base: dw 0 diff --git a/product-source/hololake-platform/guanghu-os/scripts/native-layout-nasm-args.sh b/product-source/hololake-platform/guanghu-os/scripts/native-layout-nasm-args.sh index 84bf9bd4f..bacce8f19 100755 --- a/product-source/hololake-platform/guanghu-os/scripts/native-layout-nasm-args.sh +++ b/product-source/hololake-platform/guanghu-os/scripts/native-layout-nasm-args.sh @@ -49,7 +49,6 @@ recovery_beacon_lba=$(native_value recovery_beacon_lba_start) gestational_index_lba=$(native_value gestational_index_lba_start) native_ipv4=$(ipv4_dword "$(network_value native_ipv4)") gateway_ipv4=$(ipv4_dword "$(network_value gateway_ipv4)") -relay_ipv4=$(ipv4_dword "$(network_value relay_ipv4)") for value in \ "${kernel_lba}" "${proof_lba}" "${world_store_lba}" \ @@ -69,5 +68,4 @@ printf '%s\n' \ "-dGHOS_NATIVE_RECOVERY_BEACON_LBA=${recovery_beacon_lba}" \ "-dGHOS_NATIVE_GESTATIONAL_INDEX_LBA=${gestational_index_lba}" \ "-dGHOS_NATIVE_IPV4_DWORD=${native_ipv4}" \ - "-dGHOS_GATEWAY_IPV4_DWORD=${gateway_ipv4}" \ - "-dGHOS_RELAY_IPV4_DWORD=${relay_ipv4}" + "-dGHOS_GATEWAY_IPV4_DWORD=${gateway_ipv4}" diff --git a/product-source/hololake-platform/guanghu-os/scripts/physical-native-icmp-peer.py b/product-source/hololake-platform/guanghu-os/scripts/physical-native-icmp-peer.py index cb6e8257a..484dd58a3 100755 --- a/product-source/hololake-platform/guanghu-os/scripts/physical-native-icmp-peer.py +++ b/product-source/hololake-platform/guanghu-os/scripts/physical-native-icmp-peer.py @@ -53,35 +53,6 @@ def verify_reply(packet: bytes, magic: bytes) -> int: return int.from_bytes(packet[6:8], "big") -def verify_native_request(packet: bytes, pipeline: list[bytes]) -> tuple[int, str]: - if not packet or packet[0] >> 4 != 4: - raise RuntimeError("native request is missing its IPv4 header") - header_length = (packet[0] & 0x0F) * 4 - source = socket.inet_ntoa(packet[12:16]) - icmp = packet[header_length:] - if len(icmp) < 48 or icmp[0] != 8 or icmp[1] != 0: - raise RuntimeError("unexpected native ICMP request shape") - if checksum(icmp) != 0: - raise RuntimeError("native ICMP request checksum failed") - sequence = int.from_bytes(icmp[6:8], "big") - if not 1 <= sequence <= len(pipeline): - raise RuntimeError("native ICMP sequence is outside the pipeline") - magic = pipeline[sequence - 1] - if icmp[16:32] != magic or icmp[32:48] != magic: - raise RuntimeError("native ICMP request magic mismatch") - return sequence, source - - -def native_ack_reply(packet: bytes) -> bytes: - header_length = (packet[0] & 0x0F) * 4 - icmp = bytearray(packet[header_length:]) - icmp[0] = 0 - icmp[2:4] = b"\0\0" - icmp[32:48] = NATIVE_ACK_MAGIC - icmp[2:4] = struct.pack("!H", checksum(bytes(icmp))) - return bytes(icmp) - - def exchange( peer: socket.socket, target: tuple[str, int], @@ -109,7 +80,7 @@ def exchange( def main() -> None: parser = argparse.ArgumentParser() - parser.add_argument("--target") + parser.add_argument("--target", required=True) parser.add_argument("--receipt", required=True) parser.add_argument("--timeout", type=float, default=90.0) parser.add_argument("--retry-interval", type=float, default=1.0) @@ -121,8 +92,6 @@ def main() -> None: parser.add_argument("--resume-after-branch", action="store_true") parser.add_argument("--resume-resident-count", type=int) parser.add_argument("--resident-pipeline", action="store_true") - parser.add_argument("--native-relay", action="store_true") - parser.add_argument("--allowed-source") args = parser.parse_args() if args.retry_interval < 1.0: raise SystemExit("--retry-interval must be at least 1 second") @@ -139,79 +108,19 @@ def main() -> None: args.resume_after_branch, args.resume_resident_count is not None, args.resident_pipeline, - args.native_relay, ) ) > 1: raise SystemExit( "--resident, --login-only, --resume-after-login, and " "--resume-after-commit, --resume-after-branch, and " - "--resume-resident-count, --resident-pipeline, and --native-relay " - "are mutually exclusive" + "--resume-resident-count, and --resident-pipeline are mutually exclusive" ) socket_type = socket.SOCK_RAW if args.raw_socket else socket.SOCK_DGRAM peer = socket.socket(socket.AF_INET, socket_type, socket.IPPROTO_ICMP) - deadline = time.monotonic() + args.timeout - if args.native_relay: - if not args.raw_socket: - raise SystemExit("--native-relay requires --raw-socket") - if not args.allowed_source: - raise SystemExit("--native-relay requires --allowed-source") - allowed_source = socket.gethostbyname(args.allowed_source) - pipeline = [ - LOGIN_MAGIC, - LOGIN_MAGIC, - LOGIN_MAGIC, - COMMIT_MAGIC, - BRANCH_MAGIC, - *([LOGIN_MAGIC] * 10), - RECOVERY_MAGIC, - ] - peer.settimeout(0.5) - acknowledged: set[int] = set() - sources: set[str] = set() - completed_at: float | None = None - while time.monotonic() < deadline and ( - completed_at is None or time.monotonic() < completed_at + 5.0 - ): - try: - packet, address = peer.recvfrom(4096) - sequence, source = verify_native_request(packet, pipeline) - except (TimeoutError, RuntimeError, IndexError): - continue - if source != allowed_source: - continue - peer.sendto(native_ack_reply(packet), address) - acknowledged.add(sequence) - sources.add(source) - if len(acknowledged) == len(pipeline) and completed_at is None: - completed_at = time.monotonic() - if len(acknowledged) != len(pipeline): - raise TimeoutError( - "native relay pipeline incomplete; acknowledged sequences: " - + ",".join(str(item) for item in sorted(acknowledged)) - ) - receipt = pathlib.Path(args.receipt) - receipt.write_text( - "schema: guanghu.physical-native-icmp-relay/v1\n" - "status: PASS_100\n" - "handshake_direction: NATIVE_INITIATED_OUTBOUND_ICMP\n" - "native_ack_marker: HLDP-NATIVE-ACK!\n" - "acknowledged_sequences: 1-16\n" - f"observed_nat_sources: {','.join(sorted(sources))}\n" - "login_reply_count: 3\n" - "code_commit_reply_verified: true\n" - "branch_move_reply_verified: true\n" - "resident_login_reply_count: 10\n" - "recovery_reply_verified: true\n", - encoding="utf-8", - ) - print(receipt.read_text(encoding="utf-8"), end="") - return - if not args.target: - raise SystemExit("--target is required unless --native-relay is used") peer.settimeout(0.2 if args.resident_pipeline else 1.0) target = (socket.gethostbyname(args.target), 0) + deadline = time.monotonic() + args.timeout if args.resident_pipeline: pipeline = [ LOGIN_MAGIC, @@ -228,24 +137,19 @@ def main() -> None: if time.monotonic() >= deadline: break peer.sendto(request(pipeline_sequence, pipeline_magic), target) - receive_until = min(deadline, time.monotonic() + 0.8) - while time.monotonic() < receive_until: - try: - packet, _ = peer.recvfrom(4096) - observed_sequence = reply_sequence_index(packet) - if not 1 <= observed_sequence <= len(pipeline): - raise RuntimeError( - "native ACK sequence is outside the pipeline" - ) - reply_sequence = verify_reply( - packet, - pipeline[observed_sequence - 1], - ) - except (TimeoutError, RuntimeError, IndexError): - continue + try: + packet, _ = peer.recvfrom(4096) + observed_sequence = reply_sequence_index(packet) + if not 1 <= observed_sequence <= len(pipeline): + raise RuntimeError("native ACK sequence is outside the pipeline") + reply_sequence = verify_reply( + packet, + pipeline[observed_sequence - 1], + ) + except (TimeoutError, RuntimeError, IndexError): + continue + if reply_sequence == pipeline_sequence: acknowledged.add(reply_sequence) - if reply_sequence == pipeline_sequence: - break if len(acknowledged) != len(pipeline): raise TimeoutError( "native pipeline incomplete; acknowledged sequences: " diff --git a/product-source/hololake-platform/guanghu-os/scripts/qemu-native-net-peer.py b/product-source/hololake-platform/guanghu-os/scripts/qemu-native-net-peer.py index ade6f980a..03b8fdb51 100644 --- a/product-source/hololake-platform/guanghu-os/scripts/qemu-native-net-peer.py +++ b/product-source/hololake-platform/guanghu-os/scripts/qemu-native-net-peer.py @@ -7,9 +7,9 @@ import time GUEST_MAC = bytes.fromhex("525400267198") PEER_MAC = bytes.fromhex("525400123401") -GUEST_IP = socket.inet_aton("172.16.0.6") -GATEWAY_IP = socket.inet_aton("172.16.0.1") -RELAY_IP = socket.inet_aton("43.153.193.169") +GUEST_IP = socket.inet_aton("10.0.0.7") +PEER_IP = socket.inet_aton("10.0.0.1") +LOGIN_CLIENT_IP = socket.inet_aton("10.0.0.2") LOGIN_MAGIC = b"HLDP-GHOS-LOGIN!" COMMIT_MAGIC = b"HLDP-CODE-COMMIT" BRANCH_MAGIC = b"HLDP-BRANCH-MOVE" @@ -35,65 +35,68 @@ def arp_reply(request: bytes) -> bytes: target_ip = request[38:42] assert sender_mac == GUEST_MAC assert sender_ip == GUEST_IP - assert target_ip == GATEWAY_IP + assert target_ip == PEER_IP return ( sender_mac + PEER_MAC + b"\x08\x06" + b"\x00\x01\x08\x00\x06\x04\x00\x02" + PEER_MAC - + GATEWAY_IP + + PEER_IP + sender_mac + sender_ip ) -def verified_request(frame: bytes, sequence: int, magic: bytes) -> None: +def icmp_request(sequence: int, magic: bytes) -> bytes: + payload = b"\0" * 8 + magic + magic + icmp = struct.pack("!BBHHH", 8, 0, 0, 0x4748, sequence) + payload + icmp = icmp[:2] + struct.pack("!H", checksum(icmp)) + icmp[4:] + total_length = 20 + len(icmp) + ip = struct.pack( + "!BBHHHBBH4s4s", + 0x45, + 0, + total_length, + 0x484C, + 0, + 64, + 1, + 0, + LOGIN_CLIENT_IP, + GUEST_IP, + ) + ip = ip[:10] + struct.pack("!H", checksum(ip)) + ip[12:] + return GUEST_MAC + PEER_MAC + b"\x08\x00" + ip + icmp + + +def validate_reply(frame: bytes, magic: bytes) -> None: assert frame[0:6] == PEER_MAC assert frame[6:12] == GUEST_MAC assert frame[12:14] == b"\x08\x00" assert frame[26:30] == GUEST_IP - assert frame[30:34] == RELAY_IP - assert checksum(frame[14:34]) == 0 - assert frame[34] == 8 - assert frame[35] == 0 - assert frame[38:40] == b"\x47\x48" - assert int.from_bytes(frame[40:42], "big") == sequence + assert frame[30:34] == LOGIN_CLIENT_IP + assert frame[34] == 0 assert frame[50:66] == magic - assert frame[66:82] == magic - assert checksum(frame[34:82]) == 0 - - -def authenticated_reply(frame: bytes, magic: bytes) -> bytes: - reply = bytearray(frame) - reply[0:6] = GUEST_MAC - reply[6:12] = PEER_MAC - reply[26:30] = RELAY_IP - reply[30:34] = GUEST_IP - reply[24:26] = b"\0\0" - reply[24:26] = struct.pack("!H", checksum(bytes(reply[14:34]))) - reply[34] = 0 - reply[36:38] = b"\0\0" - reply[66:82] = NATIVE_ACK_MAGIC - reply[36:38] = struct.pack("!H", checksum(bytes(reply[34:82]))) - return bytes(reply) + assert frame[66:82] == NATIVE_ACK_MAGIC + assert checksum(frame[34:]) == 0 def main() -> None: - global GUEST_IP, GATEWAY_IP, RELAY_IP + global GUEST_IP, PEER_IP, LOGIN_CLIENT_IP parser = argparse.ArgumentParser() parser.add_argument("--listen-port", type=int, required=True) parser.add_argument("--qemu-port", type=int, required=True) parser.add_argument("--receipt", required=True) parser.add_argument("--resident", action="store_true") parser.add_argument("--login-only", action="store_true") - parser.add_argument("--guest-ip", default="172.16.0.6") - parser.add_argument("--peer-ip", default="172.16.0.1") - parser.add_argument("--relay-ip", default="43.153.193.169") + parser.add_argument("--guest-ip", default="10.0.0.7") + parser.add_argument("--peer-ip", default="10.0.0.1") + parser.add_argument("--login-client-ip", default="10.0.0.2") args = parser.parse_args() GUEST_IP = socket.inet_aton(args.guest_ip) - GATEWAY_IP = socket.inet_aton(args.peer_ip) - RELAY_IP = socket.inet_aton(args.relay_ip) + PEER_IP = socket.inet_aton(args.peer_ip) + LOGIN_CLIENT_IP = socket.inet_aton(args.login_client_ip) peer = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) peer.bind(("127.0.0.1", args.listen_port)) @@ -101,63 +104,101 @@ def main() -> None: qemu = ("127.0.0.1", args.qemu_port) deadline = time.monotonic() + 15 arp_verified = False - login_count = 0 - resident_login_count = 0 - commit_verified = False - branch_verified = False - recovery_verified = False + login_sent = False + reply_count = 0 + login_reply_count = 0 + resident_login_reply_count = 0 + recovery_reply_verified = False + command_phase = "login" + + def write_receipt( + *, + commit_verified: bool, + branch_verified: bool, + ) -> None: + with open(args.receipt, "w", encoding="utf-8") as output: + output.write( + "arp_gateway_reply: VERIFIED\n" + f"icmp_login_request_sent: {str(login_sent).lower()}\n" + "icmp_login_reply_verified: true\n" + f"icmp_login_reply_count: {login_reply_count}\n" + "code_commit_reply_verified: " + f"{str(commit_verified).lower()}\n" + "branch_move_reply_verified: " + f"{str(branch_verified).lower()}\n" + f"resident_login_reply_count: {resident_login_reply_count}\n" + "recovery_reply_verified: " + f"{str(recovery_reply_verified).lower()}\n" + "login_magic: HLDP-GHOS-LOGIN!\n" + ) + + def phase_magic() -> bytes: + return { + "login": LOGIN_MAGIC, + "commit": COMMIT_MAGIC, + "branch": BRANCH_MAGIC, + "resident_login": LOGIN_MAGIC, + "recovery": RECOVERY_MAGIC, + }[command_phase] while time.monotonic() < deadline: try: frame = peer.recv(4096) except TimeoutError: + if arp_verified: + peer.sendto( + icmp_request(reply_count + 1, phase_magic()), + qemu, + ) + login_sent = True continue if frame[12:14] == b"\x08\x06": peer.sendto(arp_reply(frame), qemu) arp_verified = True continue - if frame[12:14] != b"\x08\x00": - continue - sequence = int.from_bytes(frame[40:42], "big") - if sequence <= 3: - magic = LOGIN_MAGIC - login_count += 1 - elif sequence == 4: - magic = COMMIT_MAGIC - commit_verified = True - elif sequence == 5: - magic = BRANCH_MAGIC - branch_verified = True - elif 6 <= sequence <= 15: - magic = LOGIN_MAGIC - resident_login_count += 1 - elif sequence == 16: - magic = RECOVERY_MAGIC - recovery_verified = True - else: - raise AssertionError(f"unexpected native sequence {sequence}") - verified_request(frame, sequence, magic) - peer.sendto(authenticated_reply(frame, magic), qemu) - - terminal_sequence = 3 if args.login_only else (16 if args.resident else 5) - if sequence != terminal_sequence: - continue - with open(args.receipt, "w", encoding="utf-8") as output: - output.write( - "arp_gateway_reply: VERIFIED\n" - "handshake_direction: NATIVE_INITIATED_OUTBOUND_ICMP\n" - "authenticated_relay_reply: VERIFIED\n" - "icmp_login_request_sent: true\n" - "icmp_login_reply_verified: true\n" - f"icmp_login_reply_count: {login_count}\n" - f"code_commit_reply_verified: {str(commit_verified).lower()}\n" - f"branch_move_reply_verified: {str(branch_verified).lower()}\n" - f"resident_login_reply_count: {resident_login_count}\n" - f"recovery_reply_verified: {str(recovery_verified).lower()}\n" - "login_magic: HLDP-GHOS-LOGIN!\n" - ) - return - raise SystemExit("timed out waiting for native outbound ICMP exchange") + if frame[12:14] == b"\x08\x00": + magic = phase_magic() + validate_reply(frame, magic) + reply_count += 1 + if command_phase == "login": + login_reply_count += 1 + if command_phase == "login" and reply_count < 3: + peer.sendto(icmp_request(reply_count + 1, LOGIN_MAGIC), qemu) + continue + if command_phase == "login": + if args.login_only: + write_receipt( + commit_verified=False, + branch_verified=False, + ) + return + command_phase = "commit" + peer.sendto(icmp_request(4, COMMIT_MAGIC), qemu) + continue + if command_phase == "commit": + command_phase = "branch" + peer.sendto(icmp_request(5, BRANCH_MAGIC), qemu) + continue + if command_phase == "branch" and args.resident: + command_phase = "resident_login" + peer.sendto(icmp_request(6, LOGIN_MAGIC), qemu) + continue + if command_phase == "resident_login": + resident_login_reply_count += 1 + if resident_login_reply_count < 10: + peer.sendto( + icmp_request(6 + resident_login_reply_count, LOGIN_MAGIC), + qemu, + ) + continue + command_phase = "recovery" + peer.sendto(icmp_request(16, RECOVERY_MAGIC), qemu) + continue + if command_phase == "recovery": + recovery_reply_verified = True + write_receipt(commit_verified=True, branch_verified=True) + return + raise SystemExit("timed out waiting for native ICMP login reply") if __name__ == "__main__": diff --git a/product-source/hololake-platform/guanghu-os/scripts/test-jd-native-resident-candidate.sh b/product-source/hololake-platform/guanghu-os/scripts/test-jd-native-resident-candidate.sh deleted file mode 100755 index c9cee9522..000000000 --- a/product-source/hololake-platform/guanghu-os/scripts/test-jd-native-resident-candidate.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -[[ $# -eq 2 ]] || { - echo "usage: test-jd-native-resident-candidate.sh " >&2 - exit 64 -} - -candidate=$(readlink -f "$1") -receipt=$(readlink -m "$2") -source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) -native_root=${source_root}/native/x86_64-bios -test_root=$(mktemp -d) -peer_pid= -cleanup() { - if [[ -n ${peer_pid} ]]; then - kill "${peer_pid}" 2>/dev/null || true - fi - if [[ ${GHOS_KEEP_TEST_ROOT:-0} != 1 ]]; then - rm -rf "${test_root}" - else - echo "GHOS_TEST_ROOT=${test_root}" >&2 - fi -} -trap cleanup EXIT - -[[ $(stat -c %s "${candidate}") -eq 14848 ]] -truncate -s 700M "${test_root}/disk.img" -nasm -f bin -dCANDIDATE_LBA=105 -dPROOF_LBA=134 \ - "${native_root}/physical-test-mbr.asm" -o "${test_root}/mbr.bin" -dd if="${test_root}/mbr.bin" of="${test_root}/disk.img" \ - bs=512 seek=0 conv=notrunc status=none -dd if="${candidate}" of="${test_root}/disk.img" \ - bs=512 seek=105 conv=notrunc status=none - -peer_port=$((32000 + ${BASHPID:-$$} % 1000)) -qemu_port=$((peer_port + 1)) -python3 "${source_root}/scripts/qemu-native-net-peer.py" \ - --listen-port "${peer_port}" \ - --qemu-port "${qemu_port}" \ - --receipt "${test_root}/peer.hldp" \ - --resident >"${test_root}/peer.log" 2>&1 & -peer_pid=$! -set +e -timeout 35 qemu-system-x86_64 \ - -machine pc,accel=tcg \ - -m 64M \ - -drive "if=none,id=ghboot,format=raw,file=${test_root}/disk.img" \ - -device virtio-blk-pci,drive=ghboot,disable-modern=on,bootindex=0 \ - -netdev "dgram,id=ghnet,local.type=inet,local.host=127.0.0.1,local.port=${qemu_port},remote.type=inet,remote.host=127.0.0.1,remote.port=${peer_port}" \ - -device virtio-net-pci,netdev=ghnet,disable-modern=on,mac=52:54:00:26:71:98 \ - -display none \ - -monitor none \ - -serial "file:${test_root}/serial.log" \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 -qemu_status=$? -set -e -[[ ${qemu_status} -eq 33 ]] -wait "${peer_pid}" -peer_pid= - -grep -q '^handshake_direction: NATIVE_INITIATED_OUTBOUND_ICMP$' \ - "${test_root}/peer.hldp" -grep -q '^authenticated_relay_reply: VERIFIED$' "${test_root}/peer.hldp" -grep -q '^icmp_login_reply_count: 3$' "${test_root}/peer.hldp" -grep -q '^code_commit_reply_verified: true$' "${test_root}/peer.hldp" -grep -q '^branch_move_reply_verified: true$' "${test_root}/peer.hldp" -grep -q '^resident_login_reply_count: 10$' "${test_root}/peer.hldp" -grep -q '^recovery_reply_verified: true$' "${test_root}/peer.hldp" -grep -q '^GHOS_DISK_PROOF_OBSERVED_AFTER_RESET=LBA134' \ - "${test_root}/serial.log" - -python3 - "${test_root}/disk.img" <<'PY' -import pathlib -import sys - -with pathlib.Path(sys.argv[1]).open("rb") as disk: - def sector(lba: int, count: int = 1) -> bytes: - disk.seek(lba * 512) - return disk.read(count * 512) - - proof = sector(134) - assert proof[0] == 0xA7 - assert proof[1:].startswith(b"GHOS_NATIVE_LONG64_DISK_PROOF\0") - assert proof[42:44] == bytes([0x7F, 0]) - assert proof[90] == 13 - assert proof[93:105] == bytes([1] * 12) - assert sector(135).startswith(b"GHOS_HLDP_WORLD_STORE_V1\n") - assert sector(136).startswith(b"GHOS_CODE_CHANNEL_STORE_V1\n") - assert sector(137) == sector(136) - assert b"branch=guanghu/main\n" in sector(138) - assert sector(139, 2).startswith(b"# GRUB Environment Block\n") - assert sector(141).startswith(b"GHOS_GHCIP_INDEX_V1\n") - assert b"GHCIP_PERSONA_STATE=EXISTS\n" in sector(142) -PY - -observed_at=$(date --iso-8601=seconds) -image_sha=$(sha256sum "${candidate}" | awk '{print $1}') -cat >"${receipt}" <