Lotus 1-2-3 cho Linux
(lock.cmpxchg8b.com)- Lotus 1-2-3, một phần mềm bảng tính độc quyền 30 năm tuổi, đã được chạy native trên Linux nhờ dữ liệu được phục hồi tình cờ và quá trình hack nhị phân, dù khi nó phát hành thì Linux còn chưa tồn tại
- Việc tìm thấy LPL add-in SDK từng được cho là đã thất lạc cùng Lotus 1-2-3 for UNIX trong các bản sao lưu BBS từ thập niên 1990 đã cho phép build plugin mẫu và phân tích nhị phân UNIX
- Bản phân phối UNIX chứa Intel 80386 COFF object nén tên
123.o, và khoảng 20.000 symbol cùng thông tin debug đã hé lộ cấu trúc bên trong - Việc port không chỉ dừng ở chuyển COFF sang ELF, mà còn phải xử lý khác biệt về system call và ABI của struct giữa Linux và UNIX bằng
coffsyrupvà các hàm wrapper - Hiện tại bản port chạy được mà không crash và có thể sử dụng 100%, nhưng vẫn còn một số vấn đề và phần port terminal driver, nên bản DOS chạy qua mô phỏng hiện vẫn nhìn đẹp hơn
Điểm khởi đầu của việc đưa một ứng dụng độc quyền 30 năm tuổi lên Linux
- Lotus 1-2-3 vẫn là một abandonware 30 năm tuổi, nhưng nhờ nhiều phát hiện và kỹ thuật hack, việc tạo bản port native cho Linux đã trở nên khả thi
- Mục tiêu port là Lotus 1-2-3 R3 cổ điển, dù bản thân Lotus 1-2-3 vẫn còn các bản phát hành cho tới năm 2002
- Dự án này bắt đầu từ công việc duy trì driver lotusdrv, nhằm giúp Lotus 1-2-3 hoạt động tốt trên các hệ thống hiện đại
- API của driver đã được xác định bằng reverse engineering, và các driver hiện có hoạt động tốt trên hệ thống hiện đại
LPL SDK bị thất lạc và các bản sao lưu BBS
- Lotus 1-2-3 được thiết kế để mở rộng bằng plugin, tức add-in, nhưng các add-in phải được viết bằng ngôn ngữ đặc biệt tên LPL
- Trình biên dịch LPL và SDK đã biến mất, và Lotus không phát hành SDK miễn phí mà bán với giá 395 USD
- Một cựu sysop đang lưu giữ bản sao lưu băng từ của hệ thống BBS thập niên 1990 đã giúp khôi phục SDK ở dạng warez
- ADK được phục hồi có thể tải tại 123DADK.ZIP
- Chương trình LPL mẫu được công bố tại modern.pl
- Trong cùng bộ sao lưu BBS đó cũng có một bản warez của Lotus 1-2-3 for UNIX, vốn từ lâu được xem là đã thất lạc
Phân tích image đĩa của Lotus 1-2-3 for UNIX
- Phiên bản UNIX còn lại dưới dạng bộ file TD0 từ
123UNIX1.TD0tới123UNIX5.TD0 - TD0 được xác định là một định dạng image đĩa nén cũ từ thập niên 1980, và được chuyển sang image đĩa raw bằng samdisk
- Trong các image đã chuyển đổi, image đầu tiên là
tar archive, còn các image còn lại là ASCII cpio archive ở định dạng pre-SVR4 hoặc odc - Toàn bộ image đĩa đã được tải lên Internet Archive
- Sau khi giải nén, bên dưới
lotus/123.v10xuất hiện file thực thi, trợ giúp, keymap, dữ liệu driver máy in và video, file mẫu, tài liệu hướng dẫn, v.v.- Tổng thể gồm 35 thư mục và 338 tệp
123.o trở thành manh mối quyết định
- Trong thư mục
sysV386/lib, một file lớn được tìm thấy dưới dạng hai phần123.o.z_1và123.o.z_2 - Sau khi ghép hai phần lại và giải nén,
123.ođược xác nhận là một Intel 80386 COFF object file- object file chưa bị stripped
- 5 section
- symbol offset
0x1efbdc -
19.755 symbol
- kích thước optional header là 28
- File này chứa private symbol và thông tin debug, giúp ích rất nhiều trong việc hiểu cấu trúc nội bộ của Lotus 1-2-3
- Phản hồi từ
alt.folklore.computersnghiêng về khả năng file này không bị đưa vào nhầm - Vì
dlopen()chưa được dùng rộng rãi trên UNIX đầu thập niên 1990, đây nhiều khả năng là một partially linked object để phục vụ mở rộng tính năng và relink lại
Cấu trúc nội bộ lộ ra nhờ thông tin debug
- Phiên bản UNIX gần như là một bản port trực tiếp từ source của bản DOS nên phần lớn vận hành theo cùng cách
- Thông tin debug đi kèm đã giải đáp nhiều câu hỏi về nội bộ Lotus 1-2-3
- Để cải thiện đầu ra đồ họa, tác giả muốn hook vào rasterizer từ driver, nhưng chỉ với tài liệu thì rất khó hiểu được cách nó hoạt động
- Nhờ thông tin debug, tác giả xác định được rasterizer tạo động một chương trình bytecode nhỏ, rồi graphics engine sẽ diễn giải nó
- Sau khi biết các opcode, có thể disassemble và chỉnh sửa chúng trong raster.c để cải thiện đầu ra
Chuyển từ COFF sang ELF
objcopycó thể chuyển COFF object file sang định dạng ELF mà Linux sử dụng123.ođược chuyển thành123elf.obằng lệnhobjcopy -I coff-i386 -O elf32-i386 123.o 123elf.o- Kết quả chuyển đổi được xác nhận là
ELF 32-bit LSB relocatable, Intel 803386, version 1 (SYSV), not stripped - Theo
objdump, thời điểm biên dịch của object file gốc là ngày 8 tháng 9 năm 1990 06:23:50, tức trước khi phiên bản Linux đầu tiên ra đời
Xử lý khác biệt ABI giữa Linux và UNIX
- Vấn đề đầu tiên là Linux và UNIX không dùng giao diện system call tương thích với nhau
- Phiên bản UNIX dùng giao diện
lcall7; ví dụopen()gọi callgate ở dạngcall 0x7:0x0 - Trên Linux, callgate này không được hỗ trợ nên nếu chạy nguyên bản sẽ bị crash
- Linux từng có hỗ trợ tương thích
lcall7vàlcall27, nhưng hiện không còn nữa
- Linux từng có hỗ trợ tương thích
- Mục tiêu là loại bỏ các lời gọi như vậy và định tuyến toàn bộ qua glibc
Relocation và coffsyrup
- Ban đầu tác giả định xóa symbol bằng
objcopy --strip-symbol open, nhưngobjcopytừ chối vìopenđang được dùng trong relocation - Relocatable object file chứa tham chiếu symbol và thông tin relocation để vẫn hoạt động dù được load ở địa chỉ nào
- Muốn xóa symbol thì phải đồng thời sửa cả thông tin relocation đang tham chiếu tới symbol đó
- Vì vậy tác giả đã viết công cụ nhỏ coffsyrup
- Nó có thể xóa cả các symbol COFF mà
objcopytừ chối - Ví dụ, công cụ này tìm và xử lý symbol
opencùng các relocation liên quan
- Nó có thể xóa cả các symbol COFF mà
Các hàm UNIX không tương thích nhị phân
- Nhiều hàm UNIX chuẩn tuy tương thích ở mức source nhưng lại không tương thích ở mức nhị phân
- Ví dụ tiêu biểu là
struct stat- Cùng một đoạn mã C có thể biên dịch được trên nhiều hệ UNIX khác nhau
- Nhưng object file đã biên dịch có thể hỏng trên hệ khác do khác biệt về kích thước
struct stathoặc offset củast_size
- Các hàm chính cần xử lý gồm
stat(),times(),uname(),fcntl(),ioctl(), v.v. - Cách tiếp cận là đổi tên symbol bằng
objcopy, đánh dấu undefined bằngcoffsyrup, rồi viết các hàm wrapper chuyển đổi struct Linux sang struct UNIX termiosđặc biệt là điểm khó lớn, vì chi tiết hành vi giữa các hệ UNIX khác nhau rất tinh vi và không tương thích, khiến việc debug trở nên khó khăn
Kiểm tra license và kết quả chạy
- Sau nhiều lần hack, chương trình đã chạy mà không crash, nhưng sẽ không hoạt động nếu không có license
- Sau khi đặt breakpoint vào
exit(), tác giả xác định symbol nội bộ dùng để kiểm tra license làlic_init() - Phân tích mã bằng IDA cho thấy cơ chế kiểm tra license là tìm file
LICENSE.000, rồi kiểm tra ngày hết hạn, tên người dùng và tên hệ thống bên trong có khớp với giá trị do hệ thống báo cáo hay không - Cuối cùng, Lotus 1-2-3 đã được port sang hệ điều hành mới là Linux
- Trạng thái hiện tại như sau
- chạy không bị crash
-
có thể sử dụng 100%
- vẫn còn một số vấn đề cần tinh chỉnh thêm
- vẫn còn phần port terminal driver
- hiện tại bản DOS chạy trong môi trường mô phỏng vẫn nhìn đẹp hơn, nhưng có thể sửa được
- mã nguồn bản port được công bố trên github
1 bình luận
Ý kiến trên Hacker News
Thật khó tin là họ đã khôi phục được một bản sao warez của SDK từ bản sao lưu băng từ của một hệ thống BBS cũ, rồi còn build được cả plugin mẫu
Làm tôi nhớ đến Why History Needs Software Piracy
Những thiết bị này là phần cứng có thể còn tồn tại sau vài chục năm nữa, nên nếu có một kho lưu trữ tập trung, bền lâu để cả cộng đồng dùng được, vượt ra ngoài mức mỗi hãng tự để trong cloud riêng, thì giá trị công ích sẽ rất lớn
Tôi cũng từng nghĩ đến cách phát hành archive hằng năm, hoặc bán archival Blu-ray trên loại vật lý có thể trụ khoảng 100 năm
Khi đó, xác suất để ai đó có file
.binhiếm cuối cùng cần thiết để cứu firmware bị hỏng của một module Eurorack DSP nền ARM sẽ gần như bằng 1Cha tôi giữ rất nhiều file Lotus 1-2-3 quan trọng trên một laptop phụ chạy Windows cũ, thỉnh thoảng vẫn phải mở ra xem nên tình trạng đó khá đáng lo
Gần đây tôi biết LibreOffice có thể chuyển đổi file Lotus sang ODF/ODS, thậm chí từ dòng lệnh, nên đã viết một script bash đơn giản để chuyển đổi tất cả
Tôi upload hàng loạt các file đã chuyển đổi lên Nextcloud có Collabora, rồi đưa tài khoản và hướng dẫn sử dụng ngắn gọn cho cha; giờ ông có thể xem file online và chúng cũng được đưa vào quy trình backup thông thường của server
Rất cảm ơn những nhà khảo cổ dữ liệu như OP và các contributor của LibreOffice
Tôi nhớ hồi 7 tuổi xin cha mua Nintendo, nhưng thay vào đó ông mua cho một chiếc PC 286 cùng Lotus 1-2-3 và trò phiêu lưu chữ Indiana Jones
Vì thế ngôn ngữ đầu tiên của tôi không phải LISP mà là BASIC, và tôi định đổ mọi thất bại trong đời mình cho bi kịch này; không nhận phản biện
Ngay cả khi lúc đó Spectrum đã bắt đầu thoái trào
Tôi đang làm một việc tương tự, nhưng thêm bước trước tiên chuyển một phần chương trình thành object file
Vì vậy không bị bó buộc chỉ vào các object file còn sót lại, nhưng để chạy được thì cần một mức độ reverse engineering nhất định
Tôi đã làm proof of concept với
aln, linker của Atari Jaguar: tách một file thực thi Linux x86a.outthành object file ELF, rồi né khác biệt ABI để link lại thành file thực thi ELF x86https://forums.atariage.com/topic/354341-porting-the-original-atari-jaguar-sdk-to-elf/
Thú vị ở nhiều khía cạnh
Quá trình chuyển từ binary UNIX sang binary Linux khi không có cả mã nguồn lẫn compiler và ngôn ngữ gốc trông rất hay, đúng chất nội dung HN
Nó cũng nhắc rằng đến năm 2023 Usenet vẫn được dùng cho việc khác ngoài phân phối file rar
Và cũng gợi lại thời văn hóa BBS trước khi Internet phổ cập đã lan tỏa niềm đam mê cùng các bản shareware xuất sắc đến đại chúng
Nhất là khi nhìn xu hướng Twitter và các mạng xã hội khác đang sụp đổ; nhóm Gen Z lớn tuổi cũng mê retro thập niên 80–90 đến mức tải tiếng modem handshake làm nhạc chuông
Đứa cháu 23 tuổi của tôi gần đây cũng làm vậy, và các tác phẩm như American Horror Story hay Stranger Things càng nuôi dưỡng nỗi hoài niệm đó
Câu nói cũ rằng nếu chờ đủ lâu thì mọi thứ sẽ lại thành mốt xem ra đúng
Hồi tháng 5 năm 2022 cũng có một cuộc thảo luận hay
https://news.ycombinator.com/item?id=31455968
https://scenelist.org/ được link trong bài viết tuyệt vời này đúng là quả bom hoài niệm mà sáng nay tôi cần
Rất hợp để du hành ký ức, cực kỳ khuyến nghị
Các liên kết liên quan
Lotus 1-2-3 for Linux - https://news.ycombinator.com/item?id=35807639 - tháng 5/2023, 73 bình luận
Lotus 1-2-3 - https://news.ycombinator.com/item?id=35872758 - tháng 5/2023, 117 bình luận
Lotus 1-2-3 For Linux - https://news.ycombinator.com/item?id=31455968 - tháng 5/2022, 83 bình luận
Lotus 1-2-3 arbitrary resolution - https://news.ycombinator.com/item?id=26316637 - tháng 3/2021, 123 bình luận
Vì đã dùng thử một chút vào năm ngoái nên tôi đã quên hẳn 1-2-3
Binary
123vẫn chạy tốt trên Linux, và việc một phần mềm đã biến mất từ lâu cứ thế hoạt động được là một thành tựu khá đáng nểTôi luôn muốn có thứ như thế này. Vì không dùng nhiều font hay hình ảnh trong bảng tính, bảng tính chạy trên terminal là rất phù hợp
Mừng là cuối cùng nó đã xuất hiện, và hy vọng sẽ được port sang cả Mac và Windows
https://lock.cmpxchg8b.com/spreadsheet.html
Tôi chưa từng dùng, nhưng đáng để xem thử
Ngoài ra Org-Mode của Emacs là một công cụ có thể đào sâu mãi không hết, và cũng có cách dùng các ô bảng org-mode như bảng tính cùng với tính năng
Calccủa Emacshttps://www.youtube.com/watch?v=15aDIvb5LJs
Trông khá mạnh, và đúng chất Emacs là chạy được cả trong terminal lẫn môi trường cửa sổ
scrồi: https://www.unix.com/man-page/linux/1/sc/