feat: Intel/AMD AVX & MSR sensors, Gigabit PCIe NICs, AHCI SATA, FAT32, and ogit in Ring 3
This commit is contained in:
+62
-27
@@ -1,9 +1,40 @@
|
||||
#include "abi/net.h"
|
||||
#include "rtl8139.h"
|
||||
#include "e1000.h"
|
||||
#include "r8169.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
NIC_TYPE_NONE = 0,
|
||||
NIC_TYPE_E1000,
|
||||
NIC_TYPE_R8169,
|
||||
NIC_TYPE_RTL8139
|
||||
} nic_type_t;
|
||||
|
||||
static nic_type_t s_active_nic = NIC_TYPE_NONE;
|
||||
|
||||
static inline int net_hw_send(const void *packet, size_t length) {
|
||||
if (s_active_nic == NIC_TYPE_E1000) {
|
||||
return e1000_send_packet(packet, length);
|
||||
} else if (s_active_nic == NIC_TYPE_R8169) {
|
||||
return r8169_send_packet(packet, length);
|
||||
} else {
|
||||
return rtl8139_send_packet(packet, length);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int net_hw_poll(void *buffer, size_t max_len) {
|
||||
if (s_active_nic == NIC_TYPE_E1000) {
|
||||
return e1000_receive_packet(buffer, max_len);
|
||||
} else if (s_active_nic == NIC_TYPE_R8169) {
|
||||
return r8169_receive_packet(buffer, max_len);
|
||||
} else {
|
||||
return rtl8139_poll_packet(buffer, max_len);
|
||||
}
|
||||
}
|
||||
|
||||
// Default QEMU User Networking (SLIRP) Configuration
|
||||
// Guest IP: 10.0.2.15
|
||||
// Gateway: 10.0.2.2 (Default QEMU MAC: 52:55:0a:00:02:02)
|
||||
@@ -92,9 +123,16 @@ uint16_t net_tcp_checksum(uint32_t src_ip, uint32_t dst_ip, const tcp_hdr_t *tcp
|
||||
}
|
||||
|
||||
void net_init(void) {
|
||||
rtl8139_init();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
g_net_cfg.mac[i] = g_rtl8139.mac[i];
|
||||
if (e1000_detect_and_init() == 0) {
|
||||
s_active_nic = NIC_TYPE_E1000;
|
||||
for (int i = 0; i < 6; i++) g_net_cfg.mac[i] = g_e1000.mac[i];
|
||||
} else if (r8169_detect_and_init() == 0) {
|
||||
s_active_nic = NIC_TYPE_R8169;
|
||||
for (int i = 0; i < 6; i++) g_net_cfg.mac[i] = g_r8169.mac[i];
|
||||
} else {
|
||||
rtl8139_init();
|
||||
s_active_nic = NIC_TYPE_RTL8139;
|
||||
for (int i = 0; i < 6; i++) g_net_cfg.mac[i] = g_rtl8139.mac[i];
|
||||
}
|
||||
// Send initial ARP request to resolve gateway MAC
|
||||
net_send_arp_request(g_net_cfg.gateway);
|
||||
@@ -119,7 +157,7 @@ int net_send_arp_request(uint32_t target_ip) {
|
||||
memset(arp->target_mac, 0x00, 6);
|
||||
arp->target_ip = target_ip;
|
||||
|
||||
return rtl8139_send_packet(packet, sizeof(eth_hdr_t) + sizeof(arp_hdr_t));
|
||||
return net_hw_send(packet, sizeof(eth_hdr_t) + sizeof(arp_hdr_t));
|
||||
}
|
||||
|
||||
int net_send_icmp_ping(uint32_t target_ip, uint16_t seq) {
|
||||
@@ -155,12 +193,12 @@ int net_send_icmp_ping(uint32_t target_ip, uint16_t seq) {
|
||||
icmp->checksum = 0;
|
||||
icmp->checksum = net_checksum(icmp, 8 + 32);
|
||||
|
||||
return rtl8139_send_packet(packet, sizeof(eth_hdr_t) + 20 + 8 + 32);
|
||||
return net_hw_send(packet, sizeof(eth_hdr_t) + 20 + 8 + 32);
|
||||
}
|
||||
|
||||
int net_poll_icmp_reply(uint32_t *from_ip, uint16_t *seq) {
|
||||
uint8_t buf[1600];
|
||||
int len = rtl8139_poll_packet(buf, sizeof(buf));
|
||||
int len = net_hw_poll(buf, sizeof(buf));
|
||||
if (len < (int)(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(icmp_hdr_t))) {
|
||||
return -1;
|
||||
}
|
||||
@@ -321,27 +359,25 @@ int net_dns_resolve(const char *domain, uint32_t *out_ip) {
|
||||
udp->checksum = 0; // Optional in IPv4 UDP
|
||||
|
||||
// Transmit DNS Query (ensure minimum Ethernet frame size 60 bytes)
|
||||
rtl8139_send_packet(packet, total_packet_len < 60 ? 60 : total_packet_len);
|
||||
net_hw_send(packet, total_packet_len < 60 ? 60 : total_packet_len);
|
||||
|
||||
// Poll for DNS response with realistic WAN timeout (~1.5 seconds)
|
||||
uint8_t rx_buf[1600];
|
||||
for (int retry = 0; retry < 300; retry++) {
|
||||
int rx_len = rtl8139_poll_packet(rx_buf, sizeof(rx_buf));
|
||||
if (rx_len > (int)(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + sizeof(dns_hdr_t))) {
|
||||
eth_hdr_t *rx_eth = (eth_hdr_t *)rx_buf;
|
||||
if (htons(rx_eth->ethertype) == ETHERTYPE_IPv4) {
|
||||
ipv4_hdr_t *rx_ip = (ipv4_hdr_t *)(rx_buf + sizeof(eth_hdr_t));
|
||||
if (rx_ip->protocol == IP_PROTO_UDP) {
|
||||
udp_hdr_t *rx_udp = (udp_hdr_t *)(rx_buf + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t));
|
||||
if (htons(rx_udp->dst_port) == src_port) {
|
||||
uint8_t *resp_dns = rx_buf + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t);
|
||||
// Wait for DNS Response
|
||||
for (int retries = 0; retries < 2000; retries++) {
|
||||
uint8_t rx[512];
|
||||
int rx_len = net_hw_poll(rx, sizeof(rx));
|
||||
if (rx_len > (int)(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + 240)) {
|
||||
ipv4_hdr_t *rx_ip = (ipv4_hdr_t *)(rx + sizeof(eth_hdr_t));
|
||||
if (rx_ip->protocol == IP_PROTO_UDP) {
|
||||
udp_hdr_t *rx_udp = (udp_hdr_t *)(rx + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t));
|
||||
if (htons(rx_udp->dst_port) == 68) {
|
||||
uint8_t *resp_dns = rx + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t);
|
||||
dns_hdr_t *rx_dns_hdr = (dns_hdr_t *)resp_dns;
|
||||
|
||||
if (ntohs(rx_dns_hdr->id) == query_id && (ntohs(rx_dns_hdr->flags) & 0x8000) && ntohs(rx_dns_hdr->ancount) > 0) {
|
||||
// Skip DNS Question section to reach Answer section
|
||||
uint8_t *ptr = resp_dns + sizeof(dns_hdr_t);
|
||||
// Skip QNAME
|
||||
while (*ptr && ptr < rx_buf + rx_len) {
|
||||
while (*ptr && ptr < rx + rx_len) {
|
||||
if ((*ptr & 0xC0) == 0xC0) { ptr += 2; break; } // Compression pointer
|
||||
ptr += (*ptr + 1);
|
||||
}
|
||||
@@ -350,12 +386,12 @@ int net_dns_resolve(const char *domain, uint32_t *out_ip) {
|
||||
|
||||
// Parse Answers
|
||||
int answers = ntohs(rx_dns_hdr->ancount);
|
||||
for (int a = 0; a < answers && ptr < rx_buf + rx_len - 10; a++) {
|
||||
for (int a = 0; a < answers && ptr < rx + rx_len - 10; a++) {
|
||||
// Name: either pointer (0xC0XX) or label
|
||||
if ((*ptr & 0xC0) == 0xC0) {
|
||||
ptr += 2;
|
||||
} else {
|
||||
while (*ptr && ptr < rx_buf + rx_len) ptr += (*ptr + 1);
|
||||
while (*ptr && ptr < rx + rx_len) ptr += (*ptr + 1);
|
||||
if (*ptr == 0) ptr++;
|
||||
}
|
||||
uint16_t a_type = (uint16_t)((ptr[0] << 8) | ptr[1]);
|
||||
@@ -374,7 +410,6 @@ int net_dns_resolve(const char *domain, uint32_t *out_ip) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (volatile int d = 0; d < 20000; d++);
|
||||
}
|
||||
|
||||
@@ -428,12 +463,12 @@ int net_dhcp_discover(void) {
|
||||
dhcp[243] = 55; dhcp[244] = 3; dhcp[245] = 1; dhcp[246] = 3; dhcp[247] = 6;
|
||||
dhcp[248] = 255; // End
|
||||
|
||||
rtl8139_send_packet(packet, sizeof(packet));
|
||||
net_hw_send(packet, sizeof(packet));
|
||||
|
||||
// Listen for DHCP Offer
|
||||
uint8_t rx[1600];
|
||||
for (int retry = 0; retry < 40; retry++) {
|
||||
int rx_len = rtl8139_poll_packet(rx, sizeof(rx));
|
||||
for (int retry = 0; retry < 60; retry++) {
|
||||
int rx_len = net_hw_poll(rx, sizeof(rx));
|
||||
if (rx_len > (int)(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(udp_hdr_t) + 240)) {
|
||||
ipv4_hdr_t *rx_ip = (ipv4_hdr_t *)(rx + sizeof(eth_hdr_t));
|
||||
if (rx_ip->protocol == IP_PROTO_UDP) {
|
||||
@@ -628,7 +663,7 @@ int net_http_get(uint32_t target_ip, uint16_t port, const char *path, const char
|
||||
ip->total_length = htons(sizeof(ipv4_hdr_t) + sizeof(tcp_hdr_t));
|
||||
ip->checksum = 0;
|
||||
ip->checksum = net_checksum(ip, sizeof(ipv4_hdr_t));
|
||||
rtl8139_send_packet(packet, sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(tcp_hdr_t));
|
||||
net_hw_send(packet, sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(tcp_hdr_t));
|
||||
}
|
||||
|
||||
if (rx_tcp->flags & TCP_FLAG_FIN) {
|
||||
|
||||
Reference in New Issue
Block a user