读书人

几年前写的小玩意儿: 黑苹果向导工具t

发布时间: 2013-01-19 11:41:36 作者: rapoo

几年前写的小玩意儿: 黑苹果引导工具tboot

若干年前,tpu听说苹果的MacOSX也推出PC版本了,十分兴奋,赶紧下载ISO想试试看。我记得下载的版本是10.4.6吧。然后准备安装。由于硬盘前面都满了,于是找了个扩展分区安装。安装后傻眼了......不启动啊。然后才开始上网看各种文档,这才知道,MacOSX只能安装在主分区。

tpu不甘心啊,找来各种资料研究。darwin本身是开放源代码的,关于引导的文件,都可以找得到。比如chain0, boot0 boot1 boot2等。有了这些原始的资料帮助,再加上tpu很久之前就研究过MBR这些东西,于是就拼凑出了tboot这个东西(tpu's bootloader)。

tboot的原理很简单,在boot0的代码基础上,完善了扩展分区的搜索代码。这样不论系统装在哪个分区上,都可以找得到。找到之后,再加载该分区前面的boot1部分。boot1再解析分区结构,继续加载boot2。boot2完成整个OSX的加载。

boot2运行后,如果你的硬盘有多个分区,会显示一个分区列表,让你选择从哪一个分区启动。默认的选项是第一个分区。但一般OSX所在的分区不是第一个,这样每次启动你必须再手动选择一次,很是麻烦。于是tpu对boot2打了个补丁,让它把OSX所在的分区作为默认分区。这样就方便许多了。

虽然tpu为引导OSX费了这么大的劲,但OSX只在我硬盘上存在几周就消失了。用起来实在是不习惯啊。不过副产品tboot一直有很多网友在用,它确实解决了一些实际的问题,tpu觉得所作的努力还是值得的。听说现在引导工具已经是百花齐放了,比tboot各种先进。不知道tboot是否还能继续引导最新的OSX...

; tboot.s;; Load HFS volume on any partition(main or ext); writen by tpu, base on boot0 source from Darwin;; Set to 1 to enable obscure debug messages.DEBUG                EQU  0; Various constants.kBoot0Segment        EQU  0x0000kBoot0Stack          EQU  0xFFF0        ; boot0 stack pointerkBoot0LoadAddr       EQU  0x7C00        ; boot0 load addresskBoot0RelocAddr      EQU  0xE000        ; boot0 relocated addresskBoot2Sectors        EQU  126           ; sectors to load for boot2kBoot2Address        EQU  0x0000        ; boot2 load addresskBoot2Segment        EQU  0x2000        ; boot2 load segmentkMBRBuffer           EQU  0x1000        ; MBR buffer addresskExtBuffer           EQU  0x1200        ; MBR buffer addresskPartTableOffset     EQU  0x1bekMBRPartTable        EQU  kMBRBuffer + kPartTableOffsetkExtPartTable        EQU  kExtBuffer + kPartTableOffsetkSectorBytes         EQU  512           ; sector size in byteskBootSignature       EQU  0xAA55        ; boot sector signaturekPartCount           EQU  4             ; number of paritions per tablekPartTypeBoot        EQU  0xab          ; boot2 partition typekPartTypeUFS         EQU  0xa8          ; UFS partition typekPartTypeHFS         EQU  0xaf          ; HFS partition typekPartTypeExtDOS      EQU  0x05          ; DOS extended partition typekPartTypeExtWin      EQU  0x0f          ; Windows extended partition typekPartTypeExtLinux    EQU  0x85          ; Linux extended partition typekPartActive         EQU  0x80kDriveNumber         EQU  0x80; Format of fdisk partition entry.; The symbol 'part_size' is automatically defined as an `EQU'; giving the size of the structure.           struc part.bootid:   resb 1      ; bootable or not .head:     resb 1      ; starting head, sector, cylinder.sect:     resb 1      ;.cyl:      resb 1      ;.type:     resb 1      ; partition type.endhead   resb 1      ; ending head, sector, cylinder.endsect:  resb 1      ;.endcyl:   resb 1      ;.lba:      resd 1      ; starting lba.sectors   resd 1      ; size in sectors           endstruc; Macros.%macro DebugCharMacro 1mov   al, %1call  _putc%endmacro%if DEBUG%define putc(x)DebugCharMacro x%else%define putc(x)%endif%macro puts 1mov   si, %1call  put_string%endmacro;--------------------------------------; Start of text segment.SEGMENT .textORG     0xe000                  ; must match kBoot0RelocAddr;--------------------------------------; Boot code is loaded at 0:7C00h.start:; Set up the stack to grow down from kBoot0Segment:kBoot0Stack.; Interrupts should be off while the stack is being manipulated.cli                             ; interrupts offxor     ax, ax                  ; zero axmov     ss, ax                  ; ss <- 0mov     sp, kBoot0Stack         ; sp <- top of stacksti                             ; reenable interruptsmov     es, ax                  ; es <- 0mov     ds, ax                  ; ds <- 0; Relocate boot0 code.mov     si, kBoot0LoadAddr      ; si <- sourcemov     di, kBoot0RelocAddr     ; di <- destinationcld                             ; auto-increment SI and/or DI registersmov     cx, kSectorBytes/2      ; copy 256 wordsrepnz   movsw                   ; repeat string move (word) operation; Code relocated, jump to start_reloc in relocated location.jmp     0:start_reloc;--------------------------------------; Start execution from the relocated location.;start_reloc:.loop_next_drive:; Clear drive flags.xor     eax, eaxmov     [first_part], eax        ; clear EBIOS LBA offsetmov     [this_part], eax%if DEBUGputc('D')mov     al, dlcall    putbputc(' ')%endif; Read MBR sector to memory.mov     al, 1                   ; load one sectormov     bx, kMBRBuffer          ; MBR load addressxor     ecx, ecxcall    loadjc      .next_drivemov     di, kMBRBuffermov     si, kMBRBuffer+kPartTableOffsetcmp     WORD [si + part_size * kPartCount], kBootSignaturejne     .next_drive             ; Signature error; Look for the HFS partition in the MBR partition tablecall    find_boot               ; will not return on success.next_drive:inc     dl                      ; next drive numbertest    dl, 0x4                 ; went through all 4 drives?jz      .loop_next_drive        ; not yet, loop againputs    part_error_str.hang:hltjmp     SHORT .hang;--------------------------------------; Find the HFS partition and load the booter from the partition.;--------------------------------------find_boot:mov     cx, 4                   ; number of partition entries per table.loop_part:push    cxpush    si%if DEBUGmov     al, [si + part.type]call    putbputc(' ')mov     eax, [si + part.lba]call    putdputc(10)putc(13)%endifmov     eax, [si + part.lba]mov     bl, [si + part.type]    ; print partition typecmp     bl, kPartTypeExtLinux   ; Extended Linuxje.ext_checkcmp     bl, kPartTypeExtDOS     ; Extended DOSje.ext_checkcmp     bl, kPartTypeExtWin     ; Extended Windows(95)jne.nonext.ext_check:cmp     di, kMBRBufferjnz     .ext_not_mbrmov     [first_part], eaxxor     eax, eax.ext_not_mbr:mov     [this_part], eax; Read extended partition tablemov     ecx, eaxmov     al, 1                   ; load one sectormov     bx, kExtBuffer          ; extended load addresscall    loadjc      .next_partmov     si, kExtBuffer+kPartTableOffsetcmp     WORD [si + part_size * kPartCount], kBootSignaturejne     .next_part              ; Signature errorpush    dimov     di, kExtBuffercall    find_bootpopdicmp     di, kMBRBufferjnz     .next_partxor     eax, eaxmov     [this_part], eaxmov     [first_part], eax.next_part:pop     sipop     cxadd     si, part_size           ; advance SI to next partition entryloop    .loop_part              ; loop through all partition entries.exit_findret.nonext:cmp     bl, 0je      .next_partcmp     bl, kPartTypeHFSje     .found_partcmp     bl, kPartTypeUFSje     .found_partcmp     bl, kPartTypeBootjne     .next_part.found_part:add     eax, [this_part]mov     ecx, eaxadd     eax, [first_part]mov     [si+part.lba], eax; Found boot partition, read boot sector to memory.mov     bx, kBoot0LoadAddrmov     al, 1call    loadjc      .next_part               ; load error, keep looking?putc("F")cmp     WORD [bx + 510], kBootSignaturejnz     .next_part; patch boot1hmov     eax, [0x7cbb]cmp     eax, 0x20000200jnz     .no_patchmov     eax, 0x00007d40mov     [0x7cbb], eaxpush    simov     si, patch_code_startmov     di, 0x7d40mov     cx, (patch_code_end-patch_code_start)cldrepnzmovsbpop     si.no_patch:; Jump to partition booter. The drive number is already in register DL.; SI is pointing to the modified partition entry.jmp     kBoot0Segment:kBoot0LoadAddr;--------------------------------------; load - Read sectors from a partition using LBA addressing.;--------------------------------------load:pushad                          ; save all registersmov     bp, sp                  ; save current SP;push    DWORD 0               ; offset 12, upper 32-bit LBApush    ds                      ; For sake of saving memory,push    ds                      ; push DS register, which is 0.add     ecx, [first_part]        ; offset 8, lower 32-bit LBApush    ecxpush    es                      ; offset 6, memory segmentpush    bx                      ; offset 4, memory offsetxor     ah, ah                  ; offset 3, must be 0push    ax                      ; offset 2, number of sectorspush    WORD 16                 ; offset 0-1, packet size%if DEBUGputc('L')mov     eax, ecxcall    putdputc(10)putc(13)%endifmov     si, spmov     ah, 0x42int     0x13mov     sp, bp                  ; restore SPpopadret;--------------------------------------; Write a string to the console.;; Arguments:;   DS:SI   pointer to a NULL terminated string.;; Clobber list:;   AX, BX, SI;put_stringmov     bx, 1                   ; BH=0, BL=1 (blue)cld                             ; increment SI after each lodsb call.looplodsb                           ; load a byte from DS:SI into ALcmp     al, 0                   ; Is it a NULL?je      .exit                   ; yes, all donemov     ah, 0xE                 ; INT10 Func 0xEint     0x10                    ; display byte in tty modejmp     short .loop.exitret%if DEBUG; Show a DWORD value.putdror eax, 16call putwror eax, 16; Show a WORD value.putwror ax, 8call putbror ax, 8; Show a BYTE value.putbror al, 4call put_nibbleror al, 4; Show 4 bit value.put_nibblepush eaxand al, 0x0fadd al, 0x30cmp al, 0x39jna .pasciiadd al, 0x07.pasciicall _putcpop eaxret; Show a ASCII character to the console._putcpushamov bx, 1mov ah, 0x0eint 0x10poparet%endif ;DEBUGpatch_code_start:; patch boot2: SelectBootVolumemov     di, 0x39acmov     eax, [es:di]cmp     eax, 0x01a8da45jne     .no_patchmov     al, 2mov     [es:di+3], al.no_patch:; Jump to boot2. The drive number is already in register DL.jmp     kBoot2Segment:kBoot2Address + kSectorBytespatch_code_end:; NULL terminated strings.part_error_str:   db  'No HFS partition found', 10, 13, 0;--------------------------------------; Pad the rest of the 512 byte sized booter with zeroes. The last; two bytes is the mandatory boot sector signature.pad_boottimes 510-($-$$) db 0dw    kBootSignatureABSOLUTE 0xE400; In memory variables.first_part      resd   1   ; starting LBA of the intial extended partition.this_part       resd   1   ; starting LBA of the current extended partition. part_base       resd   1        END


读书人网 >其他相关

热点推荐