Compare commits
No commits in common. "59713279a0b08dcef801819c29f2883cd24060c6" and "3dc2c24ec566f4cd03be17838f4d02df7c6f9b29" have entirely different histories.
59713279a0
...
3dc2c24ec5
10
README.md
10
README.md
@ -38,11 +38,17 @@ Additionally, the build process needs some extra dependencies to run: `cmake`, `
|
|||||||
|
|
||||||
`tools/run.sh` is the script you should use in most cases. It will build changed files, install, make an ISO image, and run Luna in QEMU.
|
`tools/run.sh` is the script you should use in most cases. It will build changed files, install, make an ISO image, and run Luna in QEMU.
|
||||||
|
|
||||||
If you have no toolchain set up, `run.sh` will build it automatically, which means that you don't necessarily have to run `setup.sh` manually since `run.sh` does it for you.
|
If you have no toolchain set up, `run.sh` will build it automatically, which means that you don't necessarily have to run `setup.sh` since `run.sh` does it for you.
|
||||||
|
|
||||||
## Prebuilt images
|
## Prebuilt images
|
||||||
|
|
||||||
Prebuilt ISO images for every release version can be found at [pub.cloudapio.eu](https://pub.cloudapio.eu/luna/releases).
|
Prebuilt ISO images (numbered) for every version can be found at [pub.cloudapio.eu](https://pub.cloudapio.eu/luna/releases).
|
||||||
|
|
||||||
|
These images are built manually whenever a new release is created, and thus don't reflect the latest changes on the `main` branch.
|
||||||
|
|
||||||
|
Every hour, this server pulls the latest commits on `main` and builds an hourly ISO image. The ten most recent ones can be found in the [hourly](https://pub.cloudapio.eu/luna/hourly) directory, and [Luna-latest.iso](https://pub.cloudapio.eu/luna/Luna-latest.iso) should always be symlinked to the newest one.
|
||||||
|
|
||||||
|
These images do reflect the latest changes on the `main` branch, but are obviously less stable. Additionally, an hourly image will be skipped if building the latest commit of the project fails.
|
||||||
|
|
||||||
## Is there third-party software I can use on Luna?
|
## Is there third-party software I can use on Luna?
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <luna/Format.h>
|
#include <luna/Format.h>
|
||||||
#include <luna/SourceLocation.h>
|
#include <luna/SourceLocation.h>
|
||||||
#include <luna/Spinlock.h>
|
#include <luna/Spinlock.h>
|
||||||
#include <luna/StringBuilder.h>
|
|
||||||
|
|
||||||
static bool g_debug_enabled = true;
|
static bool g_debug_enabled = true;
|
||||||
static bool g_serial_enabled = true;
|
static bool g_serial_enabled = true;
|
||||||
@ -175,23 +174,3 @@ static bool g_check_already_failed = false;
|
|||||||
}
|
}
|
||||||
CPU::efficient_halt();
|
CPU::efficient_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> hexdump(void* data, usize size)
|
|
||||||
{
|
|
||||||
StringBuilder sb;
|
|
||||||
|
|
||||||
u8* ptr = (u8*)data;
|
|
||||||
|
|
||||||
while (size)
|
|
||||||
{
|
|
||||||
TRY(sb.format("%#2x ", *ptr));
|
|
||||||
ptr++;
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto message = TRY(sb.string());
|
|
||||||
|
|
||||||
kdbgln("hexdump: %s", message.chars());
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
@ -26,8 +26,6 @@ void set_text_console_initialized();
|
|||||||
#define kwarnln(...) log(LogLevel::Warn, __VA_ARGS__)
|
#define kwarnln(...) log(LogLevel::Warn, __VA_ARGS__)
|
||||||
#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__)
|
#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__)
|
||||||
|
|
||||||
Result<void> hexdump(void* data, usize size);
|
|
||||||
|
|
||||||
[[noreturn]] extern void __critical_error_handler(SourceLocation location, const char* expr, const char* failmsg,
|
[[noreturn]] extern void __critical_error_handler(SourceLocation location, const char* expr, const char* failmsg,
|
||||||
const char* errmsg);
|
const char* errmsg);
|
||||||
|
|
||||||
|
@ -157,27 +157,13 @@ namespace ATA
|
|||||||
|
|
||||||
void Channel::select(u8 drive)
|
void Channel::select(u8 drive)
|
||||||
{
|
{
|
||||||
|
if (drive == m_current_drive) return;
|
||||||
|
|
||||||
u8 value = (u8)(drive << 4) | 0xa0;
|
u8 value = (u8)(drive << 4) | 0xa0;
|
||||||
if (value == m_current_select_value) return;
|
|
||||||
|
|
||||||
write_register(Register::DriveSelect, value);
|
write_register(Register::DriveSelect, value);
|
||||||
|
|
||||||
delay_400ns();
|
delay_400ns();
|
||||||
|
|
||||||
m_current_select_value = value;
|
|
||||||
m_current_drive = drive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Channel::select(u8 base, u8 drive)
|
|
||||||
{
|
|
||||||
u8 value = (u8)(drive << 4) | base;
|
|
||||||
if (value == m_current_select_value) return;
|
|
||||||
|
|
||||||
write_register(Register::DriveSelect, value);
|
|
||||||
|
|
||||||
delay_400ns();
|
|
||||||
|
|
||||||
m_current_select_value = value;
|
|
||||||
m_current_drive = drive;
|
m_current_drive = drive;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,61 +543,10 @@ namespace ATA
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Drive::select_lba(u64 lba, usize count)
|
Result<void> Drive::send_packet_atapi_pio(const atapi_packet* packet, void* out, u16 response_size)
|
||||||
{
|
|
||||||
if (m_is_lba48)
|
|
||||||
{
|
|
||||||
m_channel->write_register(Register::SectorCount, (u8)((count >> 8) & 0xff));
|
|
||||||
m_channel->write_register(Register::LBALow, (u8)((lba >> 24) & 0xff));
|
|
||||||
m_channel->write_register(Register::LBAMiddle, (u8)((lba >> 32) & 0xff));
|
|
||||||
m_channel->write_register(Register::LBAHigh, (u8)((lba >> 40) & 0xff));
|
|
||||||
}
|
|
||||||
m_channel->write_register(Register::SectorCount, (u8)(count & 0xff));
|
|
||||||
m_channel->write_register(Register::LBALow, (u8)(lba & 0xff));
|
|
||||||
m_channel->write_register(Register::LBAMiddle, (u8)((lba >> 8) & 0xff));
|
|
||||||
m_channel->write_register(Register::LBAHigh, (u8)((lba >> 16) & 0xff));
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> Drive::read_pio_bytes(void* out, usize size)
|
|
||||||
{
|
{
|
||||||
u8* ptr = (u8*)out;
|
u8* ptr = (u8*)out;
|
||||||
|
|
||||||
usize i = 0;
|
|
||||||
|
|
||||||
while (i < size)
|
|
||||||
{
|
|
||||||
TRY(m_channel->wait_until_ready());
|
|
||||||
|
|
||||||
usize byte_count;
|
|
||||||
|
|
||||||
if (m_is_atapi)
|
|
||||||
{
|
|
||||||
byte_count =
|
|
||||||
m_channel->read_register(Register::LBAHigh) << 8 | m_channel->read_register(Register::LBAMiddle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
byte_count = min(512ul, size - i);
|
|
||||||
|
|
||||||
usize word_count = byte_count / 2;
|
|
||||||
|
|
||||||
while (word_count--)
|
|
||||||
{
|
|
||||||
u16 value = m_channel->read_data();
|
|
||||||
ptr[0] = (u8)(value & 0xff);
|
|
||||||
ptr[1] = (u8)(value >> 8);
|
|
||||||
ptr += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
i += byte_count;
|
|
||||||
|
|
||||||
m_channel->delay_400ns();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> Drive::send_packet_atapi_pio(const atapi_packet* packet, void* out, u16 response_size)
|
|
||||||
{
|
|
||||||
m_channel->select(m_drive_index);
|
m_channel->select(m_drive_index);
|
||||||
|
|
||||||
// We use PIO here.
|
// We use PIO here.
|
||||||
@ -624,11 +559,30 @@ namespace ATA
|
|||||||
|
|
||||||
m_channel->delay_400ns();
|
m_channel->delay_400ns();
|
||||||
|
|
||||||
|
usize i = 0;
|
||||||
|
|
||||||
TRY(m_channel->wait_until_ready());
|
TRY(m_channel->wait_until_ready());
|
||||||
|
|
||||||
for (int j = 0; j < 6; j++) m_channel->write_data(packet->command_words[j]);
|
for (int j = 0; j < 6; j++) m_channel->write_data(packet->command_words[j]);
|
||||||
|
|
||||||
TRY(read_pio_bytes(out, response_size));
|
while (i < response_size)
|
||||||
|
{
|
||||||
|
TRY(m_channel->wait_until_ready());
|
||||||
|
|
||||||
|
usize byte_count =
|
||||||
|
m_channel->read_register(Register::LBAHigh) << 8 | m_channel->read_register(Register::LBAMiddle);
|
||||||
|
usize word_count = byte_count / 2;
|
||||||
|
|
||||||
|
while (word_count--)
|
||||||
|
{
|
||||||
|
u16 value = m_channel->read_data();
|
||||||
|
ptr[0] = (u8)(value & 0xff);
|
||||||
|
ptr[1] = (u8)(value >> 8);
|
||||||
|
ptr += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += byte_count;
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -750,26 +704,6 @@ namespace ATA
|
|||||||
return send_packet_atapi_pio(&read_packet, out, (u16)size);
|
return send_packet_atapi_pio(&read_packet, out, (u16)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> Drive::ata_read_pio(u64 lba, void* out, usize size)
|
|
||||||
{
|
|
||||||
check(lba < m_block_count);
|
|
||||||
check(size <= ARCH_PAGE_SIZE);
|
|
||||||
|
|
||||||
usize count = ceil_div(size, m_block_size);
|
|
||||||
|
|
||||||
m_channel->select(m_is_lba48 ? 0x40 : (0xe0 | ((lba >> 24) & 0xf)), m_drive_index);
|
|
||||||
|
|
||||||
select_lba(lba, count);
|
|
||||||
|
|
||||||
m_channel->write_register(Register::Command, m_is_lba48 ? CMD_ReadSectorsExt : CMD_ReadSectors);
|
|
||||||
|
|
||||||
m_channel->delay_400ns();
|
|
||||||
|
|
||||||
TRY(read_pio_bytes(out, size));
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> Drive::read_lba(u64 lba, void* out, usize nblocks)
|
Result<void> Drive::read_lba(u64 lba, void* out, usize nblocks)
|
||||||
{
|
{
|
||||||
const usize blocks_per_page = ARCH_PAGE_SIZE / m_block_size;
|
const usize blocks_per_page = ARCH_PAGE_SIZE / m_block_size;
|
||||||
@ -785,16 +719,7 @@ namespace ATA
|
|||||||
return atapi_read_pio(lba, out, nblocks * m_block_size);
|
return atapi_read_pio(lba, out, nblocks * m_block_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
todo();
|
||||||
while (nblocks > blocks_per_page)
|
|
||||||
{
|
|
||||||
TRY(ata_read_pio(lba, out, ARCH_PAGE_SIZE));
|
|
||||||
lba += blocks_per_page;
|
|
||||||
nblocks -= blocks_per_page;
|
|
||||||
out = offset_ptr(out, ARCH_PAGE_SIZE);
|
|
||||||
}
|
|
||||||
return ata_read_pio(lba, out, nblocks * m_block_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Drive::irq_handler()
|
void Drive::irq_handler()
|
||||||
|
@ -54,8 +54,6 @@ namespace ATA
|
|||||||
|
|
||||||
enum CommandRegister : u8
|
enum CommandRegister : u8
|
||||||
{
|
{
|
||||||
CMD_ReadSectors = 0x20,
|
|
||||||
CMD_ReadSectorsExt = 0x24,
|
|
||||||
CMD_Identify = 0xec,
|
CMD_Identify = 0xec,
|
||||||
CMD_Packet = 0xa0,
|
CMD_Packet = 0xa0,
|
||||||
CMD_Identify_Packet = 0xa1
|
CMD_Identify_Packet = 0xa1
|
||||||
@ -182,11 +180,6 @@ namespace ATA
|
|||||||
|
|
||||||
Result<void> atapi_read_pio(u64 lba, void* out, usize size);
|
Result<void> atapi_read_pio(u64 lba, void* out, usize size);
|
||||||
|
|
||||||
Result<void> ata_read_pio(u64 lba, void* out, usize size);
|
|
||||||
|
|
||||||
void select_lba(u64 lba, usize count);
|
|
||||||
Result<void> read_pio_bytes(void* out, usize size);
|
|
||||||
|
|
||||||
Channel* m_channel;
|
Channel* m_channel;
|
||||||
|
|
||||||
u8 m_drive_index;
|
u8 m_drive_index;
|
||||||
@ -257,7 +250,6 @@ namespace ATA
|
|||||||
}
|
}
|
||||||
|
|
||||||
void select(u8 drive);
|
void select(u8 drive);
|
||||||
void select(u8 base, u8 drive);
|
|
||||||
|
|
||||||
bool initialize();
|
bool initialize();
|
||||||
|
|
||||||
@ -278,7 +270,6 @@ namespace ATA
|
|||||||
bool m_irq_called { false };
|
bool m_irq_called { false };
|
||||||
|
|
||||||
u8 m_current_drive = (u8)-1;
|
u8 m_current_drive = (u8)-1;
|
||||||
u8 m_current_select_value = 0xff;
|
|
||||||
|
|
||||||
Option<Drive> m_drives[2];
|
Option<Drive> m_drives[2];
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user