Chameleon

Chameleon Commit Details

Date:2011-06-25 09:36:44 (7 years 11 months ago)
Author:Azimutz
Commit:1056
Parents: 1055
Message:Since i started messing with saio_types.h and min/max Macros, include <sys/param.h> instead of declaring the Macros (like done in others) and tidy up. Was going to move DEBUG_DISK to disk.c but gave up; that's why the file is "touched".. will finish it later. Changes on klibc are due to the indiscriminate use of "#include libsaio.h" :-/ damn file...
Changes:
M/trunk/i386/modules/klibc/vsnprintf.c
M/trunk/i386/libsaio/saio_types.h
M/trunk/i386/libsaio/disk.c
M/trunk/i386/modules/klibc/vsscanf.c

File differences

trunk/i386/libsaio/disk.c
4444
4545
4646
47
48
49
47
48
49
50
5051
5152
53
54
5255
5356
5457
5558
5659
5760
61
62
63
64
65
66
5867
5968
6069
70
6171
62
63
64
6572
6673
6774
6875
69
7076
7177
78
79
80
7281
73
74
75
7682
7783
7884
79
80
81
82
8385
8486
8587
......
631633
632634
633635
634
635
636
637
638
639
640
641
636
637
638
639
640
641
642
643
644
645
646
647
648
649
642650
643651
644652
......
12561264
12571265
12581266
1259
1267
12601268
12611269
12621270
......
12851293
12861294
12871295
1288
1296
12891297
12901298
12911299
......
15971605
15981606
15991607
1600
1608
1609
16011610
1611
16021612
16031613
16041614
......
16301640
16311641
16321642
1633
1643
16341644
16351645
16361646
......
16751685
16761686
16771687
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
16911701
16921702
16931703
......
17251735
17261736
17271737
1728
1738
17291739
1730
1740
17311741
17321742
17331743
......
19871997
19881998
19891999
1990
19912000
19922001
19932002
* All rights reserved.
*/
/* Copyright 2007 VMware Inc.
"Preboot" ramdisk support added by David Elliott
GPT support added by David Elliott. Based on IOGUIDPartitionScheme.cpp.
/*
* Copyright 2007 VMware Inc.
* "Preboot" ramdisk support added by David Elliott
* GPT support added by David Elliott. Based on IOGUIDPartitionScheme.cpp.
*/
//Azi: style the rest later...
// Allow UFS_SUPPORT to be overridden with preprocessor option.
#ifndef UFS_SUPPORT
// zef: Disabled UFS support
#define UFS_SUPPORT 0
#endif
#if UFS_SUPPORT
#include "ufs.h"
#endif
#include <limits.h>
#include <IOKit/storage/IOApplePartitionScheme.h>
#include <IOKit/storage/IOGUIDPartitionScheme.h>
#include "libsaio.h"
#include "boot.h"
#include "bootstruct.h"
#include "memory.h"
#include "fdisk.h"
#if UFS_SUPPORT
#include "ufs.h"
#endif
#include "hfs.h"
#include "ntfs.h"
#include "msdos.h"
#include "ext2fs.h"
#include "xml.h"
#include "disk.h"
// For EFI_GUID
#include "efi.h"
#include "efi_tables.h"
#include <limits.h>
#include <IOKit/storage/IOApplePartitionScheme.h>
#include <IOKit/storage/IOGUIDPartitionScheme.h>
typedef struct gpt_hdr gpt_hdr;
typedef struct gpt_ent gpt_ent;
// For EFI_GUID
#include "efi.h"
#include "efi_tables.h"
#define PROBEFS_SIZE BPS * 4 /* buffer size for filesystem probe */
#define CD_BPS 2048 /* CD-ROM block size */
#define N_CACHE_SECS (BIOS_LEN / BPS) /* Must be a multiple of 4 for CD-ROMs */
//==========================================================================
// HFS+ GUID in LE form
EFI_GUID const GPT_HFS_GUID= { 0x48465300, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } };
// turbo - also our booter partition
EFI_GUID const GPT_BOOT_GUID= { 0x426F6F74, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } };
// turbo - or an efi system partition
EFI_GUID const GPT_EFISYS_GUID= { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B } };
// zef - basic data partition EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 for foreign OS support
EFI_GUID const GPT_BASICDATA_GUID = { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 } };
// GUID's in LE form:
// HFS+ partition - 48465300-0000-11AA-AA11-00306543ECAC
EFI_GUID const GPT_HFS_GUID = { 0x48465300, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } };
// turbo - Apple Boot Partition - 426F6F74-0000-11AA-AA11-00306543ECAC
EFI_GUID const GPT_BOOT_GUID = { 0x426F6F74, 0x0000, 0x11AA, { 0xAA, 0x11, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC } };
// turbo - or an EFI System Partition - C12A7328-F81F-11D2-BA4B-00A0C93EC93B
EFI_GUID const GPT_EFISYS_GUID = { 0xC12A7328, 0xF81F, 0x11D2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B } };
// zef - Basic Data Partition - EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 for foreign OS support
EFI_GUID const GPT_BASICDATA_GUID = { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 } };
// Microsoft Reserved Partition - E3C9E316-0B5C-4DB8-817DF92DF00215AE
EFI_GUID const GPT_BASICDATA2_GUID = { 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE } };
// NOTE: EFI_GUID's are in LE and we know we're on an x86.
// The IOGUIDPartitionScheme.cpp code uses byte-based UUIDs, we don't.
if(isPartitionUsed(gptMap))
if (isPartitionUsed(gptMap))
{
char stringuuid[100];
efi_guid_unparse_upper((EFI_GUID*)gptMap->ent_type, stringuuid);
kBIOSDevTypeHardDrive, bvrFlags);
}
// zef - foreign OS support
// zef - foreign OS support
if ( (efi_guid_compare(&GPT_BASICDATA_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) ||
(efi_guid_compare(&GPT_BASICDATA2_GUID, (EFI_GUID const*)gptMap->ent_type) == 0) )
{
)
newBVR->visible = true;
/* Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format
/*
* Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format,
* to be able to hide foreign partitions from the boot menu.
*
*/
if ( (newBVR->flags & kBVFlagForeignBoot) )
{
}
}
#if DEBUG
#if DEBUG //Azi: warning - too big for boot-log.. far too big.. i mean HUGE!! :P
for (bvr = chain; bvr; bvr = bvr->next)
{
printf(" bvr: %d, dev: %d, part: %d, flags: %d, vis: %d\n", bvr, bvr->biosdev, bvr->part_no, bvr->flags, bvr->visible);
static const struct NamedValue fdiskTypes[] =
{
{ FDISK_NTFS,"Windows NTFS" },
{ FDISK_DOS12,"Windows FAT12" },
{ FDISK_DOS16B, "Windows FAT16" },
{ FDISK_DOS16S, "Windows FAT16" },
{ FDISK_DOS16SLBA,"Windows FAT16" },
{ FDISK_SMALLFAT32,"Windows FAT32" },
{ FDISK_FAT32,"Windows FAT32" },
{ FDISK_LINUX,"Linux" },
{ FDISK_UFS,"Apple UFS" },
{ FDISK_HFS,"Apple HFS" },
{ FDISK_BOOTER,"Apple Boot/UFS" },
{ 0xCD,"CD-ROM" },
{ 0x00,0 }/* must be last */
{ FDISK_NTFS, "Windows NTFS" },
{ FDISK_DOS12, "Windows FAT12" },
{ FDISK_DOS16B, "Windows FAT16" },
{ FDISK_DOS16S, "Windows FAT16" },
{ FDISK_DOS16SLBA, "Windows FAT16" },
{ FDISK_SMALLFAT32, "Windows FAT32" },
{ FDISK_FAT32, "Windows FAT32" },
{ FDISK_LINUX, "Linux" },
{ FDISK_UFS, "Apple UFS" },
{ FDISK_HFS, "Apple HFS" },
{ FDISK_BOOTER, "Apple Boot/UFS" },
{ 0xCD, "CD-ROM" },
{ 0x00, 0 } /* must be last */
};
//==========================================================================
return false;
}
/* If Rename Partition has defined an alias, then extract it for description purpose
/* If Rename Partition has defined an alias, then extract it for description purpose.
* The format for the rename string is the following:
* hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ...
* hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" "alias"; etc...
*/
bool getVolumeLabelAlias(BVRef bvr, char* str, long strMaxLen)
return 0;
}
int diskIsCDROM(BVRef bvr)
{
struct driveInfo di;
trunk/i386/libsaio/saio_types.h
66
77
88
9
9
1010
1111
1212
......
2828
2929
3030
31
3132
3233
3334
......
4142
4243
4344
44
45
46
45
46
47
4748
4849
4950
50
51
52
53
51
52
53
54
5455
5556
5657
57
58
59
58
59
60
6061
6162
6263
......
6566
6667
6768
68
69
6970
7071
7172
7273
7374
7475
75
76
7677
7778
7879
......
9293
9394
9495
95
96
96
97
9798
9899
99100
100101
101
102
102103
103104
104105
105
106
106
107
107108
108109
109110
110111
111112
112
113
113114
114115
115116
116117
117
118
119
120
121
118
119
120
121
122
122123
123124
124125
125
126
126127
127128
128
129
129130
130131
131132
......
134135
135136
136137
137
138
138
139
139140
140141
141142
142143
143144
144145
145
146
147
148
146
147
148
149
149150
150151
151
152
153
154
155
156
157
158
152
153
154
155
156
157
158
159
159160
160161
161
162
163
162
163
164
164165
165166
166167
167168
168169
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
193194
194195
195196
196
197
198
199
200
201
202
197
198
199
200
201
202
203
203204
204205
205206
206
207
208
209
210
211
207
208
209
210
211
212
212213
213214
214215
215
216
217
218
219
220
216
217
218
219
220
221221
222222
223
224
223
224
225225
226226
227227
228228
229229
230
231
232
233
230
231
232
233
234234
235235
236236
237237
238
238239
239
240
240
241
242
241243
242
244
243245
244246
245
247
246248
247249
248
249
250
250
251
251252
252
253
254253
255
256
254
255
257256
258257
259258
260
261
259
260
262261
263262
264263
* Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 2.0 (the "License"). You may not use this file
* Source License Version 2.0 (the "License").You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
#include <sys/reboot.h>
#include <sys/types.h>
#include <sys/param.h>
#include "bios.h"
#include "nbp_cmd.h"
#include "bootargs.h"
typedef unsigned long entry_t;
typedef struct {
unsigned int sectors:8;
unsigned int heads:8;
unsigned int cylinders:16;
unsigned int sectors:8;
unsigned int heads:8;
unsigned int cylinders:16;
} compact_diskinfo_t;
struct driveParameters {
int cylinders;
int sectors;
int heads;
int totalDrives;
int cylinders;
int sectors;
int heads;
int totalDrives;
};
struct Tag {
long type;
char *string;
long offset;
longtype;
char *string;
longoffset;
struct Tag *tag;
struct Tag *tagNext;
};
typedef struct {
charplist[4096];// buffer for plist
TagPtrdictionary;// buffer for xml dictionary
bool canOverride; // flag to mark a dictionary can be overriden
boolcanOverride;// flag to mark a dictionary can be overriden
} config_file_t;
/*
* BIOS drive information.
*/
struct boot_drive_info {
struct drive_params {
struct drive_params {
unsigned short buf_size;
unsigned short info_flags;
unsigned long phys_cyls;
unsigned char dev_path[8];
unsigned char reserved3;
unsigned char checksum;
} params;
struct drive_dpte {
} params;
struct drive_dpte {
unsigned short io_port_base;
unsigned short control_port_base;
unsigned char head_flags;
unsigned char vendor_info;
unsigned char irq : 4;
unsigned char irq : 4;
unsigned char irq_unused : 4;
unsigned char block_count;
unsigned char dma_channel : 4;
unsigned char dma_type : 4;
unsigned char pio_type : 4;
unsigned char dma_type : 4;
unsigned char pio_type : 4;
unsigned char pio_unused : 4;
unsigned short option_flags;
unsigned short reserved;
unsigned char revision;
unsigned char checksum;
} dpte;
} dpte;
} __attribute__((packed));
typedef struct boot_drive_info boot_drive_info_t;
struct driveInfo {
boot_drive_info_t di;
int uses_ebios;
int no_emulation;
int biosdev;
int valid;
boot_drive_info_t di;
int uses_ebios;
int no_emulation;
int biosdev;
int valid;
};
typedef struct FinderInfo {
unsigned char data[16];
unsigned char data[16];
} FinderInfo;
struct BootVolume;
struct BootVolume;
typedef struct BootVolume * BVRef;
typedef struct BootVolume * CICell;
typedef long (*FSReadFile)(CICell ih, char *filePath, void *base, uint64_t offset, uint64_t length);
typedef long (*FSGetFileBlock)(CICell ih, char *filePath, unsigned long long *firstBlock);
typedef long (*FSGetDirEntry)(CICell ih, char * dirPath, long long * dirIndex,
char ** name, long * flags, long * time,
FinderInfo * finderInfo, long * infoValid);
char ** name, long * flags, long * time,
FinderInfo * finderInfo, long * infoValid);
typedef long (*FSGetUUID)(CICell ih, char *uuidStr);
typedef void (*BVGetDescription)(CICell ih, char * str, long strMaxLen);
// Can be just pointed to free or a special free function
typedef void (*BVFree)(CICell ih);
struct iob {
unsigned int i_flgs; /* see F_* below */
unsigned int i_offset; /* seek byte offset in file */
int i_filesize; /* size of file */
char * i_buf; /* file load address */
unsigned int i_flgs;/* see F_* below */
unsigned int i_offset;/* seek byte offset in file */
int i_filesize;/* size of file */
char * i_buf;/* file load address */
};
#define BPS 512 /* sector size of the device */
#define F_READ 0x1 /* file opened for reading */
#define F_WRITE 0x2 /* file opened for writing */
#define F_ALLOC 0x4 /* buffer allocated */
#define F_FILE 0x8 /* file instead of device */
#define F_NBSF 0x10 /* no bad sector forwarding */
#define F_SSI 0x40 /* set skip sector inhibit */
#define F_MEM 0x80 /* memory instead of file or device */
#define BPS 512/* sector size of the device */
#define F_READ 0x1/* file opened for reading */
#define F_WRITE 0x2/* file opened for writing */
#define F_ALLOC 0x4/* buffer allocated */
#define F_FILE 0x8/* file instead of device */
#define F_NBSF 0x10/* no bad sector forwarding */
#define F_SSI 0x40/* set skip sector inhibit */
#define F_MEM 0x80/* memory instead of file or device */
struct dirstuff {
char * dir_path; /* directory path */
long long dir_index; /* directory entry index */
BVRef dir_bvr; /* volume reference */
char * dir_path;/* directory path */
long long dir_index;/* directory entry index */
BVRef dir_bvr;/* volume reference */
};
#define BVSTRLEN 32
struct BootVolume {
BVRef next; /* list linkage pointer */
int biosdev; /* BIOS device number */
int type; /* device type (floppy, hd, network) */
unsigned int flags; /* attribute flags */
BVGetDescription description; /* BVGetDescription function */
int part_no; /* partition number (1 based) */
unsigned int part_boff; /* partition block offset */
unsigned int part_type; /* partition type */
unsigned int fs_boff; /* 1st block # of next read */
unsigned int fs_byteoff; /* Byte offset for read within block */
FSLoadFile fs_loadfile; /* FSLoadFile function */
FSReadFile fs_readfile; /* FSReadFile function */
FSGetDirEntry fs_getdirentry; /* FSGetDirEntry function */
FSGetFileBlock fs_getfileblock; /* FSGetFileBlock function */
FSGetUUID fs_getuuid; /* FSGetUUID function */
unsigned int bps; /* bytes per sector for this device */
char name[BVSTRLEN]; /* (name of partition) */
char type_name[BVSTRLEN]; /* (type of partition, eg. Apple_HFS) */
BVFree bv_free; /* BVFree function */
uint32_t modTime;
char label[BVSTRLEN]; /* partition volume label */
char altlabel[BVSTRLEN]; /* partition volume label */
bool filtered; /* newFilteredBVChain() will set to TRUE */
bool visible; /* will shown in the device list */
BVRef next; /* list linkage pointer */
int biosdev; /* BIOS device number */
int type; /* device type (floppy, hd, network) */
unsigned int flags; /* attribute flags */
BVGetDescription description; /* BVGetDescription function */
int part_no; /* partition number (1 based) */
unsigned int part_boff; /* partition block offset */
unsigned int part_type; /* partition type */
unsigned int fs_boff; /* 1st block # of next read */
unsigned int fs_byteoff; /* Byte offset for read within block */
FSLoadFile fs_loadfile; /* FSLoadFile function */
FSReadFile fs_readfile; /* FSReadFile function */
FSGetDirEntry fs_getdirentry; /* FSGetDirEntry function */
FSGetFileBlock fs_getfileblock; /* FSGetFileBlock function */
FSGetUUID fs_getuuid; /* FSGetUUID function */
unsigned int bps; /* bytes per sector for this device */
char name[BVSTRLEN]; /* (name of partition) */
char type_name[BVSTRLEN]; /* (type of partition, eg. Apple_HFS) */
BVFree bv_free; /* BVFree function */
uint32_t modTime;
char label[BVSTRLEN]; /* partition volume label */
char altlabel[BVSTRLEN]; /* partition volume label */
bool filtered; /* newFilteredBVChain() will set to TRUE */
bool visible; /* will shown in the device list */
};
enum {
kBVFlagPrimary = 0x01,
kBVFlagNativeBoot = 0x02,
kBVFlagForeignBoot = 0x04,
kBVFlagBootable = 0x08,
kBVFlagEFISystem = 0x10,
kBVFlagBooter = 0x20,
kBVFlagSystemVolume = 0x40
kBVFlagPrimary= 0x01,
kBVFlagNativeBoot= 0x02,
kBVFlagForeignBoot= 0x04,
kBVFlagBootable= 0x08,
kBVFlagEFISystem= 0x10,
kBVFlagBooter= 0x20,
kBVFlagSystemVolume= 0x40
};
enum {
kBIOSDevTypeFloppy = 0x00,
kBIOSDevTypeHardDrive = 0x80,
kBIOSDevTypeNetwork = 0xE0,
kBIOSDevUnitMask = 0x0F,
kBIOSDevTypeMask = 0xF0,
kBIOSDevMask = 0xFF
kBIOSDevTypeFloppy= 0x00,
kBIOSDevTypeHardDrive= 0x80,
kBIOSDevTypeNetwork= 0xE0,
kBIOSDevUnitMask= 0x0F,
kBIOSDevTypeMask= 0xF0,
kBIOSDevMask= 0xFF
};
enum {
kPartitionTypeHFS = 0xAF,
kPartitionTypeHPFS = 0x07,
kPartitionTypeFAT16 = 0x06,
kPartitionTypeFAT32 = 0x0c,
kPartitionTypeEXT3 = 0x83,
kPartitionTypeHFS= 0xAF,
kPartitionTypeHPFS= 0x07,
kPartitionTypeFAT16= 0x06,
kPartitionTypeFAT32= 0x0c,
kPartitionTypeEXT3= 0x83
};
//#define BIOS_DEV_TYPE(d) ((d) & kBIOSDevTypeMask)
#define BIOS_DEV_UNIT(bvr) ((bvr)->biosdev - (bvr)->type)
//#define BIOS_DEV_TYPE(d)((d) & kBIOSDevTypeMask)
#define BIOS_DEV_UNIT(bvr)((bvr)->biosdev - (bvr)->type)
/*
* KernBootStruct device types.
*/
enum {
DEV_SD = 0,
DEV_HD = 1,
DEV_FD = 2,
DEV_EN = 3
DEV_SD = 0,
DEV_HD = 1,
DEV_FD = 2,
DEV_EN = 3
};
/*
* min/max Macros.
* counting and rounding Macros.
*
* Azi: defined on <sys/param.h>, i386/include/IOKit/IOLib.h (min/max, lower case), and others...
*/
* Azi: defined on <sys/param.h>,
*i386/include/IOKit/IOLib.h (min/max), and others...
*
#ifndef MIN
#defineMIN(a,b) ( ((a) < (b)) ? (a) : (b) )
#define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
#endif
#ifndef MAX
#defineMAX(a,b) ( ((a) > (b)) ? (a) : (b) )
#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
#endif
/*Azi: not used
#defineround2(x, m)(((x) + (m / 2)) & ~(m - 1))
#define roundup2(x, m) (((x) + m - 1) & ~(m - 1))
#define round2(x, m)(((x) + (m / 2)) & ~(m - 1))
#define roundup2(x, m)(((x) + m - 1) & ~(m - 1))*/
#define MAKEKERNDEV(t, u, p) MAKEBOOTDEV(t, 0, 0, u, p)*/
enum {
kNetworkDeviceType = kBIOSDevTypeNetwork,
kBlockDeviceType = kBIOSDevTypeHardDrive
kNetworkDeviceType = kBIOSDevTypeNetwork,
kBlockDeviceType = kBIOSDevTypeHardDrive
}; //gBootFileType_t;
enum {
kCursorTypeHidden = 0x0100,
kCursorTypeUnderline = 0x0607
kCursorTypeHidden = 0x0100,
kCursorTypeUnderline = 0x0607
};
#endif /* !__LIBSAIO_SAIO_TYPES_H */
trunk/i386/modules/klibc/vsnprintf.c
55
66
77
8
8
9
10
911
12
1013
1114
1215
* family is built
*/
#include "libsaio.h"
//#include "libsaio.h"
//Azi: "UCHAR_MAX" & "UINT_MAX" redefined error - limits.h is also present in i386/include.
#include "libsa.h"
#include "limits.h"
enum flags {
FL_ZERO= 0x01,/* Zero modifier */
FL_MINUS= 0x02,/* Minus modifier */
trunk/i386/modules/klibc/vsscanf.c
55
66
77
8
8
9
10
911
12
1013
1114
1215
* family is built
*/
#include "libsaio.h"
//#include "libsaio.h"
//Azi: "UCHAR_MAX" & "UINT_MAX" redefined error - limits.h is also present in i386/include.
#include "libsa.h"
#include "limits.h"
extern uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n);
#ifndef LONG_BIT

Archive Download the corresponding diff file

Revision: 1056